tenfourfox/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

220 lines
7.2 KiB
Java

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.mozstumbler.service.stumblerthread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.net.wifi.ScanResult;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.mozstumbler.service.AppGlobals;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageContract;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.StumblerBundle;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellInfo;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellScanner;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.GPSScanner;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.WifiScanner;
public final class Reporter extends BroadcastReceiver {
private static final String LOG_TAG = AppGlobals.makeLogTag(Reporter.class.getSimpleName());
public static final String ACTION_FLUSH_TO_BUNDLE = AppGlobals.ACTION_NAMESPACE + ".FLUSH";
public static final String ACTION_NEW_BUNDLE = AppGlobals.ACTION_NAMESPACE + ".NEW_BUNDLE";
private boolean mIsStarted;
/* The maximum number of Wi-Fi access points in a single observation. */
private static final int MAX_WIFIS_PER_LOCATION = 200;
/* The maximum number of cells in a single observation */
private static final int MAX_CELLS_PER_LOCATION = 50;
private Context mContext;
private int mPhoneType;
private StumblerBundle mBundle;
Reporter() {}
private void resetData() {
mBundle = null;
}
public void flush() {
reportCollectedLocation();
}
void startup(Context context) {
if (mIsStarted) {
return;
}
mContext = context.getApplicationContext();
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
mPhoneType = tm.getPhoneType();
} else {
Log.d(LOG_TAG, "No telephony manager.");
mPhoneType = TelephonyManager.PHONE_TYPE_NONE;
}
mIsStarted = true;
resetData();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiScanner.ACTION_WIFIS_SCANNED);
intentFilter.addAction(CellScanner.ACTION_CELLS_SCANNED);
intentFilter.addAction(GPSScanner.ACTION_GPS_UPDATED);
intentFilter.addAction(ACTION_FLUSH_TO_BUNDLE);
LocalBroadcastManager.getInstance(mContext).registerReceiver(this,
intentFilter);
}
void shutdown() {
if (mContext == null) {
return;
}
mIsStarted = false;
Log.d(LOG_TAG, "shutdown");
flush();
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(this);
}
private void receivedWifiMessage(Intent intent) {
List<ScanResult> results = intent.getParcelableArrayListExtra(WifiScanner.ACTION_WIFIS_SCANNED_ARG_RESULTS);
putWifiResults(results);
}
private void receivedCellMessage(Intent intent) {
List<CellInfo> results = intent.getParcelableArrayListExtra(CellScanner.ACTION_CELLS_SCANNED_ARG_CELLS);
putCellResults(results);
}
private void receivedGpsMessage(Intent intent) {
String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
if (subject.equals(GPSScanner.SUBJECT_NEW_LOCATION)) {
reportCollectedLocation();
Location newPosition = intent.getParcelableExtra(GPSScanner.NEW_LOCATION_ARG_LOCATION);
mBundle = (newPosition != null) ? new StumblerBundle(newPosition, mPhoneType) : mBundle;
}
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case ACTION_FLUSH_TO_BUNDLE:
flush();
return;
case WifiScanner.ACTION_WIFIS_SCANNED:
receivedWifiMessage(intent);
break;
case CellScanner.ACTION_CELLS_SCANNED:
receivedCellMessage(intent);
break;
case GPSScanner.ACTION_GPS_UPDATED:
// Calls reportCollectedLocation, this is the ideal case
receivedGpsMessage(intent);
break;
}
if (mBundle != null &&
(mBundle.getWifiData().size() > MAX_WIFIS_PER_LOCATION ||
mBundle.getCellData().size() > MAX_CELLS_PER_LOCATION)) {
// no gps for a while, have too much data, just bundle it
reportCollectedLocation();
}
}
private void putWifiResults(List<ScanResult> results) {
if (mBundle == null) {
return;
}
Map<String, ScanResult> currentWifiData = mBundle.getWifiData();
for (ScanResult result : results) {
if (currentWifiData.size() > MAX_WIFIS_PER_LOCATION) {
return;
}
String key = result.BSSID;
if (!currentWifiData.containsKey(key)) {
currentWifiData.put(key, result);
}
}
}
private void putCellResults(List<CellInfo> cells) {
if (mBundle == null) {
return;
}
Map<String, CellInfo> currentCellData = mBundle.getCellData();
for (CellInfo result : cells) {
if (currentCellData.size() > MAX_CELLS_PER_LOCATION) {
return;
}
String key = result.getCellIdentity();
if (!currentCellData.containsKey(key)) {
currentCellData.put(key, result);
}
}
}
private void reportCollectedLocation() {
if (mBundle == null) {
return;
}
storeBundleAsJSON(mBundle);
mBundle.wasSent();
}
private void storeBundleAsJSON(StumblerBundle bundle) {
JSONObject mlsObj;
int wifiCount = 0;
int cellCount = 0;
try {
mlsObj = bundle.toMLSJSON();
wifiCount = mlsObj.getInt(DataStorageContract.ReportsColumns.WIFI_COUNT);
cellCount = mlsObj.getInt(DataStorageContract.ReportsColumns.CELL_COUNT);
} catch (JSONException e) {
Log.w(LOG_TAG, "Failed to convert bundle to JSON: " + e);
return;
}
if (AppGlobals.isDebug) {
// PII: do not log the bundle without obfuscating it
Log.d(LOG_TAG, "Received bundle");
}
if (wifiCount + cellCount < 1) {
return;
}
try {
DataStorageManager.getInstance().insert(mlsObj.toString(), wifiCount, cellCount);
} catch (IOException e) {
Log.w(LOG_TAG, e.toString());
}
}
}