diff options
author | Matt A. Tobin <email@mattatobin.com> | 2019-04-23 15:32:23 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2019-04-23 15:32:23 -0400 |
commit | abe80cc31d5a40ebed743085011fbcda0c1a9a10 (patch) | |
tree | fb3762f06b84745b182af281abb107b95a9fcf01 /mobile/android/stumbler/java | |
parent | 63295d0087eb58a6eb34cad324c4c53d1b220491 (diff) | |
download | UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.gz UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.lz UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.xz UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.zip |
Issue #1053 - Drop support Android and remove Fennec - Part 1a: Remove mobile/android
Diffstat (limited to 'mobile/android/stumbler/java')
28 files changed, 0 insertions, 4223 deletions
diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/AppGlobals.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/AppGlobals.java deleted file mode 100644 index 11a3bf4e0..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/AppGlobals.java +++ /dev/null @@ -1,82 +0,0 @@ -/* 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; - -import java.util.concurrent.ConcurrentLinkedQueue; - -public class AppGlobals { - public static final String LOG_PREFIX = "Stumbler_"; - - /* All intent actions start with this string. Only locally broadcasted. */ - public static final String ACTION_NAMESPACE = "org.mozilla.mozstumbler.intent.action"; - - /* Handle this for logging reporter info. */ - public static final String ACTION_GUI_LOG_MESSAGE = AppGlobals.ACTION_NAMESPACE + ".LOG_MESSAGE"; - public static final String ACTION_GUI_LOG_MESSAGE_EXTRA = ACTION_GUI_LOG_MESSAGE + ".MESSAGE"; - - /* Defined here so that the Reporter class can access the time of an Intent in a generic fashion. - * Classes should have their own constant that is assigned to this, for example, - * WifiScanner has ACTION_WIFIS_SCANNED_ARG_TIME = ACTION_ARG_TIME. - * This member definition in the broadcaster makes it clear what the extra Intent args are for that class. */ - public static final String ACTION_ARG_TIME = "time"; - - /* Location constructor requires a named origin, these are created in the app. */ - public static final String LOCATION_ORIGIN_INTERNAL = "internal"; - - public enum ActiveOrPassiveStumbling { ACTIVE_STUMBLING, PASSIVE_STUMBLING } - - /* In passive mode, only scan this many times for each gps. */ - public static final int PASSIVE_MODE_MAX_SCANS_PER_GPS = 3; - - /* These are set on startup. The appVersionName and code are not used in the service-only case. */ - public static String appVersionName = "0.0.0"; - public static int appVersionCode = 0; - public static String appName = "StumblerService"; - public static boolean isDebug; - - /* The log activity will clear this periodically, and display the messages. - * Always null when the stumbler service is used stand-alone. */ - public static volatile ConcurrentLinkedQueue<String> guiLogMessageBuffer; - - public static void guiLogError(String msg) { - guiLogInfo(msg, "red", true); - } - - public static void guiLogInfo(String msg) { - guiLogInfo(msg, "white", false); - } - - public static void guiLogInfo(String msg, String color, boolean isBold) { - if (guiLogMessageBuffer != null) { - if (isBold) { - msg = "<b>" + msg + "</b>"; - } - guiLogMessageBuffer.add("<font color='" + color +"'>" + msg + "</font>"); - } - } - - public static String makeLogTag(String name) { - final int maxLen = 23 - LOG_PREFIX.length(); - if (name.length() > maxLen) { - name = name.substring(name.length() - maxLen, name.length()); - } - return LOG_PREFIX + name; - } - - public static final String ACTION_TEST_SETTING_ENABLED = "stumbler-test-setting-enabled"; - public static final String ACTION_TEST_SETTING_DISABLED = "stumbler-test-setting-disabled"; - - // Histogram values - public static final String TELEMETRY_TIME_BETWEEN_UPLOADS_SEC = "STUMBLER_TIME_BETWEEN_UPLOADS_SEC"; - public static final String TELEMETRY_BYTES_UPLOADED_PER_SEC = "STUMBLER_VOLUME_BYTES_UPLOADED_PER_SEC"; - public static final String TELEMETRY_TIME_BETWEEN_STARTS_SEC = "STUMBLER_TIME_BETWEEN_START_SEC"; - public static final String TELEMETRY_BYTES_PER_UPLOAD = "STUMBLER_UPLOAD_BYTES"; - public static final String TELEMETRY_OBSERVATIONS_PER_UPLOAD = "STUMBLER_UPLOAD_OBSERVATION_COUNT"; - public static final String TELEMETRY_CELLS_PER_UPLOAD = "STUMBLER_UPLOAD_CELL_COUNT"; - public static final String TELEMETRY_WIFIS_PER_UPLOAD = "STUMBLER_UPLOAD_WIFI_AP_COUNT"; - public static final String TELEMETRY_OBSERVATIONS_PER_DAY = "STUMBLER_OBSERVATIONS_PER_DAY"; - public static final String TELEMETRY_TIME_BETWEEN_RECEIVED_LOCATIONS_SEC = "STUMBLER_TIME_BETWEEN_RECEIVED_LOCATIONS_SEC"; -} - diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/Prefs.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/Prefs.java deleted file mode 100644 index fa00f29e9..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/Prefs.java +++ /dev/null @@ -1,205 +0,0 @@ -/* 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; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.SharedPreferences; -import android.location.Location; -import android.os.Build.VERSION; -import android.text.TextUtils; -import android.util.Log; - -public final class Prefs { - private static final String LOG_TAG = AppGlobals.makeLogTag(Prefs.class.getSimpleName()); - private static final String NICKNAME_PREF = "nickname"; - private static final String USER_AGENT_PREF = "user-agent"; - private static final String VALUES_VERSION_PREF = "values_version"; - private static final String WIFI_ONLY = "wifi_only"; - private static final String LAT_PREF = "lat_pref"; - private static final String LON_PREF = "lon_pref"; - private static final String GEOFENCE_HERE = "geofence_here"; - private static final String GEOFENCE_SWITCH = "geofence_switch"; - private static final String FIREFOX_SCAN_ENABLED = "firefox_scan_on"; - private static final String MOZ_API_KEY = "moz_api_key"; - private static final String WIFI_SCAN_ALWAYS = "wifi_scan_always"; - private static final String LAST_ATTEMPTED_UPLOAD_TIME = "last_attempted_upload_time"; - // Public for MozStumbler to use for manual upgrade of old prefs. - public static final String PREFS_FILE = Prefs.class.getSimpleName(); - - private final SharedPreferences mSharedPrefs; - static private Prefs sInstance; - - private Prefs(Context context) { - mSharedPrefs = context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE); - if (getPrefs().getInt(VALUES_VERSION_PREF, -1) != AppGlobals.appVersionCode) { - Log.i(LOG_TAG, "Version of the application has changed. Updating default values."); - // Remove old keys - getPrefs().edit() - .remove("reports") - .remove("power_saving_mode") - .commit(); - - getPrefs().edit().putInt(VALUES_VERSION_PREF, AppGlobals.appVersionCode).commit(); - getPrefs().edit().commit(); - } - } - - public static Prefs getInstance(Context c) { - if (sInstance == null) { - sInstance = new Prefs(c); - } - return sInstance; - } - - // Allows code without a context handle to grab the prefs. The caller must null check the return value. - public static Prefs getInstanceWithoutContext() { - return sInstance; - } - - /// - /// Setters - /// - public synchronized void setUserAgent(String userAgent) { - setStringPref(USER_AGENT_PREF, userAgent); - } - - public synchronized void setUseWifiOnly(boolean state) { - setBoolPref(WIFI_ONLY, state); - } - - public synchronized void setGeofenceEnabled(boolean state) { - setBoolPref(GEOFENCE_SWITCH, state); - } - - public synchronized void setGeofenceHere(boolean flag) { - setBoolPref(GEOFENCE_HERE, flag); - } - - public synchronized void setGeofenceLocation(Location location) { - SharedPreferences.Editor editor = getPrefs().edit(); - editor.putFloat(LAT_PREF, (float) location.getLatitude()); - editor.putFloat(LON_PREF, (float) location.getLongitude()); - apply(editor); - } - - public synchronized void setMozApiKey(String s) { - setStringPref(MOZ_API_KEY, s); - } - - /// - /// Getters - /// - public synchronized String getUserAgent() { - String s = getStringPref(USER_AGENT_PREF); - return (s == null)? AppGlobals.appName + "/" + AppGlobals.appVersionName : s; - } - - public synchronized boolean getFirefoxScanEnabled() { - return getBoolPrefWithDefault(FIREFOX_SCAN_ENABLED, false); - } - - public synchronized String getMozApiKey() { - String s = getStringPref(MOZ_API_KEY); - return (s == null)? "no-mozilla-api-key" : s; - } - - public synchronized boolean getGeofenceEnabled() { - return getBoolPrefWithDefault(GEOFENCE_SWITCH, false); - } - - public synchronized boolean getGeofenceHere() { - return getBoolPrefWithDefault(GEOFENCE_HERE, false); - } - - public synchronized Location getGeofenceLocation() { - Location loc = new Location(AppGlobals.LOCATION_ORIGIN_INTERNAL); - loc.setLatitude(getPrefs().getFloat(LAT_PREF, 0)); - loc.setLongitude(getPrefs().getFloat(LON_PREF,0)); - return loc; - } - - // This is the time an upload was last attempted, not necessarily successful. - // Used to ensure upload attempts aren't happening too frequently. - public synchronized long getLastAttemptedUploadTime() { - return getPrefs().getLong(LAST_ATTEMPTED_UPLOAD_TIME, 0); - } - - public synchronized String getNickname() { - String nickname = getStringPref(NICKNAME_PREF); - if (nickname != null) { - nickname = nickname.trim(); - } - return TextUtils.isEmpty(nickname) ? null : nickname; - } - - public synchronized void setFirefoxScanEnabled(boolean on) { - setBoolPref(FIREFOX_SCAN_ENABLED, on); - } - - public synchronized void setLastAttemptedUploadTime(long time) { - SharedPreferences.Editor editor = getPrefs().edit(); - editor.putLong(LAST_ATTEMPTED_UPLOAD_TIME, time); - apply(editor); - } - - public synchronized void setNickname(String nick) { - if (nick != null) { - nick = nick.trim(); - if (nick.length() > 0) { - setStringPref(NICKNAME_PREF, nick); - } - } - } - - public synchronized boolean getUseWifiOnly() { - return getBoolPrefWithDefault(WIFI_ONLY, true); - } - - public synchronized boolean getWifiScanAlways() { - return getBoolPrefWithDefault(WIFI_SCAN_ALWAYS, false); - } - - public synchronized void setWifiScanAlways(boolean b) { - setBoolPref(WIFI_SCAN_ALWAYS, b); - } - - /// - /// Privates - /// - - private String getStringPref(String key) { - return getPrefs().getString(key, null); - } - - private boolean getBoolPrefWithDefault(String key, boolean def) { - return getPrefs().getBoolean(key, def); - } - - private void setBoolPref(String key, Boolean state) { - SharedPreferences.Editor editor = getPrefs().edit(); - editor.putBoolean(key,state); - apply(editor); - } - - private void setStringPref(String key, String value) { - SharedPreferences.Editor editor = getPrefs().edit(); - editor.putString(key, value); - apply(editor); - } - - @TargetApi(9) - private static void apply(SharedPreferences.Editor editor) { - if (VERSION.SDK_INT >= 9) { - editor.apply(); - } else if (!editor.commit()) { - Log.e(LOG_TAG, "", new IllegalStateException("commit() failed?!")); - } - } - - private SharedPreferences getPrefs() { - return mSharedPrefs; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/LocalPreferenceReceiver.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/LocalPreferenceReceiver.java deleted file mode 100644 index 388abba15..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/LocalPreferenceReceiver.java +++ /dev/null @@ -1,70 +0,0 @@ -/* 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.mainthread; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.stumblerthread.StumblerService; - -/** - * Starts the StumblerService, an Intent service, which by definition runs on its own thread. - * Registered as a local broadcast receiver in SafeReceiver. - * Starts the StumblerService in passive listening mode. - * - * The received intent contains enabled state, upload API key and user agent, - * and is used to initialize the StumblerService. - */ -public class LocalPreferenceReceiver extends BroadcastReceiver { - // This allows global debugging logs to be enabled by doing - // |adb shell setprop log.tag.PassiveStumbler DEBUG| - static final String LOG_TAG = "PassiveStumbler"; - - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null) { - return; - } - - // This value is cached, so if |setprop| is performed (as described on the LOG_TAG above), - // then the start/stop intent must be resent by toggling the setting or stopping/starting Fennec. - // This does not guard against dumping PII (PII in stumbler is location, wifi BSSID, cell tower details). - AppGlobals.isDebug = Log.isLoggable(LOG_TAG, Log.DEBUG); - - StumblerService.sFirefoxStumblingEnabled.set(intent.getBooleanExtra("enabled", false)); - - if (!StumblerService.sFirefoxStumblingEnabled.get()) { - Log.d(LOG_TAG, "Stopping StumblerService | isDebug:" + AppGlobals.isDebug); - // This calls the service's onDestroy(), and the service's onHandleIntent(...) is not called - context.stopService(new Intent(context, StumblerService.class)); - // For testing service messages were received - context.sendBroadcast(new Intent(AppGlobals.ACTION_TEST_SETTING_DISABLED)); - return; - } - - // For testing service messages were received - context.sendBroadcast(new Intent(AppGlobals.ACTION_TEST_SETTING_ENABLED)); - - Log.d(LOG_TAG, "Sending passive start message | isDebug:" + AppGlobals.isDebug); - - final Intent startServiceIntent = new Intent(context, StumblerService.class); - - startServiceIntent.putExtra(StumblerService.ACTION_START_PASSIVE, true); - startServiceIntent.putExtra( - StumblerService.ACTION_EXTRA_MOZ_API_KEY, - intent.getStringExtra("moz_mozilla_api_key") - ); - startServiceIntent.putExtra( - StumblerService.ACTION_EXTRA_USER_AGENT, - intent.getStringExtra("user_agent") - ); - - context.startService(startServiceIntent); - } -} - diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SafeReceiver.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SafeReceiver.java deleted file mode 100644 index e145dbb0f..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SafeReceiver.java +++ /dev/null @@ -1,43 +0,0 @@ -/* 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.mainthread; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -/** - * Responsible for registering LocalPreferenceReceiver as a receiver with LocalBroadcastManager. - * This receiver is registered in the AndroidManifest.xml - */ -public class SafeReceiver extends BroadcastReceiver { - static final String LOG_TAG = "StumblerSafeReceiver"; - static final String PREFERENCE_INTENT_FILTER = "STUMBLER_PREF"; - - private boolean registeredLocalReceiver = false; - - @Override - public synchronized void onReceive(Context context, Intent intent) { - if (intent == null) { - return; - } - - if (registeredLocalReceiver) { - return; - } - - LocalBroadcastManager.getInstance(context).registerReceiver( - new LocalPreferenceReceiver(), - new IntentFilter(PREFERENCE_INTENT_FILTER) - ); - - Log.d(LOG_TAG, "Registered local preference listener"); - - registeredLocalReceiver = true; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SystemReceiver.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SystemReceiver.java deleted file mode 100644 index eaaab3423..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/mainthread/SystemReceiver.java +++ /dev/null @@ -1,41 +0,0 @@ -/* 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.mainthread; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; -import android.util.Log; - -import org.mozilla.mozstumbler.service.stumblerthread.StumblerService; - -/** - * Responsible for starting StumblerService in response to - * BOOT_COMPLETE and EXTERNAL_APPLICATIONS_AVAILABLE system intents. - */ -public class SystemReceiver extends BroadcastReceiver { - static final String LOG_TAG = "StumblerSystemReceiver"; - - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null) { - return; - } - - final String action = intent.getAction(); - - if (!TextUtils.equals(action, Intent.ACTION_BOOT_COMPLETED) && !TextUtils.equals(action, Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE)) { - // This is not the broadcast you are looking for. - return; - } - - final Intent startServiceIntent = new Intent(context, StumblerService.class); - startServiceIntent.putExtra(StumblerService.ACTION_NOT_FROM_HOST_APP, true); - context.startService(startServiceIntent); - - Log.d(LOG_TAG, "Responded to a system intent"); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java deleted file mode 100644 index 8f7f19c8d..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java +++ /dev/null @@ -1,219 +0,0 @@ -/* 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 (GPSScanner.SUBJECT_NEW_LOCATION.equals(subject)) { - 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()); - } - } -} - diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java deleted file mode 100644 index 5d1a278b9..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java +++ /dev/null @@ -1,254 +0,0 @@ -/* 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.Manifest; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.location.Location; -import android.os.AsyncTask; -import android.support.v4.content.ContextCompat; -import android.util.Log; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.Prefs; -import org.mozilla.mozstumbler.service.stumblerthread.blocklist.WifiBlockListInterface; -import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager; -import org.mozilla.mozstumbler.service.stumblerthread.scanners.ScanManager; -import org.mozilla.mozstumbler.service.uploadthread.UploadAlarmReceiver; -import org.mozilla.mozstumbler.service.utils.PersistentIntentService; - -// In stand-alone service mode (a.k.a passive scanning mode), this is created from PassiveServiceReceiver (by calling startService). -// The StumblerService is a sticky unbound service in this usage. -// -public class StumblerService extends PersistentIntentService - implements DataStorageManager.StorageIsEmptyTracker { - private static final String LOG_TAG = AppGlobals.makeLogTag(StumblerService.class.getSimpleName()); - public static final String ACTION_BASE = AppGlobals.ACTION_NAMESPACE; - public static final String ACTION_START_PASSIVE = ACTION_BASE + ".START_PASSIVE"; - public static final String ACTION_EXTRA_MOZ_API_KEY = ACTION_BASE + ".MOZKEY"; - public static final String ACTION_EXTRA_USER_AGENT = ACTION_BASE + ".USER_AGENT"; - public static final String ACTION_NOT_FROM_HOST_APP = ACTION_BASE + ".NOT_FROM_HOST"; - public static final AtomicBoolean sFirefoxStumblingEnabled = new AtomicBoolean(); - protected final ScanManager mScanManager = new ScanManager(); - protected final Reporter mReporter = new Reporter(); - - // This is a delay before the single-shot upload is attempted. The number is arbitrary - // and used to avoid startup tasks bunching up. - private static final int DELAY_IN_SEC_BEFORE_STARTING_UPLOAD_IN_PASSIVE_MODE = 2; - - // This is the frequency of the repeating upload alarm in active scanning mode. - private static final int FREQUENCY_IN_SEC_OF_UPLOAD_IN_ACTIVE_MODE = 5 * 60; - - // Used to guard against attempting to upload too frequently in passive mode. - private static final long PASSIVE_UPLOAD_FREQ_GUARD_MSEC = 5 * 60 * 1000; - - public StumblerService() { - this("StumblerService"); - } - - public StumblerService(String name) { - super(name); - } - - public boolean isScanning() { - return mScanManager.isScanning(); - } - - public void startScanning() { - mScanManager.startScanning(this); - } - - // This is optional, not used in Fennec, and is for clients to specify a (potentially long) list - // of blocklisted SSIDs/BSSIDs - public void setWifiBlockList(WifiBlockListInterface list) { - mScanManager.setWifiBlockList(list); - } - - public Prefs getPrefs(Context c) { - return Prefs.getInstance(c); - } - - public void checkPrefs() { - mScanManager.checkPrefs(); - } - - public int getLocationCount() { - return mScanManager.getLocationCount(); - } - - public double getLatitude() { - return mScanManager.getLatitude(); - } - - public double getLongitude() { - return mScanManager.getLongitude(); - } - - public Location getLocation() { - return mScanManager.getLocation(); - } - - public int getWifiStatus() { - return mScanManager.getWifiStatus(); - } - - public int getAPCount() { - return mScanManager.getAPCount(); - } - - public int getVisibleAPCount() { - return mScanManager.getVisibleAPCount(); - } - - public int getCellInfoCount() { - return mScanManager.getCellInfoCount(); - } - - public boolean isGeofenced () { - return mScanManager.isGeofenced(); - } - - // Previously this was done in onCreate(). Moved out of that so that in the passive standalone service - // use (i.e. Fennec), init() can be called from this class's dedicated thread. - // Safe to call more than once, ensure added code complies with that intent. - protected void init() { - // Ensure Prefs is created, so internal utility code can use getInstanceWithoutContext - Prefs.getInstance(this); - DataStorageManager.createGlobalInstance(this, this); - - mReporter.startup(this); - } - - // Called from the main thread. - @Override - public void onCreate() { - super.onCreate(); - setIntentRedelivery(true); - } - - // Called from the main thread - @Override - public void onDestroy() { - super.onDestroy(); - - if (!mScanManager.isScanning()) { - return; - } - - // Used to move these disk I/O ops off the calling thread. The current operations here are synchronized, - // however instead of creating another thread (if onDestroy grew to have concurrency complications) - // we could be messaging the stumbler thread to perform a shutdown function. - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "onDestroy"); - } - - if (!sFirefoxStumblingEnabled.get()) { - Prefs.getInstance(StumblerService.this).setFirefoxScanEnabled(false); - } - - if (DataStorageManager.getInstance() != null) { - try { - DataStorageManager.getInstance().saveCurrentReportsToDisk(); - } catch (IOException ex) { - AppGlobals.guiLogInfo(ex.toString()); - Log.e(LOG_TAG, "Exception in onDestroy saving reports" + ex.toString()); - } - } - return null; - } - }.execute(); - - mReporter.shutdown(); - mScanManager.stopScanning(); - } - - // This is the entry point for the stumbler thread. - @Override - protected void onHandleIntent(Intent intent) { - // Do init() in all cases, there is no cost, whereas it is easy to add code that depends on this. - init(); - - // Post-init(), set the mode to passive. - mScanManager.setPassiveMode(true); - - if (!hasLocationPermission()) { - Log.d(LOG_TAG, "Location permission not granted. Aborting."); - return; - } - - if (intent == null) { - return; - } - - final boolean isScanEnabledInPrefs = Prefs.getInstance(this).getFirefoxScanEnabled(); - - if (!isScanEnabledInPrefs && intent.getBooleanExtra(ACTION_NOT_FROM_HOST_APP, false)) { - stopSelf(); - return; - } - - boolean hasFilesWaiting = !DataStorageManager.getInstance().isDirEmpty(); - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "Files waiting:" + hasFilesWaiting); - } - if (hasFilesWaiting) { - // non-empty on startup, schedule an upload - // This is the only upload trigger in Firefox mode - // Firefox triggers this ~4 seconds after startup (after Gecko is loaded), add a small delay to avoid - // clustering with other operations that are triggered at this time. - final long lastAttemptedTime = Prefs.getInstance(this).getLastAttemptedUploadTime(); - final long timeNow = System.currentTimeMillis(); - - if (timeNow - lastAttemptedTime < PASSIVE_UPLOAD_FREQ_GUARD_MSEC) { - // TODO Consider telemetry to track this. - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "Upload attempt too frequent."); - } - } else { - Prefs.getInstance(this).setLastAttemptedUploadTime(timeNow); - UploadAlarmReceiver.scheduleAlarm(this, DELAY_IN_SEC_BEFORE_STARTING_UPLOAD_IN_PASSIVE_MODE, false /* no repeat*/); - } - } - - if (!isScanEnabledInPrefs) { - Prefs.getInstance(this).setFirefoxScanEnabled(true); - } - - String apiKey = intent.getStringExtra(ACTION_EXTRA_MOZ_API_KEY); - if (apiKey != null && !apiKey.equals(Prefs.getInstance(this).getMozApiKey())) { - Prefs.getInstance(this).setMozApiKey(apiKey); - } - - String userAgent = intent.getStringExtra(ACTION_EXTRA_USER_AGENT); - if (userAgent != null && !userAgent.equals(Prefs.getInstance(this).getUserAgent())) { - Prefs.getInstance(this).setUserAgent(userAgent); - } - - if (!mScanManager.isScanning()) { - startScanning(); - } - } - - // Note that in passive mode, having data isn't an upload trigger, it is triggered by the start intent - @Override - public void notifyStorageStateEmpty(boolean isEmpty) { - if (isEmpty) { - UploadAlarmReceiver.cancelAlarm(this, !mScanManager.isPassiveMode()); - } else if (!mScanManager.isPassiveMode()) { - UploadAlarmReceiver.scheduleAlarm(this, FREQUENCY_IN_SEC_OF_UPLOAD_IN_ACTIVE_MODE, true /* repeating */); - } - } - - private boolean hasLocationPermission() { - return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/BSSIDBlockList.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/BSSIDBlockList.java deleted file mode 100644 index 6354cb0cc..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/BSSIDBlockList.java +++ /dev/null @@ -1,65 +0,0 @@ -/* 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.blocklist; - -import android.net.wifi.ScanResult; -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; -import java.util.Locale; -import java.util.regex.Pattern; - -public final class BSSIDBlockList { - private static final String LOG_TAG = AppGlobals.makeLogTag(BSSIDBlockList.class.getSimpleName()); - private static final String NULL_BSSID = "000000000000"; - private static final String WILDCARD_BSSID = "ffffffffffff"; - private static final Pattern BSSID_PATTERN = Pattern.compile("([0-9a-f]{12})"); - private static String[] sOuiList = new String[]{}; - - private BSSIDBlockList() { - } - - public static void setFilterList(String[] list) { - sOuiList = list; - } - - public static boolean contains(ScanResult scanResult) { - String BSSID = scanResult.BSSID; - if (BSSID == null || NULL_BSSID.equals(BSSID) || WILDCARD_BSSID.equals(BSSID)) { - return true; // blocked! - } - - if (!isCanonicalBSSID(BSSID)) { - Log.w(LOG_TAG, "", new IllegalArgumentException("Unexpected BSSID format: " + BSSID)); - return true; // blocked! - } - - for (String oui : sOuiList) { - if (BSSID.startsWith(oui)) { - return true; // blocked! - } - } - - return false; // OK - } - - public static String canonicalizeBSSID(String BSSID) { - if (BSSID == null) { - return ""; - } - - if (isCanonicalBSSID(BSSID)) { - return BSSID; - } - - // Some devices may return BSSIDs with ':', '-' or '.' delimiters. - BSSID = BSSID.toLowerCase(Locale.US).replaceAll("[\\-\\.:]", ""); - - return isCanonicalBSSID(BSSID) ? BSSID : ""; - } - - private static boolean isCanonicalBSSID(String BSSID) { - return BSSID_PATTERN.matcher(BSSID).matches(); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/SSIDBlockList.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/SSIDBlockList.java deleted file mode 100644 index f5086ab34..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/SSIDBlockList.java +++ /dev/null @@ -1,41 +0,0 @@ -/* 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.blocklist; - -import android.net.wifi.ScanResult; - -public final class SSIDBlockList { - private static String[] sPrefixList = new String[]{}; - private static String[] sSuffixList = new String[]{"_nomap"}; - - private SSIDBlockList() { - } - - public static void setFilterLists(String[] prefix, String[] suffix) { - sPrefixList = prefix; - sSuffixList = suffix; - } - - public static boolean contains(ScanResult scanResult) { - String SSID = scanResult.SSID; - if (SSID == null) { - return true; // no SSID? - } - - for (String prefix : sPrefixList) { - if (SSID.startsWith(prefix)) { - return true; // blocked! - } - } - - for (String suffix : sSuffixList) { - if (SSID.endsWith(suffix)) { - return true; // blocked! - } - } - - return false; // OK - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/WifiBlockListInterface.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/WifiBlockListInterface.java deleted file mode 100644 index 0e940cdc9..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/blocklist/WifiBlockListInterface.java +++ /dev/null @@ -1,11 +0,0 @@ -/* 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.blocklist; - -public interface WifiBlockListInterface { - String[] getSsidPrefixList(); - String[] getSsidSuffixList(); - String[] getBssidOuiList(); -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageContract.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageContract.java deleted file mode 100644 index 2aaeb05ff..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageContract.java +++ /dev/null @@ -1,38 +0,0 @@ -/* 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.datahandling; - -public final class DataStorageContract { - - public static class ReportsColumns { - public static final String LAT = "lat"; - public static final String LON = "lon"; - public static final String TIME = "timestamp"; - public static final String ACCURACY = "accuracy"; - public static final String ALTITUDE = "altitude"; - public static final String RADIO = "radio"; - public static final String CELL = "cell"; - public static final String WIFI = "wifi"; - public static final String CELL_COUNT = "cell_count"; - public static final String WIFI_COUNT = "wifi_count"; - public static final String HEADING = "heading"; - public static final String SPEED = "speed"; - public static final String PRESSURE = "pressure"; - } - - public static class Stats { - public static final String KEY_VERSION = "version_code"; - public static final int VERSION_CODE = 2; - public static final String KEY_BYTES_SENT = "bytes_sent"; - public static final String KEY_LAST_UPLOAD_TIME = "last_upload_time"; - public static final String KEY_OBSERVATIONS_SENT = "observations_sent"; - public static final String KEY_WIFIS_SENT = "wifis_sent"; - public static final String KEY_CELLS_SENT = "cells_sent"; - public static final String KEY_OBSERVATIONS_PER_DAY = "obs_per_day"; - } - - private DataStorageContract() { - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java deleted file mode 100644 index adaaea4dc..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java +++ /dev/null @@ -1,473 +0,0 @@ -/* 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.datahandling; - -import android.content.Context; -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.utils.Zipper; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.Properties; -import java.util.Timer; -import java.util.TimerTask; - -/* Stores reports in memory (mCurrentReports) until MAX_REPORTS_IN_MEMORY, - * then writes them to disk as a .gz file. The name of the file has - * the time written, the # of reports, and the # of cells and wifis. - * - * Each .gz file is typically 1-5KB. File name example: reports-t1406863343313-r4-w25-c7.gz - * - * The sync stats are written as a key-value pair file (not zipped). - * - * The tricky bit is the mCurrentReportsSendBuffer. When the uploader code begins accessing the - * report batches, mCurrentReports gets pushed to mCurrentReportsSendBuffer. - * The mCurrentReports is then cleared, and can continue receiving new reports. - * From the uploader perspective, mCurrentReportsSendBuffer looks and acts exactly like a batch file on disk. - * - * If the network is reasonably active, and reporting is slow enough, there is no disk I/O, it all happens - * in-memory. - * - * Also of note: the in-memory buffers (both mCurrentReports and mCurrentReportsSendBuffer) are saved - * when the service is destroyed. - */ -public class DataStorageManager { - private static final String LOG_TAG = AppGlobals.makeLogTag(DataStorageManager.class.getSimpleName()); - - // The max number of reports stored in the mCurrentReports. Each report is a GPS location plus wifi and cell scan. - // After this size is reached, data is persisted to disk, mCurrentReports is cleared. - private static final int MAX_REPORTS_IN_MEMORY = 50; - - // Used to cap the amount of data stored. When this limit is hit, no more data is saved to disk - // until the data is uploaded, or and data exceeds DEFAULT_MAX_WEEKS_DATA_ON_DISK. - private static final long DEFAULT_MAX_BYTES_STORED_ON_DISK = 1024 * 250; // 250 KiB max by default - - // Used as a safeguard to ensure stumbling data is not persisted. The intended use case of the stumbler lib is not - // for long-term storage, and so if ANY data on disk is this old, ALL data is wiped as a privacy mechanism. - private static final int DEFAULT_MAX_WEEKS_DATA_ON_DISK = 2; - - // Set to the default value specified above. - private final long mMaxBytesDiskStorage; - - // Set to the default value specified above. - private final int mMaxWeeksStored; - - private final ReportBatchBuilder mCurrentReports = new ReportBatchBuilder(); - private final File mReportsDir; - private final File mStatsFile; - private final StorageIsEmptyTracker mTracker; - - private static DataStorageManager sInstance; - - private ReportBatch mCurrentReportsSendBuffer; - private ReportBatchIterator mReportBatchIterator; - private final ReportFileList mFileList; - private Timer mFlushMemoryBuffersToDiskTimer; - private final PersistedStats mPersistedOnDiskUploadStats; - - static final String SEP_REPORT_COUNT = "-r"; - static final String SEP_WIFI_COUNT = "-w"; - static final String SEP_CELL_COUNT = "-c"; - static final String SEP_TIME_MS = "-t"; - static final String FILENAME_PREFIX = "reports"; - static final String MEMORY_BUFFER_NAME = "in memory send buffer"; - - public static class QueuedCounts { - public final int mReportCount; - public final int mWifiCount; - public final int mCellCount; - public final long mBytes; - - QueuedCounts(int reportCount, int wifiCount, int cellCount, long bytes) { - this.mReportCount = reportCount; - this.mWifiCount = wifiCount; - this.mCellCount = cellCount; - this.mBytes = bytes; - } - } - - /* Some data is calculated on-demand, don't abuse this function */ - public QueuedCounts getQueuedCounts() { - int reportCount = mFileList.mReportCount + mCurrentReports.reports.size(); - int wifiCount = mFileList.mWifiCount + mCurrentReports.wifiCount; - int cellCount = mFileList.mCellCount + mCurrentReports.cellCount; - long bytes = 0; - - if (mCurrentReports.reports.size() > 0) { - try { - bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes()).length; - } catch (IOException ex) { - Log.e(LOG_TAG, "Zip error in getQueuedCounts()", ex); - } - - if (mFileList.mReportCount > 0) { - bytes += mFileList.mFilesOnDiskBytes; - } - } - - if (mCurrentReportsSendBuffer != null) { - reportCount += mCurrentReportsSendBuffer.reportCount; - wifiCount += mCurrentReportsSendBuffer.wifiCount; - cellCount += mCurrentReportsSendBuffer.cellCount; - bytes += mCurrentReportsSendBuffer.data.length; - } - return new QueuedCounts(reportCount, wifiCount, cellCount, bytes); - } - - private static class ReportFileList { - File[] mFiles; - int mReportCount; - int mWifiCount; - int mCellCount; - long mFilesOnDiskBytes; - - public ReportFileList() {} - public ReportFileList(ReportFileList other) { - if (other == null) { - return; - } - - if (other.mFiles != null) { - mFiles = other.mFiles.clone(); - } - - mReportCount = other.mReportCount; - mWifiCount = other.mWifiCount; - mCellCount = other.mCellCount; - mFilesOnDiskBytes = other.mFilesOnDiskBytes; - } - - void update(File directory) { - mFiles = directory.listFiles(); - if (mFiles == null) { - return; - } - - if (AppGlobals.isDebug) { - for (File f : mFiles) { - Log.d("StumblerFiles", f.getName()); - } - } - - mFilesOnDiskBytes = mReportCount = mWifiCount = mCellCount = 0; - for (File f : mFiles) { - mReportCount += (int) getLongFromFilename(f.getName(), SEP_REPORT_COUNT); - mWifiCount += (int) getLongFromFilename(f.getName(), SEP_WIFI_COUNT); - mCellCount += (int) getLongFromFilename(f.getName(), SEP_CELL_COUNT); - mFilesOnDiskBytes += f.length(); - } - } - } - - public static class ReportBatch { - public final String filename; - public final byte[] data; - public final int reportCount; - public final int wifiCount; - public final int cellCount; - - public ReportBatch(String filename, byte[] data, int reportCount, int wifiCount, int cellCount) { - this.filename = filename; - this.data = data; - this.reportCount = reportCount; - this.wifiCount = wifiCount; - this.cellCount = cellCount; - } - } - - private static class ReportBatchBuilder { - public final ArrayList<String> reports = new ArrayList<String>(); - public int wifiCount; - public int cellCount; - } - - private static class ReportBatchIterator { - public ReportBatchIterator(ReportFileList list) { - fileList = new ReportFileList(list); - } - - static final int BATCH_INDEX_FOR_MEM_BUFFER = -1; - public int currentIndex = BATCH_INDEX_FOR_MEM_BUFFER; - public final ReportFileList fileList; - } - - public interface StorageIsEmptyTracker { - public void notifyStorageStateEmpty(boolean isEmpty); - } - - private String getStorageDir(Context c) { - File dir = c.getFilesDir(); - if (!dir.exists()) { - boolean ok = dir.mkdirs(); - if (!ok) { - Log.d(LOG_TAG, "getStorageDir: error in mkdirs()"); - } - } - - return dir.getPath(); - } - - public static synchronized void createGlobalInstance(Context context, StorageIsEmptyTracker tracker) { - DataStorageManager.createGlobalInstance(context, tracker, - DEFAULT_MAX_BYTES_STORED_ON_DISK, DEFAULT_MAX_WEEKS_DATA_ON_DISK); - } - - public static synchronized void createGlobalInstance(Context context, StorageIsEmptyTracker tracker, - long maxBytesStoredOnDisk, int maxWeeksDataStored) { - if (sInstance != null) { - return; - } - sInstance = new DataStorageManager(context, tracker, maxBytesStoredOnDisk, maxWeeksDataStored); - } - - public static synchronized DataStorageManager getInstance() { - return sInstance; - } - - private DataStorageManager(Context c, StorageIsEmptyTracker tracker, - long maxBytesStoredOnDisk, int maxWeeksDataStored) { - mMaxBytesDiskStorage = maxBytesStoredOnDisk; - mMaxWeeksStored = maxWeeksDataStored; - mTracker = tracker; - final String baseDir = getStorageDir(c); - mStatsFile = new File(baseDir, "upload_stats.ini"); - mReportsDir = new File(baseDir + "/reports"); - if (!mReportsDir.exists()) { - mReportsDir.mkdirs(); - } - mFileList = new ReportFileList(); - mFileList.update(mReportsDir); - mPersistedOnDiskUploadStats = new PersistedStats(baseDir); - } - - public synchronized int getMaxWeeksStored() { - return mMaxWeeksStored; - } - - private static byte[] readFile(File file) throws IOException { - final RandomAccessFile f = new RandomAccessFile(file, "r"); - try { - final byte[] data = new byte[(int) f.length()]; - f.readFully(data); - return data; - } finally { - f.close(); - } - } - - public synchronized boolean isDirEmpty() { - return (mFileList.mFiles == null || mFileList.mFiles.length < 1); - } - - /* Pass filename returned from dataToSend() */ - public synchronized boolean delete(String filename) { - if (filename.equals(MEMORY_BUFFER_NAME)) { - mCurrentReportsSendBuffer = null; - return true; - } - - final File file = new File(mReportsDir, filename); - final boolean ok = file.delete(); - mFileList.update(mReportsDir); - return ok; - } - - private static long getLongFromFilename(String name, String separator) { - final int s = name.indexOf(separator) + separator.length(); - int e = name.indexOf('-', s); - if (e < 0) { - e = name.indexOf('.', s); - } - return Long.parseLong(name.substring(s, e)); - } - - /* return name of file used, or memory buffer sentinel value. - * The return value is used to delete the file/buffer later. */ - public synchronized ReportBatch getFirstBatch() throws IOException { - final boolean dirEmpty = isDirEmpty(); - final int currentReportsCount = mCurrentReports.reports.size(); - - if (dirEmpty && currentReportsCount < 1) { - return null; - } - - mReportBatchIterator = new ReportBatchIterator(mFileList); - - if (currentReportsCount > 0) { - final String filename = MEMORY_BUFFER_NAME; - final byte[] data = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes()); - final int wifiCount = mCurrentReports.wifiCount; - final int cellCount = mCurrentReports.cellCount; - clearCurrentReports(); - final ReportBatch result = new ReportBatch(filename, data, currentReportsCount, wifiCount, cellCount); - mCurrentReportsSendBuffer = result; - return result; - } else { - return getNextBatch(); - } - } - - private void clearCurrentReports() { - mCurrentReports.reports.clear(); - mCurrentReports.wifiCount = mCurrentReports.cellCount = 0; - } - - public synchronized ReportBatch getNextBatch() throws IOException { - if (mReportBatchIterator == null) { - return null; - } - - mReportBatchIterator.currentIndex++; - if (mReportBatchIterator.currentIndex < 0 || - mReportBatchIterator.currentIndex > mReportBatchIterator.fileList.mFiles.length - 1) { - return null; - } - - final File f = mReportBatchIterator.fileList.mFiles[mReportBatchIterator.currentIndex]; - final String filename = f.getName(); - final int reportCount = (int) getLongFromFilename(f.getName(), SEP_REPORT_COUNT); - final int wifiCount = (int) getLongFromFilename(f.getName(), SEP_WIFI_COUNT); - final int cellCount = (int) getLongFromFilename(f.getName(), SEP_CELL_COUNT); - final byte[] data = readFile(f); - return new ReportBatch(filename, data, reportCount, wifiCount, cellCount); - } - - private File createFile(int reportCount, int wifiCount, int cellCount) { - final long time = System.currentTimeMillis(); - final String name = FILENAME_PREFIX + - SEP_TIME_MS + time + - SEP_REPORT_COUNT + reportCount + - SEP_WIFI_COUNT + wifiCount + - SEP_CELL_COUNT + cellCount + ".gz"; - return new File(mReportsDir, name); - } - - public synchronized long getOldestBatchTimeMs() { - if (isDirEmpty()) { - return 0; - } - - long oldest = Long.MAX_VALUE; - for (File f : mFileList.mFiles) { - final long t = getLongFromFilename(f.getName(), SEP_TIME_MS); - if (t < oldest) { - oldest = t; - } - } - return oldest; - } - - public synchronized void saveCurrentReportsSendBufferToDisk() throws IOException { - if (mCurrentReportsSendBuffer == null || mCurrentReportsSendBuffer.reportCount < 1) { - return; - } - - saveToDisk(mCurrentReportsSendBuffer.data, - mCurrentReportsSendBuffer.reportCount, - mCurrentReportsSendBuffer.wifiCount, - mCurrentReportsSendBuffer.cellCount); - mCurrentReportsSendBuffer = null; - } - - private void saveToDisk(byte[] bytes, int reportCount, int wifiCount, int cellCount) - throws IOException { - if (mFileList.mFilesOnDiskBytes > mMaxBytesDiskStorage) { - return; - } - - final FileOutputStream fos = new FileOutputStream(createFile(reportCount, wifiCount, cellCount)); - try { - fos.write(bytes); - } finally { - fos.close(); - } - mFileList.update(mReportsDir); - } - - private String finalizeReports(ArrayList<String> reports) { - final String kPrefix = "{\"items\":["; - final String kSuffix = "]}"; - final StringBuilder sb = new StringBuilder(kPrefix); - String sep = ""; - final String separator = ","; - if (reports != null) { - for(String s: reports) { - sb.append(sep).append(s); - sep = separator; - } - } - - final String result = sb.append(kSuffix).toString(); - return result; - } - - public synchronized void saveCurrentReportsToDisk() throws IOException { - saveCurrentReportsSendBufferToDisk(); - if (mCurrentReports.reports.size() < 1) { - return; - } - final byte[] bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes()); - saveToDisk(bytes, mCurrentReports.reports.size(), mCurrentReports.wifiCount, mCurrentReports.cellCount); - clearCurrentReports(); - } - - public synchronized void insert(String report, int wifiCount, int cellCount) throws IOException { - notifyStorageIsEmpty(false); - - if (mFlushMemoryBuffersToDiskTimer != null) { - mFlushMemoryBuffersToDiskTimer.cancel(); - mFlushMemoryBuffersToDiskTimer = null; - } - - mCurrentReports.reports.add(report); - mCurrentReports.wifiCount += wifiCount; - mCurrentReports.cellCount += cellCount; - - if (mCurrentReports.reports.size() >= MAX_REPORTS_IN_MEMORY) { - // save to disk - saveCurrentReportsToDisk(); - } else { - // Schedule a timer to flush to disk after a few mins. - // If collection stops and wifi not available for uploading, the memory buffer is flushed to disk. - final int kMillis = 1000 * 60 * 3; - mFlushMemoryBuffersToDiskTimer = new Timer(); - mFlushMemoryBuffersToDiskTimer.schedule(new TimerTask() { - @Override - public void run() { - try { - saveCurrentReportsToDisk(); - } catch (IOException ex) { - Log.e(LOG_TAG, "mFlushMemoryBuffersToDiskTimer exception" + ex); - } - } - }, kMillis); - } - } - - public synchronized void deleteAll() { - if (mFileList.mFiles == null) { - return; - } - - for (File f : mFileList.mFiles) { - f.delete(); - } - mFileList.update(mReportsDir); - } - - private void notifyStorageIsEmpty(boolean isEmpty) { - if (mTracker != null) { - mTracker.notifyStorageStateEmpty(isEmpty); - } - } - - public synchronized void incrementSyncStats(long bytesSent, long reports, long cells, long wifis) throws IOException { - mPersistedOnDiskUploadStats.incrementSyncStats(bytesSent, reports, cells, wifis); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/PersistedStats.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/PersistedStats.java deleted file mode 100644 index 79c8e59d1..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/PersistedStats.java +++ /dev/null @@ -1,99 +0,0 @@ -/* 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.datahandling; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.utils.TelemetryWrapper; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -class PersistedStats { - private final File mStatsFile; - - public PersistedStats(String baseDir) { - mStatsFile = new File(baseDir, "upload_stats.ini"); - } - - public synchronized Properties readSyncStats() throws IOException { - if (!mStatsFile.exists()) { - return new Properties(); - } - - final FileInputStream input = new FileInputStream(mStatsFile); - try { - final Properties props = new Properties(); - props.load(input); - return props; - } finally { - input.close(); - } - } - - public synchronized void incrementSyncStats(long bytesSent, long reports, long cells, long wifis) throws IOException { - if (reports + cells + wifis < 1) { - return; - } - - final Properties properties = readSyncStats(); - final long time = System.currentTimeMillis(); - final long lastUploadTime = Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_LAST_UPLOAD_TIME, "0")); - final long storedObsPerDay = Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_OBSERVATIONS_PER_DAY, "0")); - long observationsToday = reports; - if (lastUploadTime > 0) { - long dayLastUploaded = TimeUnit.MILLISECONDS.toDays(lastUploadTime); - long dayDiff = TimeUnit.MILLISECONDS.toDays(time) - dayLastUploaded; - if (dayDiff > 0) { - // send value of store obs per day - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_OBSERVATIONS_PER_DAY, - Long.valueOf(storedObsPerDay / dayDiff).intValue()); - } else { - observationsToday += storedObsPerDay; - } - } - - writeSyncStats(time, - Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_BYTES_SENT, "0")) + bytesSent, - Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_OBSERVATIONS_SENT, "0")) + reports, - Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_CELLS_SENT, "0")) + cells, - Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_WIFIS_SENT, "0")) + wifis, - observationsToday); - - - final long lastUploadMs = Long.parseLong(properties.getProperty(DataStorageContract.Stats.KEY_LAST_UPLOAD_TIME, "0")); - final int timeDiffSec = Long.valueOf((time - lastUploadMs) / 1000).intValue(); - if (lastUploadMs > 0 && timeDiffSec > 0) { - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_TIME_BETWEEN_UPLOADS_SEC, timeDiffSec); - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_BYTES_UPLOADED_PER_SEC, Long.valueOf(bytesSent).intValue() / timeDiffSec); - } - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_BYTES_PER_UPLOAD, Long.valueOf(bytesSent).intValue()); - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_OBSERVATIONS_PER_UPLOAD, Long.valueOf(reports).intValue()); - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_WIFIS_PER_UPLOAD, Long.valueOf(wifis).intValue()); - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_CELLS_PER_UPLOAD, Long.valueOf(cells).intValue()); - } - - public synchronized void writeSyncStats(long time, long bytesSent, long totalObs, - long totalCells, long totalWifis, long obsPerDay) throws IOException { - final FileOutputStream out = new FileOutputStream(mStatsFile); - try { - final Properties props = new Properties(); - props.setProperty(DataStorageContract.Stats.KEY_LAST_UPLOAD_TIME, String.valueOf(time)); - props.setProperty(DataStorageContract.Stats.KEY_BYTES_SENT, String.valueOf(bytesSent)); - props.setProperty(DataStorageContract.Stats.KEY_OBSERVATIONS_SENT, String.valueOf(totalObs)); - props.setProperty(DataStorageContract.Stats.KEY_CELLS_SENT, String.valueOf(totalCells)); - props.setProperty(DataStorageContract.Stats.KEY_WIFIS_SENT, String.valueOf(totalWifis)); - props.setProperty(DataStorageContract.Stats.KEY_VERSION, String.valueOf(DataStorageContract.Stats.VERSION_CODE)); - props.setProperty(DataStorageContract.Stats.KEY_OBSERVATIONS_PER_DAY, String.valueOf(obsPerDay)); - props.store(out, null); - } finally { - out.close(); - } - } - -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/StumblerBundle.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/StumblerBundle.java deleted file mode 100644 index 4f47e3302..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/StumblerBundle.java +++ /dev/null @@ -1,187 +0,0 @@ -/* 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.datahandling; - -import android.location.Location; -import android.net.wifi.ScanResult; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.telephony.TelephonyManager; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellInfo; - -public final class StumblerBundle implements Parcelable { - private final int mPhoneType; - private final Location mGpsPosition; - private final Map<String, ScanResult> mWifiData; - private final Map<String, CellInfo> mCellData; - private float mPressureHPA; - - - public void wasSent() { - mGpsPosition.setTime(System.currentTimeMillis()); - mWifiData.clear(); - mCellData.clear(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - Bundle wifiBundle = new Bundle(ScanResult.class.getClassLoader()); - Collection<String> scans = mWifiData.keySet(); - for (String s : scans) { - wifiBundle.putParcelable(s, mWifiData.get(s)); - } - - Bundle cellBundle = new Bundle(CellInfo.class.getClassLoader()); - Collection<String> cells = mCellData.keySet(); - for (String c : cells) { - cellBundle.putParcelable(c, mCellData.get(c)); - } - - out.writeBundle(wifiBundle); - out.writeBundle(cellBundle); - out.writeParcelable(mGpsPosition, 0); - out.writeInt(mPhoneType); - } - - public static final Parcelable.Creator<StumblerBundle> CREATOR - = new Parcelable.Creator<StumblerBundle>() { - @Override - public StumblerBundle createFromParcel(Parcel in) { - return new StumblerBundle(in); - } - - @Override - public StumblerBundle[] newArray(int size) { - return new StumblerBundle[size]; - } - }; - - private StumblerBundle(Parcel in) { - mWifiData = new HashMap<String, ScanResult>(); - mCellData = new HashMap<String, CellInfo>(); - - Bundle wifiBundle = in.readBundle(ScanResult.class.getClassLoader()); - Bundle cellBundle = in.readBundle(CellInfo.class.getClassLoader()); - - Collection<String> scans = wifiBundle.keySet(); - for (String s : scans) { - mWifiData.put(s, (ScanResult) wifiBundle.get(s)); - } - - Collection<String> cells = cellBundle.keySet(); - for (String c : cells) { - mCellData.put(c, (CellInfo) cellBundle.get(c)); - } - - mGpsPosition = in.readParcelable(Location.class.getClassLoader()); - mPhoneType = in.readInt(); - } - - public StumblerBundle(Location position, int phoneType) { - mGpsPosition = position; - mPhoneType = phoneType; - mWifiData = new HashMap<String, ScanResult>(); - mCellData = new HashMap<String, CellInfo>(); - } - - public Location getGpsPosition() { - return mGpsPosition; - } - - public Map<String, ScanResult> getWifiData() { - return mWifiData; - } - - public Map<String, CellInfo> getCellData() { - return mCellData; - } - - public JSONObject toMLSJSON() throws JSONException { - JSONObject item = new JSONObject(); - - item.put(DataStorageContract.ReportsColumns.TIME, mGpsPosition.getTime()); - item.put(DataStorageContract.ReportsColumns.LAT, Math.floor(mGpsPosition.getLatitude() * 1.0E6) / 1.0E6); - item.put(DataStorageContract.ReportsColumns.LON, Math.floor(mGpsPosition.getLongitude() * 1.0E6) / 1.0E6); - - item.put(DataStorageContract.ReportsColumns.HEADING, mGpsPosition.getBearing()); - item.put(DataStorageContract.ReportsColumns.SPEED, mGpsPosition.getSpeed()); - if (mPressureHPA != 0.0) { - item.put(DataStorageContract.ReportsColumns.PRESSURE, mPressureHPA); - } - - - if (mGpsPosition.hasAccuracy()) { - item.put(DataStorageContract.ReportsColumns.ACCURACY, (int) Math.ceil(mGpsPosition.getAccuracy())); - } - - if (mGpsPosition.hasAltitude()) { - item.put(DataStorageContract.ReportsColumns.ALTITUDE, Math.round(mGpsPosition.getAltitude())); - } - - if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { - item.put(DataStorageContract.ReportsColumns.RADIO, "gsm"); - } else if (mPhoneType == TelephonyManager.PHONE_TYPE_CDMA) { - item.put(DataStorageContract.ReportsColumns.RADIO, "cdma"); - } else { - // issue #598. investigate this case further in future - item.put(DataStorageContract.ReportsColumns.RADIO, ""); - } - - JSONArray cellJSON = new JSONArray(); - for (CellInfo c : mCellData.values()) { - JSONObject obj = c.toJSONObject(); - cellJSON.put(obj); - } - - item.put(DataStorageContract.ReportsColumns.CELL, cellJSON); - item.put(DataStorageContract.ReportsColumns.CELL_COUNT, cellJSON.length()); - - JSONArray wifis = new JSONArray(); - - long gpsTimeSinceBootInMS = 0; - - if (Build.VERSION.SDK_INT >= 17) { - gpsTimeSinceBootInMS = mGpsPosition.getElapsedRealtimeNanos() / 1000000; - } - - for (ScanResult s : mWifiData.values()) { - JSONObject wifiEntry = new JSONObject(); - wifiEntry.put("key", s.BSSID); - wifiEntry.put("frequency", s.frequency); - wifiEntry.put("signal", s.level); - - if (Build.VERSION.SDK_INT >= 17) { - long wifiTimeSinceBootInMS = (s.timestamp / 1000); - long ageMS = wifiTimeSinceBootInMS - gpsTimeSinceBootInMS; - wifiEntry.put("age", ageMS); - } - - wifis.put(wifiEntry); - } - item.put(DataStorageContract.ReportsColumns.WIFI, wifis); - item.put(DataStorageContract.ReportsColumns.WIFI_COUNT, wifis.length()); - - return item; - } - - - public void addPressure(float hPa) { - mPressureHPA = hPa; - } - -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/GPSScanner.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/GPSScanner.java deleted file mode 100644 index 218b97af4..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/GPSScanner.java +++ /dev/null @@ -1,293 +0,0 @@ -/* 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.scanners; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.location.GpsSatellite; -import android.location.GpsStatus; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.location.LocationProvider; -import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.AppGlobals.ActiveOrPassiveStumbling; -import org.mozilla.mozstumbler.service.Prefs; -import org.mozilla.mozstumbler.service.utils.TelemetryWrapper; - -import java.text.SimpleDateFormat; -import java.util.Date; - -public class GPSScanner implements LocationListener { - public static final String ACTION_BASE = AppGlobals.ACTION_NAMESPACE + ".GPSScanner."; - public static final String ACTION_GPS_UPDATED = ACTION_BASE + "GPS_UPDATED"; - public static final String ACTION_ARG_TIME = AppGlobals.ACTION_ARG_TIME; - public static final String SUBJECT_NEW_STATUS = "new_status"; - public static final String SUBJECT_LOCATION_LOST = "location_lost"; - public static final String SUBJECT_NEW_LOCATION = "new_location"; - public static final String NEW_STATUS_ARG_FIXES = "fixes"; - public static final String NEW_STATUS_ARG_SATS = "sats"; - public static final String NEW_LOCATION_ARG_LOCATION = "location"; - - private static final String LOG_TAG = AppGlobals.makeLogTag(GPSScanner.class.getSimpleName()); - private static final int MIN_SAT_USED_IN_FIX = 3; - private static final long ACTIVE_MODE_GPS_MIN_UPDATE_TIME_MS = 1000; - private static final float ACTIVE_MODE_GPS_MIN_UPDATE_DISTANCE_M = 10; - private static final long PASSIVE_GPS_MIN_UPDATE_FREQ_MS = 3000; - private static final float PASSIVE_GPS_MOVEMENT_MIN_DELTA_M = 30; - - private final LocationBlockList mBlockList = new LocationBlockList(); - private final Context mContext; - private GpsStatus.Listener mGPSListener; - private int mLocationCount; - private Location mLocation = new Location("internal"); - private boolean mAutoGeofencing; - private boolean mIsPassiveMode; - private long mTelemetry_lastStartedMs; - private final ScanManager mScanManager; - - public GPSScanner(Context context, ScanManager scanManager) { - mContext = context; - mScanManager = scanManager; - } - - public void start(final ActiveOrPassiveStumbling stumblingMode) { - mIsPassiveMode = (stumblingMode == ActiveOrPassiveStumbling.PASSIVE_STUMBLING); - if (mIsPassiveMode ) { - startPassiveMode(); - } else { - startActiveMode(); - } - } - - private boolean isGpsAvailable(LocationManager locationManager) { - if (locationManager == null || - locationManager.getProvider(LocationManager.GPS_PROVIDER) == null) { - String msg = "No GPS available, scanning not started."; - Log.d(LOG_TAG, msg); - AppGlobals.guiLogError(msg); - return false; - } - return true; - } - - @SuppressLint("MissingPermission") // Permissions are explicitly checked for in StumblerService.onHandleIntent() - private void startPassiveMode() { - LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - if (!isGpsAvailable(locationManager)) { - return; - } - - locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this); - - final int timeDiffSec = Long.valueOf((System.currentTimeMillis() - mTelemetry_lastStartedMs) / 1000).intValue(); - if (mTelemetry_lastStartedMs > 0 && timeDiffSec > 0) { - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_TIME_BETWEEN_STARTS_SEC, timeDiffSec); - } - mTelemetry_lastStartedMs = System.currentTimeMillis(); - } - - @SuppressLint("MissingPermission") // Permissions are explicitly checked for in StumblerService.onHandleIntent() - private void startActiveMode() { - LocationManager lm = getLocationManager(); - if (!isGpsAvailable(lm)) { - return; - } - - lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, - ACTIVE_MODE_GPS_MIN_UPDATE_TIME_MS, - ACTIVE_MODE_GPS_MIN_UPDATE_DISTANCE_M, - this); - - reportLocationLost(); - mGPSListener = new GpsStatus.Listener() { - @Override - public void onGpsStatusChanged(int event) { - if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) { - GpsStatus status = getLocationManager().getGpsStatus(null); - Iterable<GpsSatellite> sats = status.getSatellites(); - - int satellites = 0; - int fixes = 0; - - for (GpsSatellite sat : sats) { - satellites++; - if (sat.usedInFix()) { - fixes++; - } - } - reportNewGpsStatus(fixes, satellites); - if (fixes < MIN_SAT_USED_IN_FIX) { - reportLocationLost(); - } - - if (AppGlobals.isDebug) { - Log.v(LOG_TAG, "onGpsStatusChange - satellites: " + satellites + " fixes: " + fixes); - } - } else if (event == GpsStatus.GPS_EVENT_STOPPED) { - reportLocationLost(); - } - } - }; - - lm.addGpsStatusListener(mGPSListener); - } - - @SuppressLint("MissingPermission") // Permissions are explicitly checked for in StumblerService.onHandleIntent() - public void stop() { - LocationManager lm = getLocationManager(); - lm.removeUpdates(this); - reportLocationLost(); - - if (mGPSListener != null) { - lm.removeGpsStatusListener(mGPSListener); - mGPSListener = null; - } - } - - public int getLocationCount() { - return mLocationCount; - } - - public double getLatitude() { - return mLocation.getLatitude(); - } - - public double getLongitude() { - return mLocation.getLongitude(); - } - - public Location getLocation() { - return mLocation; - } - - public void checkPrefs() { - if (mBlockList != null) { - mBlockList.updateBlocks(); - } - - Prefs prefs = Prefs.getInstanceWithoutContext(); - if (prefs == null) { - return; - } - mAutoGeofencing = prefs.getGeofenceHere(); - } - - public boolean isGeofenced() { - return (mBlockList != null) && mBlockList.isGeofenced(); - } - - private void sendToLogActivity(String msg) { - AppGlobals.guiLogInfo(msg, "#33ccff", false); - } - - @Override - public void onLocationChanged(Location location) { - if (location == null) { // TODO: is this even possible?? - reportLocationLost(); - return; - } - - String logMsg = (mIsPassiveMode)? "[Passive] " : "[Active] "; - - String provider = location.getProvider(); - if (!provider.toLowerCase().contains("gps")) { - Log.d(LOG_TAG, "Discard fused/network location."); - // only interested in GPS locations - return; - } - - final long timeDeltaMs = location.getTime() - mLocation.getTime(); - - // Seem to get greater likelihood of non-fused location with higher update freq. - // Check dist and time threshold here, not set on the listener. - if (mIsPassiveMode) { - final boolean hasMoved = location.distanceTo(mLocation) > PASSIVE_GPS_MOVEMENT_MIN_DELTA_M; - - if (timeDeltaMs < PASSIVE_GPS_MIN_UPDATE_FREQ_MS || !hasMoved) { - return; - } - } - - Date date = new Date(location.getTime()); - SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); - String time = formatter.format(date); - logMsg += String.format("%s Coord: %.4f,%.4f, Acc: %.0f, Speed: %.0f, Alt: %.0f, Bearing: %.1f", time, location.getLatitude(), - location.getLongitude(), location.getAccuracy(), location.getSpeed(), location.getAltitude(), location.getBearing()); - sendToLogActivity(logMsg); - - if (mBlockList.contains(location)) { - reportLocationLost(); - return; - } - - mLocation = location; - - if (!mAutoGeofencing) { - reportNewLocationReceived(location); - } - mLocationCount++; - - if (mIsPassiveMode) { - mScanManager.newPassiveGpsLocation(); - } - - if (timeDeltaMs > 0) { - TelemetryWrapper.addToHistogram(AppGlobals.TELEMETRY_TIME_BETWEEN_RECEIVED_LOCATIONS_SEC, - Long.valueOf(timeDeltaMs).intValue() / 1000); - } - } - - @Override - public void onProviderDisabled(String provider) { - if (LocationManager.GPS_PROVIDER.equals(provider)) { - reportLocationLost(); - } - } - - @Override - public void onProviderEnabled(String provider) { - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - if ((status != LocationProvider.AVAILABLE) && - (LocationManager.GPS_PROVIDER.equals(provider))) { - reportLocationLost(); - } - } - - private LocationManager getLocationManager() { - return (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - } - - private void reportNewLocationReceived(Location location) { - Intent i = new Intent(ACTION_GPS_UPDATED); - i.putExtra(Intent.EXTRA_SUBJECT, SUBJECT_NEW_LOCATION); - i.putExtra(NEW_LOCATION_ARG_LOCATION, location); - i.putExtra(ACTION_ARG_TIME, System.currentTimeMillis()); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(i); - } - - private void reportLocationLost() { - Intent i = new Intent(ACTION_GPS_UPDATED); - i.putExtra(Intent.EXTRA_SUBJECT, SUBJECT_LOCATION_LOST); - i.putExtra(ACTION_ARG_TIME, System.currentTimeMillis()); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(i); - } - - private void reportNewGpsStatus(int fixes, int sats) { - Intent i = new Intent(ACTION_GPS_UPDATED); - i.putExtra(Intent.EXTRA_SUBJECT, SUBJECT_NEW_STATUS); - i.putExtra(NEW_STATUS_ARG_FIXES, fixes); - i.putExtra(NEW_STATUS_ARG_SATS, sats); - i.putExtra(ACTION_ARG_TIME, System.currentTimeMillis()); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(i); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/LocationBlockList.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/LocationBlockList.java deleted file mode 100644 index c3cba7b45..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/LocationBlockList.java +++ /dev/null @@ -1,105 +0,0 @@ -/* 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.scanners; - -import android.location.Location; -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.Prefs; - -public final class LocationBlockList { - private static final String LOG_TAG = AppGlobals.makeLogTag(LocationBlockList.class.getSimpleName()); - private static final double MAX_ALTITUDE = 8848; // Mount Everest's altitude in meters - private static final double MIN_ALTITUDE = -418; // Dead Sea's altitude in meters - private static final float MAX_SPEED = 340.29f; // Mach 1 in meters/second - private static final float MIN_ACCURACY = 500; // meter radius - private static final long MIN_TIMESTAMP = 946684801; // 2000-01-01 00:00:01 - private static final double GEOFENCE_RADIUS = 0.01; // .01 degrees is approximately 1km - private static final long MILLISECONDS_PER_DAY = 86400000; - - private Location mBlockedLocation; - private boolean mGeofencingEnabled; - private boolean mIsGeofenced = false; - - public LocationBlockList() { - updateBlocks(); - } - - public void updateBlocks() { - Prefs prefs = Prefs.getInstanceWithoutContext(); - if (prefs == null) { - return; - } - mBlockedLocation = prefs.getGeofenceLocation(); - mGeofencingEnabled = prefs.getGeofenceEnabled(); - } - - public boolean contains(Location location) { - final float inaccuracy = location.getAccuracy(); - final double altitude = location.getAltitude(); - final float bearing = location.getBearing(); - final double latitude = location.getLatitude(); - final double longitude = location.getLongitude(); - final float speed = location.getSpeed(); - final long timestamp = location.getTime(); - final long tomorrow = System.currentTimeMillis() + MILLISECONDS_PER_DAY; - - boolean block = false; - mIsGeofenced = false; - - if (latitude == 0 && longitude == 0) { - block = true; - Log.w(LOG_TAG, "Bogus latitude,longitude: 0,0"); - } else { - if (latitude < -90 || latitude > 90) { - block = true; - Log.w(LOG_TAG, "Bogus latitude: " + latitude); - } - - if (longitude < -180 || longitude > 180) { - block = true; - Log.w(LOG_TAG, "Bogus longitude: " + longitude); - } - } - - if (location.hasAccuracy() && (inaccuracy < 0 || inaccuracy > MIN_ACCURACY)) { - block = true; - Log.w(LOG_TAG, "Insufficient accuracy: " + inaccuracy + " meters"); - } - - if (location.hasAltitude() && (altitude < MIN_ALTITUDE || altitude > MAX_ALTITUDE)) { - block = true; - Log.w(LOG_TAG, "Bogus altitude: " + altitude + " meters"); - } - - if (location.hasBearing() && (bearing < 0 || bearing > 360)) { - block = true; - Log.w(LOG_TAG, "Bogus bearing: " + bearing + " degrees"); - } - - if (location.hasSpeed() && (speed < 0 || speed > MAX_SPEED)) { - block = true; - Log.w(LOG_TAG, "Bogus speed: " + speed + " meters/second"); - } - - if (timestamp < MIN_TIMESTAMP || timestamp > tomorrow) { - block = true; - Log.w(LOG_TAG, "Bogus timestamp: " + timestamp); - } - - if (mGeofencingEnabled && - Math.abs(location.getLatitude() - mBlockedLocation.getLatitude()) < GEOFENCE_RADIUS && - Math.abs(location.getLongitude() - mBlockedLocation.getLongitude()) < GEOFENCE_RADIUS) { - block = true; - mIsGeofenced = true; - } - - return block; - } - - public boolean isGeofenced() { - return mIsGeofenced; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java deleted file mode 100644 index 60d7c8f1c..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java +++ /dev/null @@ -1,191 +0,0 @@ -/* 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.scanners; - -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.location.Location; -import android.os.BatteryManager; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.stumblerthread.Reporter; -import org.mozilla.mozstumbler.service.stumblerthread.blocklist.WifiBlockListInterface; -import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellScanner; -import org.mozilla.mozstumbler.service.AppGlobals.ActiveOrPassiveStumbling; - -import java.util.Date; -import java.util.Timer; -import java.util.TimerTask; - -public class ScanManager { - private static final String LOG_TAG = AppGlobals.makeLogTag(ScanManager.class.getSimpleName()); - private Timer mPassiveModeFlushTimer; - private Context mContext; - private boolean mIsScanning; - private GPSScanner mGPSScanner; - private WifiScanner mWifiScanner; - private CellScanner mCellScanner; - private ActiveOrPassiveStumbling mStumblingMode = ActiveOrPassiveStumbling.ACTIVE_STUMBLING; - - public ScanManager() { - } - - private boolean isBatteryLow() { - Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - if (intent == null) { - return false; - } - - int rawLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); - int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); - int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); - boolean isCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING); - int level = Math.round(rawLevel * scale/100.0f); - - final int kMinBatteryPct = 15; - return !isCharging && level < kMinBatteryPct; - } - - public void newPassiveGpsLocation() { - if (isBatteryLow()) { - return; - } - - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "New passive location"); - } - - mWifiScanner.start(ActiveOrPassiveStumbling.PASSIVE_STUMBLING); - mCellScanner.start(ActiveOrPassiveStumbling.PASSIVE_STUMBLING); - - // how often to flush a leftover bundle to the reports table - // If there is a bundle, and nothing happens for 10sec, then flush it - final int flushRate_ms = 10000; - - if (mPassiveModeFlushTimer != null) { - mPassiveModeFlushTimer.cancel(); - } - - Date when = new Date(); - when.setTime(when.getTime() + flushRate_ms); - mPassiveModeFlushTimer = new Timer(); - mPassiveModeFlushTimer.schedule(new TimerTask() { - @Override - public void run() { - Intent flush = new Intent(Reporter.ACTION_FLUSH_TO_BUNDLE); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(flush); - } - }, when); - } - - public void setPassiveMode(boolean on) { - mStumblingMode = (on)? ActiveOrPassiveStumbling.PASSIVE_STUMBLING : - ActiveOrPassiveStumbling.ACTIVE_STUMBLING; - } - - public boolean isPassiveMode() { - return ActiveOrPassiveStumbling.PASSIVE_STUMBLING == mStumblingMode; - } - - public void startScanning(Context context) { - if (mIsScanning) { - return; - } - - mContext = context.getApplicationContext(); - if (mContext == null) { - Log.w(LOG_TAG, "No app context available."); - return; - } - - if (mGPSScanner == null) { - mGPSScanner = new GPSScanner(context, this); - mWifiScanner = new WifiScanner(context); - mCellScanner = new CellScanner(context); - } - - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "Scanning started..."); - } - - mGPSScanner.start(mStumblingMode); - if (mStumblingMode == ActiveOrPassiveStumbling.ACTIVE_STUMBLING) { - mWifiScanner.start(mStumblingMode); - mCellScanner.start(mStumblingMode); - // in passive mode, these scans are started by passive gps notifications - } - mIsScanning = true; - } - - public boolean stopScanning() { - if (!mIsScanning) { - return false; - } - - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "Scanning stopped"); - } - - mGPSScanner.stop(); - mWifiScanner.stop(); - mCellScanner.stop(); - - mIsScanning = false; - return true; - } - - public void setWifiBlockList(WifiBlockListInterface list) { - WifiScanner.setWifiBlockList(list); - } - - public boolean isScanning() { - return mIsScanning; - } - - public int getAPCount() { - return (mWifiScanner == null)? 0 : mWifiScanner.getAPCount(); - } - - public int getVisibleAPCount() { - return (mWifiScanner == null)? 0 :mWifiScanner.getVisibleAPCount(); - } - - public int getWifiStatus() { - return (mWifiScanner == null)? 0 : mWifiScanner.getStatus(); - } - - public int getCellInfoCount() { - return (mCellScanner == null)? 0 :mCellScanner.getCellInfoCount(); - } - - public int getLocationCount() { - return (mGPSScanner == null)? 0 : mGPSScanner.getLocationCount(); - } - - public double getLatitude() { - return (mGPSScanner == null)? 0.0 : mGPSScanner.getLatitude(); - } - - public double getLongitude() { - return (mGPSScanner == null)? 0.0 : mGPSScanner.getLongitude(); - } - - public Location getLocation() { - return (mGPSScanner == null)? new Location("null") : mGPSScanner.getLocation(); - } - - public void checkPrefs() { - if (mGPSScanner != null) { - mGPSScanner.checkPrefs(); - } - } - - public boolean isGeofenced() { - return (mGPSScanner != null) && mGPSScanner.isGeofenced(); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/WifiScanner.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/WifiScanner.java deleted file mode 100644 index eed61d8bb..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/WifiScanner.java +++ /dev/null @@ -1,228 +0,0 @@ -/* 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.scanners; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.WifiLock; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicInteger; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.stumblerthread.blocklist.BSSIDBlockList; -import org.mozilla.mozstumbler.service.stumblerthread.blocklist.SSIDBlockList; -import org.mozilla.mozstumbler.service.AppGlobals.ActiveOrPassiveStumbling; -import org.mozilla.mozstumbler.service.Prefs; -import org.mozilla.mozstumbler.service.stumblerthread.blocklist.WifiBlockListInterface; - -public class WifiScanner extends BroadcastReceiver { - public static final String ACTION_BASE = AppGlobals.ACTION_NAMESPACE + ".WifiScanner."; - public static final String ACTION_WIFIS_SCANNED = ACTION_BASE + "WIFIS_SCANNED"; - public static final String ACTION_WIFIS_SCANNED_ARG_RESULTS = "scan_results"; - public static final String ACTION_WIFIS_SCANNED_ARG_TIME = AppGlobals.ACTION_ARG_TIME; - - public static final int STATUS_IDLE = 0; - public static final int STATUS_ACTIVE = 1; - public static final int STATUS_WIFI_DISABLED = -1; - - private static final String LOG_TAG = AppGlobals.makeLogTag(WifiScanner.class.getSimpleName()); - private static final long WIFI_MIN_UPDATE_TIME = 5000; // milliseconds - - private boolean mStarted; - private final Context mContext; - private WifiLock mWifiLock; - private Timer mWifiScanTimer; - private final Set<String> mAPs = Collections.synchronizedSet(new HashSet<String>()); - private final AtomicInteger mVisibleAPs = new AtomicInteger(); - - /* Testing */ - public static boolean sIsTestMode; - public List<ScanResult> mTestModeFakeScanResults = new ArrayList<ScanResult>(); - public Set<String> getAccessPoints(android.test.AndroidTestCase restrictedAccessor) { return mAPs; } - /* ------- */ - - public WifiScanner(Context c) { - mContext = c; - } - - private boolean isWifiEnabled() { - return (sIsTestMode) || getWifiManager().isWifiEnabled(); - } - - private List<ScanResult> getScanResults() { - WifiManager manager = getWifiManager(); - if (manager == null) { - return null; - } - return getWifiManager().getScanResults(); - } - - - public synchronized void start(final ActiveOrPassiveStumbling stumblingMode) { - Prefs prefs = Prefs.getInstanceWithoutContext(); - if (mStarted || prefs == null) { - return; - } - mStarted = true; - - boolean scanAlways = prefs.getWifiScanAlways(); - - if (scanAlways || isWifiEnabled()) { - activatePeriodicScan(stumblingMode); - } - - IntentFilter i = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - if (!scanAlways) i.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - mContext.registerReceiver(this, i); - } - - public synchronized void stop() { - if (mStarted) { - mContext.unregisterReceiver(this); - } - deactivatePeriodicScan(); - mStarted = false; - } - - @Override - public void onReceive(Context c, Intent intent) { - String action = intent.getAction(); - - if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { - if (isWifiEnabled()) { - activatePeriodicScan(ActiveOrPassiveStumbling.ACTIVE_STUMBLING); - } else { - deactivatePeriodicScan(); - } - } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) { - final List<ScanResult> scanResultList = getScanResults(); - if (scanResultList == null) { - return; - } - final ArrayList<ScanResult> scanResults = new ArrayList<ScanResult>(); - for (ScanResult scanResult : scanResultList) { - scanResult.BSSID = BSSIDBlockList.canonicalizeBSSID(scanResult.BSSID); - if (shouldLog(scanResult)) { - scanResults.add(scanResult); - mAPs.add(scanResult.BSSID); - } - } - mVisibleAPs.set(scanResults.size()); - reportScanResults(scanResults); - } - } - - public static void setWifiBlockList(WifiBlockListInterface blockList) { - BSSIDBlockList.setFilterList(blockList.getBssidOuiList()); - SSIDBlockList.setFilterLists(blockList.getSsidPrefixList(), blockList.getSsidSuffixList()); - } - - public int getAPCount() { - return mAPs.size(); - } - - public int getVisibleAPCount() { - return mVisibleAPs.get(); - } - - public synchronized int getStatus() { - if (!mStarted) { - return STATUS_IDLE; - } - if (mWifiScanTimer == null) { - return STATUS_WIFI_DISABLED; - } - return STATUS_ACTIVE; - } - - private synchronized void activatePeriodicScan(final ActiveOrPassiveStumbling stumblingMode) { - if (mWifiScanTimer != null) { - return; - } - - if (AppGlobals.isDebug) { - Log.v(LOG_TAG, "Activate Periodic Scan"); - } - - mWifiLock = getWifiManager().createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "MozStumbler"); - mWifiLock.acquire(); - - // Ensure that we are constantly scanning for new access points. - mWifiScanTimer = new Timer(); - mWifiScanTimer.schedule(new TimerTask() { - int mPassiveScanCount; - @Override - public void run() { - if (stumblingMode == ActiveOrPassiveStumbling.PASSIVE_STUMBLING && - mPassiveScanCount++ > AppGlobals.PASSIVE_MODE_MAX_SCANS_PER_GPS) - { - mPassiveScanCount = 0; - stop(); // set mWifiScanTimer to null - return; - } - if (AppGlobals.isDebug) { - Log.v(LOG_TAG, "WiFi Scanning Timer fired"); - } - getWifiManager().startScan(); - } - }, 0, WIFI_MIN_UPDATE_TIME); - } - - private synchronized void deactivatePeriodicScan() { - if (mWifiScanTimer == null) { - return; - } - - if (AppGlobals.isDebug) { - Log.v(LOG_TAG, "Deactivate periodic scan"); - } - - mWifiLock.release(); - mWifiLock = null; - - mWifiScanTimer.cancel(); - mWifiScanTimer = null; - - mVisibleAPs.set(0); - } - - public static boolean shouldLog(ScanResult scanResult) { - if (BSSIDBlockList.contains(scanResult)) { - return false; - } - if (SSIDBlockList.contains(scanResult)) { - return false; - } - return true; - } - - private WifiManager getWifiManager() { - return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - } - - private void reportScanResults(ArrayList<ScanResult> scanResults) { - if (scanResults.isEmpty()) { - return; - } - - Intent i = new Intent(ACTION_WIFIS_SCANNED); - i.putParcelableArrayListExtra(ACTION_WIFIS_SCANNED_ARG_RESULTS, scanResults); - i.putExtra(ACTION_WIFIS_SCANNED_ARG_TIME, System.currentTimeMillis()); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(i); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellInfo.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellInfo.java deleted file mode 100644 index f435dcf11..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellInfo.java +++ /dev/null @@ -1,391 +0,0 @@ -/* 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.scanners.cellscanner; - -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.telephony.CellLocation; -import android.telephony.NeighboringCellInfo; -import android.telephony.TelephonyManager; -import android.telephony.cdma.CdmaCellLocation; -import android.telephony.gsm.GsmCellLocation; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.mozstumbler.service.AppGlobals; - -public class CellInfo implements Parcelable { - private static final String LOG_TAG = AppGlobals.makeLogTag(CellInfo.class.getSimpleName()); - - public static final String RADIO_GSM = "gsm"; - public static final String RADIO_CDMA = "cdma"; - public static final String RADIO_WCDMA = "wcdma"; - - public static final String CELL_RADIO_GSM = "gsm"; - public static final String CELL_RADIO_UMTS = "umts"; - public static final String CELL_RADIO_CDMA = "cdma"; - public static final String CELL_RADIO_LTE = "lte"; - - public static final int UNKNOWN_CID = -1; - public static final int UNKNOWN_SIGNAL = -1000; - - public static final Parcelable.Creator<CellInfo> CREATOR - = new Parcelable.Creator<CellInfo>() { - @Override - public CellInfo createFromParcel(Parcel in) { - return new CellInfo(in); - } - - @Override - public CellInfo[] newArray(int size) { - return new CellInfo[size]; - } - }; - - private String mRadio; - private String mCellRadio; - - private int mMcc; - private int mMnc; - private int mCid; - private int mLac; - private int mSignal; - private int mAsu; - private int mTa; - private int mPsc; - - public CellInfo(int phoneType) { - reset(); - setRadio(phoneType); - } - - private CellInfo(Parcel in) { - mRadio = in.readString(); - mCellRadio = in.readString(); - mMcc = in.readInt(); - mMnc = in.readInt(); - mCid = in.readInt(); - mLac = in.readInt(); - mSignal = in.readInt(); - mAsu = in.readInt(); - mTa = in.readInt(); - mPsc = in.readInt(); - } - - public boolean isCellRadioValid() { - return mCellRadio != null && (mCellRadio.length() > 0) && !mCellRadio.equals("0"); - } - - public String getRadio() { - return mRadio; - } - - public String getCellRadio() { - return mCellRadio; - } - - public int getMcc() { - return mMcc; - } - - public int getMnc() { - return mMnc; - } - - public int getCid() { - return mCid; - } - - public int getLac() { - return mLac; - } - - public int getPsc() { - return mPsc; - } - - public JSONObject toJSONObject() { - final JSONObject obj = new JSONObject(); - - try { - obj.put("radio", getCellRadio()); - obj.put("mcc", mMcc); - obj.put("mnc", mMnc); - if (mLac != UNKNOWN_CID) obj.put("lac", mLac); - if (mCid != UNKNOWN_CID) obj.put("cid", mCid); - if (mSignal != UNKNOWN_SIGNAL) obj.put("signal", mSignal); - if (mAsu != UNKNOWN_SIGNAL) obj.put("asu", mAsu); - if (mTa != UNKNOWN_CID) obj.put("ta", mTa); - if (mPsc != UNKNOWN_CID) obj.put("psc", mPsc); - } catch (JSONException jsonE) { - throw new IllegalStateException(jsonE); - } - - return obj; - } - - public String getCellIdentity() { - return getRadio() - + " " + getCellRadio() - + " " + getMcc() - + " " + getMnc() - + " " + getLac() - + " " + getCid() - + " " + getPsc(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mRadio); - dest.writeString(mCellRadio); - dest.writeInt(mMcc); - dest.writeInt(mMnc); - dest.writeInt(mCid); - dest.writeInt(mLac); - dest.writeInt(mSignal); - dest.writeInt(mAsu); - dest.writeInt(mTa); - dest.writeInt(mPsc); - } - - void reset() { - mRadio = RADIO_GSM; - mCellRadio = CELL_RADIO_GSM; - mMcc = UNKNOWN_CID; - mMnc = UNKNOWN_CID; - mLac = UNKNOWN_CID; - mCid = UNKNOWN_CID; - mSignal = UNKNOWN_SIGNAL; - mAsu = UNKNOWN_SIGNAL; - mTa = UNKNOWN_CID; - mPsc = UNKNOWN_CID; - } - - void setRadio(int phoneType) { - mRadio = getRadioTypeName(phoneType); - } - - void setCellLocation(CellLocation cl, - int networkType, - String networkOperator, - Integer gsmSignalStrength, - Integer cdmaRssi) { - if (cl instanceof GsmCellLocation) { - final int lac, cid; - final GsmCellLocation gcl = (GsmCellLocation) cl; - - reset(); - mCellRadio = getCellRadioTypeName(networkType); - setNetworkOperator(networkOperator); - - lac = gcl.getLac(); - cid = gcl.getCid(); - if (lac >= 0) mLac = lac; - if (cid >= 0) mCid = cid; - - if (Build.VERSION.SDK_INT >= 9) { - final int psc = gcl.getPsc(); - if (psc >= 0) mPsc = psc; - } - - if (gsmSignalStrength != null) { - mAsu = gsmSignalStrength; - } - } else if (cl instanceof CdmaCellLocation) { - final CdmaCellLocation cdl = (CdmaCellLocation) cl; - - reset(); - mCellRadio = getCellRadioTypeName(networkType); - - setNetworkOperator(networkOperator); - - mMnc = cdl.getSystemId(); - - mLac = cdl.getNetworkId(); - mCid = cdl.getBaseStationId(); - - if (cdmaRssi != null) { - mSignal = cdmaRssi; - } - } else { - throw new IllegalArgumentException("Unexpected CellLocation type: " + cl.getClass().getName()); - } - } - - void setNeighboringCellInfo(NeighboringCellInfo nci, String networkOperator) { - final int lac, cid, psc, rssi; - - reset(); - mCellRadio = getCellRadioTypeName(nci.getNetworkType()); - setNetworkOperator(networkOperator); - - lac = nci.getLac(); - cid = nci.getCid(); - psc = nci.getPsc(); - rssi = nci.getRssi(); - - if (lac >= 0) mLac = lac; - if (cid >= 0) mCid = cid; - if (psc >= 0) mPsc = psc; - if (rssi != NeighboringCellInfo.UNKNOWN_RSSI) mAsu = rssi; - } - - void setGsmCellInfo(int mcc, int mnc, int lac, int cid, int asu) { - mCellRadio = CELL_RADIO_GSM; - mMcc = mcc != Integer.MAX_VALUE ? mcc : UNKNOWN_CID; - mMnc = mnc != Integer.MAX_VALUE ? mnc : UNKNOWN_CID; - mLac = lac != Integer.MAX_VALUE ? lac : UNKNOWN_CID; - mCid = cid != Integer.MAX_VALUE ? cid : UNKNOWN_CID; - mAsu = asu; - } - - public void setWcmdaCellInfo(int mcc, int mnc, int lac, int cid, int psc, int asu) { - mCellRadio = CELL_RADIO_UMTS; - mMcc = mcc != Integer.MAX_VALUE ? mcc : UNKNOWN_CID; - mMnc = mnc != Integer.MAX_VALUE ? mnc : UNKNOWN_CID; - mLac = lac != Integer.MAX_VALUE ? lac : UNKNOWN_CID; - mCid = cid != Integer.MAX_VALUE ? cid : UNKNOWN_CID; - mPsc = psc != Integer.MAX_VALUE ? psc : UNKNOWN_CID; - mAsu = asu; - } - - /** - * @param mcc Mobile Country Code, Integer.MAX_VALUE if unknown - * @param mnc Mobile Network Code, Integer.MAX_VALUE if unknown - * @param ci Cell Identity, Integer.MAX_VALUE if unknown - * @param pci Physical Cell Id, Integer.MAX_VALUE if unknown - * @param tac Tracking Area Code, Integer.MAX_VALUE if unknown - * @param asu Arbitrary strength unit - * @param ta Timing advance - */ - void setLteCellInfo(int mcc, int mnc, int ci, int pci, int tac, int asu, int ta) { - mCellRadio = CELL_RADIO_LTE; - mMcc = mcc != Integer.MAX_VALUE ? mcc : UNKNOWN_CID; - mMnc = mnc != Integer.MAX_VALUE ? mnc : UNKNOWN_CID; - mLac = tac != Integer.MAX_VALUE ? tac : UNKNOWN_CID; - mCid = ci != Integer.MAX_VALUE ? ci : UNKNOWN_CID; - mPsc = pci != Integer.MAX_VALUE ? pci : UNKNOWN_CID; - mAsu = asu; - mTa = ta; - } - - void setCdmaCellInfo(int baseStationId, int networkId, int systemId, int dbm) { - mCellRadio = CELL_RADIO_CDMA; - mMnc = systemId != Integer.MAX_VALUE ? systemId : UNKNOWN_CID; - mLac = networkId != Integer.MAX_VALUE ? networkId : UNKNOWN_CID; - mCid = baseStationId != Integer.MAX_VALUE ? baseStationId : UNKNOWN_CID; - mSignal = dbm; - } - - void setNetworkOperator(String mccMnc) { - if (mccMnc == null || mccMnc.length() < 5 || mccMnc.length() > 8) { - throw new IllegalArgumentException("Bad mccMnc: " + mccMnc); - } - mMcc = Integer.parseInt(mccMnc.substring(0, 3)); - mMnc = Integer.parseInt(mccMnc.substring(3)); - } - - static String getCellRadioTypeName(int networkType) { - switch (networkType) { - // If the network is either GSM or any high-data-rate variant of it, the radio - // field should be specified as `gsm`. This includes `GSM`, `EDGE` and `GPRS`. - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_EDGE: - return CELL_RADIO_GSM; - - // If the network is either UMTS or any high-data-rate variant of it, the radio - // field should be specified as `umts`. This includes `UMTS`, `HSPA`, `HSDPA`, - // `HSPA+` and `HSUPA`. - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - return CELL_RADIO_UMTS; - - case TelephonyManager.NETWORK_TYPE_LTE: - return CELL_RADIO_LTE; - - // If the network is either CDMA or one of the EVDO variants, the radio - // field should be specified as `cdma`. This includes `1xRTT`, `CDMA`, `eHRPD`, - // `EVDO_0`, `EVDO_A`, `EVDO_B`, `IS95A` and `IS95B`. - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_1xRTT: - case TelephonyManager.NETWORK_TYPE_EHRPD: - case TelephonyManager.NETWORK_TYPE_IDEN: - return CELL_RADIO_CDMA; - - default: - Log.e(LOG_TAG, "", new IllegalArgumentException("Unexpected network type: " + networkType)); - return String.valueOf(networkType); - } - } - - @SuppressWarnings("fallthrough") - private static String getRadioTypeName(int phoneType) { - switch (phoneType) { - case TelephonyManager.PHONE_TYPE_CDMA: - return RADIO_CDMA; - - case TelephonyManager.PHONE_TYPE_GSM: - return RADIO_GSM; - - default: - Log.e(LOG_TAG, "", new IllegalArgumentException("Unexpected phone type: " + phoneType)); - // fallthrough - - case TelephonyManager.PHONE_TYPE_NONE: - case TelephonyManager.PHONE_TYPE_SIP: - // These devices have no radio. - return ""; - } - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof CellInfo)) { - return false; - } - CellInfo ci = (CellInfo) o; - return mRadio.equals(ci.mRadio) - && mCellRadio.equals(ci.mCellRadio) - && mMcc == ci.mMcc - && mMnc == ci.mMnc - && mCid == ci.mCid - && mLac == ci.mLac - && mSignal == ci.mSignal - && mAsu == ci.mAsu - && mTa == ci.mTa - && mPsc == ci.mPsc; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + mRadio.hashCode(); - result = 31 * result + mCellRadio.hashCode(); - result = 31 * result + mMcc; - result = 31 * result + mMnc; - result = 31 * result + mCid; - result = 31 * result + mLac; - result = 31 * result + mSignal; - result = 31 * result + mAsu; - result = 31 * result + mTa; - result = 31 * result + mPsc; - return result; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScanner.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScanner.java deleted file mode 100644 index 193de9923..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScanner.java +++ /dev/null @@ -1,178 +0,0 @@ -/* 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.scanners.cellscanner; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.os.Message; -import android.support.v4.content.LocalBroadcastManager; -import android.telephony.TelephonyManager; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.AppGlobals.ActiveOrPassiveStumbling; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicBoolean; -import org.mozilla.mozstumbler.service.AppGlobals.ActiveOrPassiveStumbling; -import org.mozilla.mozstumbler.service.stumblerthread.Reporter; - -public class CellScanner { - public static final String ACTION_BASE = AppGlobals.ACTION_NAMESPACE + ".CellScanner."; - public static final String ACTION_CELLS_SCANNED = ACTION_BASE + "CELLS_SCANNED"; - public static final String ACTION_CELLS_SCANNED_ARG_CELLS = "cells"; - public static final String ACTION_CELLS_SCANNED_ARG_TIME = AppGlobals.ACTION_ARG_TIME; - - private static final String LOG_TAG = AppGlobals.makeLogTag(CellScanner.class.getSimpleName()); - private static final long CELL_MIN_UPDATE_TIME = 1000; // milliseconds - - private final Context mContext; - private Timer mCellScanTimer; - private final Set<String> mCells = new HashSet<String>(); - private final ReportFlushedReceiver mReportFlushedReceiver = new ReportFlushedReceiver(); - private final AtomicBoolean mReportWasFlushed = new AtomicBoolean(); - private Handler mBroadcastScannedHandler; - private final CellScannerImpl mCellScannerImplementation; - - public ArrayList<CellInfo> sTestingModeCellInfoArray; - - public interface CellScannerImpl { - void start(); - boolean isStarted(); - boolean isSupportedOnThisDevice(); - void stop(); - List<CellInfo> getCellInfo(); - } - - public CellScanner(Context context) { - mContext = context; - mCellScannerImplementation = new CellScannerImplementation(context); - } - - public void start(final ActiveOrPassiveStumbling stumblingMode) { - if (!mCellScannerImplementation.isSupportedOnThisDevice()) { - return; - } - - if (mCellScanTimer != null) { - return; - } - - LocalBroadcastManager.getInstance(mContext).registerReceiver(mReportFlushedReceiver, - new IntentFilter(Reporter.ACTION_NEW_BUNDLE)); - - // This is to ensure the broadcast happens from the same thread the CellScanner start() is on - mBroadcastScannedHandler = new BroadcastScannedHandler(this); - - mCellScannerImplementation.start(); - - mCellScanTimer = new Timer(); - - mCellScanTimer.schedule(new TimerTask() { - int mPassiveScanCount; - @Override - public void run() { - if (!mCellScannerImplementation.isStarted()) { - return; - } - - if (stumblingMode == ActiveOrPassiveStumbling.PASSIVE_STUMBLING && - mPassiveScanCount++ > AppGlobals.PASSIVE_MODE_MAX_SCANS_PER_GPS) - { - mPassiveScanCount = 0; - stop(); - return; - } - - final long curTime = System.currentTimeMillis(); - - ArrayList<CellInfo> cells = (sTestingModeCellInfoArray != null)? sTestingModeCellInfoArray : - new ArrayList<CellInfo>(mCellScannerImplementation.getCellInfo()); - - if (mReportWasFlushed.getAndSet(false)) { - clearCells(); - } - - if (cells.isEmpty()) { - return; - } - - for (CellInfo cell : cells) { - addToCells(cell.getCellIdentity()); - } - - Intent intent = new Intent(ACTION_CELLS_SCANNED); - intent.putParcelableArrayListExtra(ACTION_CELLS_SCANNED_ARG_CELLS, cells); - intent.putExtra(ACTION_CELLS_SCANNED_ARG_TIME, curTime); - // send to handler, so broadcast is not from timer thread - Message message = new Message(); - message.obj = intent; - mBroadcastScannedHandler.sendMessage(message); - - } - }, 0, CELL_MIN_UPDATE_TIME); - } - - private synchronized void clearCells() { - mCells.clear(); - } - - private synchronized void addToCells(String cell) { - mCells.add(cell); - } - - public synchronized void stop() { - mReportWasFlushed.set(false); - clearCells(); - LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mReportFlushedReceiver); - - if (mCellScanTimer != null) { - mCellScanTimer.cancel(); - mCellScanTimer = null; - } - mCellScannerImplementation.stop(); - } - - public synchronized int getCellInfoCount() { - return mCells.size(); - } - - private class ReportFlushedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context c, Intent i) { - mReportWasFlushed.set(true); - } - } - - // Note: this reimplements org.mozilla.gecko.util.WeakReferenceHandler because it's not available here. - private static class BroadcastScannedHandler extends Handler { - private WeakReference<CellScanner> mTarget; - - public BroadcastScannedHandler(final CellScanner that) { - super(); - mTarget = new WeakReference<>(that); - } - - @Override - public void handleMessage(Message msg) { - final CellScanner that = mTarget.get(); - if (that == null) { - return; - } - - final Intent intent = (Intent) msg.obj; - LocalBroadcastManager.getInstance(that.mContext).sendBroadcastSync(intent); - } - }; -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java deleted file mode 100644 index c6674a3c4..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java +++ /dev/null @@ -1,299 +0,0 @@ -/* 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.scanners.cellscanner; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.telephony.CellIdentityCdma; -import android.telephony.CellIdentityGsm; -import android.telephony.CellIdentityLte; -import android.telephony.CellIdentityWcdma; -import android.telephony.CellInfoCdma; -import android.telephony.CellInfoGsm; -import android.telephony.CellInfoLte; -import android.telephony.CellInfoWcdma; -import android.telephony.CellLocation; -import android.telephony.CellSignalStrengthCdma; -import android.telephony.CellSignalStrengthGsm; -import android.telephony.CellSignalStrengthLte; -import android.telephony.CellSignalStrengthWcdma; -import android.telephony.NeighboringCellInfo; -import android.telephony.PhoneStateListener; -import android.telephony.SignalStrength; -import android.telephony.TelephonyManager; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public class CellScannerImplementation implements CellScanner.CellScannerImpl { - - protected static String LOG_TAG = AppGlobals.makeLogTag(CellScannerImplementation.class.getSimpleName()); - protected GetAllCellInfoScannerImpl mGetAllInfoCellScanner; - protected TelephonyManager mTelephonyManager; - protected boolean mIsStarted; - protected int mPhoneType; - protected final Context mContext; - - protected volatile int mSignalStrength = CellInfo.UNKNOWN_SIGNAL; - protected volatile int mCdmaDbm = CellInfo.UNKNOWN_SIGNAL; - - private PhoneStateListener mPhoneStateListener; - - private static class GetAllCellInfoScannerDummy implements GetAllCellInfoScannerImpl { - @Override - public List<CellInfo> getAllCellInfo(TelephonyManager tm) { - return Collections.emptyList(); - } - } - - interface GetAllCellInfoScannerImpl { - List<CellInfo> getAllCellInfo(TelephonyManager tm); - } - - public CellScannerImplementation(Context context) { - mContext = context; - } - - public boolean isSupportedOnThisDevice() { - TelephonyManager telephonyManager = mTelephonyManager; - if (telephonyManager == null) { - telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - } - return telephonyManager != null && - (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA || - telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM); - } - - @Override - public synchronized boolean isStarted() { - return mIsStarted; - } - - @Override - public synchronized void start() { - if (mIsStarted || !isSupportedOnThisDevice()) { - return; - } - mIsStarted = true; - - if (mTelephonyManager == null) { - if (Build.VERSION.SDK_INT >= 18 /*Build.VERSION_CODES.JELLY_BEAN_MR2 */) { - mGetAllInfoCellScanner = new GetAllCellInfoScannerMr2(); - } else { - mGetAllInfoCellScanner = new GetAllCellInfoScannerDummy(); - } - - mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - } - - mPhoneStateListener = new PhoneStateListener() { - @Override - public void onSignalStrengthsChanged(SignalStrength ss) { - if (ss.isGsm()) { - mSignalStrength = ss.getGsmSignalStrength(); - } else { - mCdmaDbm = ss.getCdmaDbm(); - } - } - }; - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); - } - - @Override - public synchronized void stop() { - mIsStarted = false; - if (mTelephonyManager != null && mPhoneStateListener != null) { - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); - } - mSignalStrength = CellInfo.UNKNOWN_SIGNAL; - mCdmaDbm = CellInfo.UNKNOWN_SIGNAL; - } - - @Override - public synchronized List<CellInfo> getCellInfo() { - List<CellInfo> records = new ArrayList<CellInfo>(); - - List<CellInfo> allCells = mGetAllInfoCellScanner.getAllCellInfo(mTelephonyManager); - if (allCells.isEmpty()) { - CellInfo currentCell = getCurrentCellInfo(); - if (currentCell == null) { - return records; - } - records.add(currentCell); - }else { - records.addAll(allCells); - } - - // getNeighboringCells() sometimes contains more information than that is already - // in getAllCellInfo(). Use the results of both of them. - records.addAll(getNeighboringCells()); - return records; - } - - private String getNetworkOperator() { - String networkOperator = mTelephonyManager.getNetworkOperator(); - // getNetworkOperator() may be unreliable on CDMA networks - if (networkOperator == null || networkOperator.length() <= 3) { - networkOperator = mTelephonyManager.getSimOperator(); - } - return networkOperator; - } - - protected CellInfo getCurrentCellInfo() { - final CellLocation currentCell = mTelephonyManager.getCellLocation(); - if (currentCell == null) { - return null; - } - - try { - final CellInfo info = new CellInfo(mPhoneType); - final int signalStrength = mSignalStrength; - final int cdmaDbm = mCdmaDbm; - info.setCellLocation(currentCell, - mTelephonyManager.getNetworkType(), - getNetworkOperator(), - signalStrength == CellInfo.UNKNOWN_SIGNAL ? null : signalStrength, - cdmaDbm == CellInfo.UNKNOWN_SIGNAL ? null : cdmaDbm); - return info; - } catch (IllegalArgumentException iae) { - Log.e(LOG_TAG, "Skip invalid or incomplete CellLocation: " + currentCell, iae); - } - return null; - } - - private List<CellInfo> getNeighboringCells() { - // For max fennec compatibility, avoid VERSION_CODES - if (Build.VERSION.SDK_INT >= 22 /* Build.VERSION_CODES.LOLLIPOP_MR1 */) { - return Collections.emptyList(); - } - - @SuppressWarnings("deprecation") - Collection<NeighboringCellInfo> cells = mTelephonyManager.getNeighboringCellInfo(); - if (cells == null || cells.isEmpty()) { - return Collections.emptyList(); - } - - String networkOperator = getNetworkOperator(); - List<CellInfo> records = new ArrayList<CellInfo>(cells.size()); - for (NeighboringCellInfo nci : cells) { - try { - final CellInfo record = new CellInfo(mPhoneType); - record.setNeighboringCellInfo(nci, networkOperator); - if (record.isCellRadioValid()) { - records.add(record); - } - } catch (IllegalArgumentException iae) { - Log.e(LOG_TAG, "Skip invalid or incomplete NeighboringCellInfo: " + nci, iae); - } - } - return records; - } - - - @TargetApi(18) - protected boolean addWCDMACellToList(List<CellInfo> cells, - android.telephony.CellInfo observedCell, - TelephonyManager tm) { - boolean added = false; - if (Build.VERSION.SDK_INT >= 18 && - observedCell instanceof CellInfoWcdma) { - CellIdentityWcdma ident = ((CellInfoWcdma) observedCell).getCellIdentity(); - if (ident.getMnc() != Integer.MAX_VALUE && ident.getMcc() != Integer.MAX_VALUE) { - CellInfo cell = new CellInfo(tm.getPhoneType()); - CellSignalStrengthWcdma strength = ((CellInfoWcdma) observedCell).getCellSignalStrength(); - cell.setWcmdaCellInfo(ident.getMcc(), - ident.getMnc(), - ident.getLac(), - ident.getCid(), - ident.getPsc(), - strength.getAsuLevel()); - cells.add(cell); - added = true; - } - } - return added; - } - - @TargetApi(18) - protected boolean addCellToList(List<CellInfo> cells, - android.telephony.CellInfo observedCell, - TelephonyManager tm) { - if (tm.getPhoneType() == 0) { - return false; - } - - boolean added = false; - if (observedCell instanceof CellInfoGsm) { - CellIdentityGsm ident = ((CellInfoGsm) observedCell).getCellIdentity(); - if (ident.getMcc() != Integer.MAX_VALUE && ident.getMnc() != Integer.MAX_VALUE) { - CellSignalStrengthGsm strength = ((CellInfoGsm) observedCell).getCellSignalStrength(); - CellInfo cell = new CellInfo(tm.getPhoneType()); - cell.setGsmCellInfo(ident.getMcc(), - ident.getMnc(), - ident.getLac(), - ident.getCid(), - strength.getAsuLevel()); - cells.add(cell); - added = true; - } - } else if (observedCell instanceof CellInfoCdma) { - CellInfo cell = new CellInfo(tm.getPhoneType()); - CellIdentityCdma ident = ((CellInfoCdma) observedCell).getCellIdentity(); - CellSignalStrengthCdma strength = ((CellInfoCdma) observedCell).getCellSignalStrength(); - cell.setCdmaCellInfo(ident.getBasestationId(), - ident.getNetworkId(), - ident.getSystemId(), - strength.getDbm()); - cells.add(cell); - added = true; - } else if (observedCell instanceof CellInfoLte) { - CellIdentityLte ident = ((CellInfoLte) observedCell).getCellIdentity(); - if (ident.getMnc() != Integer.MAX_VALUE && ident.getMcc() != Integer.MAX_VALUE) { - CellInfo cell = new CellInfo(tm.getPhoneType()); - CellSignalStrengthLte strength = ((CellInfoLte) observedCell).getCellSignalStrength(); - cell.setLteCellInfo(ident.getMcc(), - ident.getMnc(), - ident.getCi(), - ident.getPci(), - ident.getTac(), - strength.getAsuLevel(), - strength.getTimingAdvance()); - cells.add(cell); - added = true; - } - } - - if (!added && Build.VERSION.SDK_INT >= 18) { - added = addWCDMACellToList(cells, observedCell, tm); - } - - return added; - } - - @TargetApi(18) - private class GetAllCellInfoScannerMr2 implements GetAllCellInfoScannerImpl { - @Override - public List<CellInfo> getAllCellInfo(TelephonyManager tm) { - final List<android.telephony.CellInfo> observed = tm.getAllCellInfo(); - if (observed == null || observed.isEmpty()) { - return Collections.emptyList(); - } - - List<CellInfo> cells = new ArrayList<CellInfo>(observed.size()); - for (android.telephony.CellInfo observedCell : observed) { - if (!addCellToList(cells, observedCell, tm)) { - //Log.i(LOG_TAG, "Skipped CellInfo of unknown class: " + observedCell.toString()); - } - } - return cells; - } - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/AsyncUploader.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/AsyncUploader.java deleted file mode 100644 index 308e35678..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/AsyncUploader.java +++ /dev/null @@ -1,214 +0,0 @@ -/* 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.uploadthread; - -import android.os.AsyncTask; -import android.util.Log; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.mozilla.mozstumbler.service.Prefs; -import org.mozilla.mozstumbler.service.utils.AbstractCommunicator; -import org.mozilla.mozstumbler.service.utils.AbstractCommunicator.SyncSummary; -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager; -import org.mozilla.mozstumbler.service.utils.NetworkUtils; - -/* Only one at a time may be uploading. If executed while another upload is in progress -* it will return immediately, and SyncResult is null. -* -* Threading: -* Uploads on a separate thread. ONLY DataStorageManager is thread-safe, do not call -* preferences, do not call any code that isn't thread-safe. You will cause suffering. -* An exception is made for AppGlobals.isDebug, a false reading is of no consequence. */ -public class AsyncUploader extends AsyncTask<Void, Void, SyncSummary> { - private static final String LOG_TAG = AppGlobals.makeLogTag(AsyncUploader.class.getSimpleName()); - private final AsyncUploadArgs mUploadArgs; - private final Object mListenerLock = new Object(); - private AsyncUploaderListener mListener; - private static final AtomicBoolean sIsUploading = new AtomicBoolean(); - private String mNickname; - - public interface AsyncUploaderListener { - public void onUploadComplete(SyncSummary result); - public void onUploadProgress(); - } - - public static class AsyncUploadArgs { - public final NetworkUtils mNetworkUtils; - public final boolean mShouldIgnoreWifiStatus; - public final boolean mUseWifiOnly; - public AsyncUploadArgs(NetworkUtils networkUtils, - boolean shouldIgnoreWifiStatus, - boolean useWifiOnly) { - mNetworkUtils = networkUtils; - mShouldIgnoreWifiStatus = shouldIgnoreWifiStatus; - mUseWifiOnly = useWifiOnly; - } - } - - public AsyncUploader(AsyncUploadArgs args, AsyncUploaderListener listener) { - mListener = listener; - mUploadArgs = args; - } - - public void setNickname(String name) { - mNickname = name; - } - - public void clearListener() { - synchronized (mListenerLock) { - mListener = null; - } - } - - public static boolean isUploading() { - return sIsUploading.get(); - } - - @Override - protected SyncSummary doInBackground(Void... voids) { - if (sIsUploading.get()) { - // This if-block is not synchronized, don't care, this is an erroneous usage. - Log.d(LOG_TAG, "Usage error: check isUploading first, only one at a time task usage is permitted."); - return null; - } - - sIsUploading.set(true); - SyncSummary result = new SyncSummary(); - Runnable progressListener = null; - - // no need to lock here, lock is checked again later - if (mListener != null) { - progressListener = new Runnable() { - @Override - public void run() { - synchronized (mListenerLock) { - if (mListener != null) { - mListener.onUploadProgress(); - } - } - } - }; - } - - uploadReports(result, progressListener); - - return result; - } - @Override - protected void onPostExecute(SyncSummary result) { - sIsUploading.set(false); - - synchronized (mListenerLock) { - if (mListener != null) { - mListener.onUploadComplete(result); - } - } - } - @Override - protected void onCancelled(SyncSummary result) { - sIsUploading.set(false); - } - - private class Submitter extends AbstractCommunicator { - private static final String SUBMIT_URL = "https://location.services.mozilla.com/v1/submit"; - - @Override - public String getUrlString() { - return SUBMIT_URL; - } - - @Override - public String getNickname(){ - return mNickname; - } - - @Override - public NetworkSendResult cleanSend(byte[] data) { - final NetworkSendResult result = new NetworkSendResult(); - try { - result.bytesSent = this.send(data, ZippedState.eAlreadyZipped); - result.errorCode = 0; - } catch (IOException ex) { - String msg = "Error submitting: " + ex; - if (ex instanceof HttpErrorException) { - result.errorCode = ((HttpErrorException) ex).responseCode; - msg += " Code:" + result.errorCode; - } - Log.e(LOG_TAG, msg); - AppGlobals.guiLogError(msg); - } - return result; - } - } - - private void uploadReports(AbstractCommunicator.SyncSummary syncResult, Runnable progressListener) { - long uploadedObservations = 0; - long uploadedCells = 0; - long uploadedWifis = 0; - - if (!mUploadArgs.mShouldIgnoreWifiStatus && mUploadArgs.mUseWifiOnly && - !mUploadArgs.mNetworkUtils.isWifiAvailable()) { - if (AppGlobals.isDebug) { - Log.d(LOG_TAG, "not on WiFi, not sending"); - } - syncResult.numIoExceptions += 1; - return; - } - - Submitter submitter = new Submitter(); - DataStorageManager dm = DataStorageManager.getInstance(); - - String error = null; - - try { - DataStorageManager.ReportBatch batch = dm.getFirstBatch(); - while (batch != null) { - AbstractCommunicator.NetworkSendResult result = submitter.cleanSend(batch.data); - - if (result.errorCode == 0) { - syncResult.totalBytesSent += result.bytesSent; - - dm.delete(batch.filename); - - uploadedObservations += batch.reportCount; - uploadedWifis += batch.wifiCount; - uploadedCells += batch.cellCount; - } else { - if (result.errorCode / 100 == 4) { - // delete on 4xx, no point in resending - dm.delete(batch.filename); - } else { - DataStorageManager.getInstance().saveCurrentReportsSendBufferToDisk(); - } - syncResult.numIoExceptions += 1; - } - - if (progressListener != null) { - progressListener.run(); - } - - batch = dm.getNextBatch(); - } - } - catch (IOException ex) { - error = ex.toString(); - } - - try { - dm.incrementSyncStats(syncResult.totalBytesSent, uploadedObservations, uploadedCells, uploadedWifis); - } catch (IOException ex) { - error = ex.toString(); - } finally { - if (error != null) { - syncResult.numIoExceptions += 1; - Log.d(LOG_TAG, error); - AppGlobals.guiLogError(error + " (uploadReports)"); - } - submitter.close(); - } - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java deleted file mode 100644 index d6680a161..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java +++ /dev/null @@ -1,138 +0,0 @@ -/* 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.uploadthread; - -import android.app.AlarmManager; -import android.app.IntentService; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.Prefs; -import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager; -import org.mozilla.mozstumbler.service.utils.NetworkUtils; - -// Only if data is queued and device awake: check network availability and upload. -// MozStumbler use: this alarm is periodic and repeating. -// Fennec use: The alarm is single-shot and it is set to run -if there is data in the queue- -// under these conditions: -// 1) Fennec start/pause (actually gecko start which is ~4 sec after Fennec start). -// 2) Changing the pref in Fennec to stumble or not. -// 3) Boot intent (and SD card app available intent). -// -// Threading: -// - scheduled from the stumbler thread -// - triggered from the main thread -// - actual work is done the upload thread (AsyncUploader) -public class UploadAlarmReceiver extends BroadcastReceiver { - private static final String LOG_TAG = AppGlobals.makeLogTag(UploadAlarmReceiver.class.getSimpleName()); - private static final String EXTRA_IS_REPEATING = "is_repeating"; - private static boolean sIsAlreadyScheduled; - - public UploadAlarmReceiver() {} - - public static class UploadAlarmService extends IntentService { - - public UploadAlarmService(String name) { - super(name); - // makes the service START_NOT_STICKY, that is, the service is not auto-restarted - setIntentRedelivery(false); - } - - public UploadAlarmService() { - this(LOG_TAG); - } - - @Override - protected void onHandleIntent(Intent intent) { - if (intent == null) { - return; - } - boolean isRepeating = intent.getBooleanExtra(EXTRA_IS_REPEATING, true); - if (DataStorageManager.getInstance() == null) { - DataStorageManager.createGlobalInstance(this, null); - } - upload(isRepeating); - } - - void upload(boolean isRepeating) { - if (!isRepeating) { - sIsAlreadyScheduled = false; - } - - // Defensive approach: if it is too old, delete all data - long oldestMs = DataStorageManager.getInstance().getOldestBatchTimeMs(); - int maxWeeks = DataStorageManager.getInstance().getMaxWeeksStored(); - if (oldestMs > 0) { - long currentTime = System.currentTimeMillis(); - long msPerWeek = 604800 * 1000; - if (currentTime - oldestMs > maxWeeks * msPerWeek) { - DataStorageManager.getInstance().deleteAll(); - UploadAlarmReceiver.cancelAlarm(this, isRepeating); - return; - } - } - - NetworkUtils networkUtils = new NetworkUtils(this); - if (networkUtils.isWifiAvailable() && - !AsyncUploader.isUploading()) { - Log.d(LOG_TAG, "Alarm upload(), call AsyncUploader"); - AsyncUploader.AsyncUploadArgs settings = - new AsyncUploader.AsyncUploadArgs(networkUtils, - Prefs.getInstance(this).getWifiScanAlways(), - Prefs.getInstance(this).getUseWifiOnly()); - AsyncUploader uploader = new AsyncUploader(settings, null); - uploader.setNickname(Prefs.getInstance(this).getNickname()); - uploader.execute(); - // we could listen for completion and cancel, instead, cancel on next alarm when db empty - } - } - } - - static PendingIntent createIntent(Context c, boolean isRepeating) { - Intent intent = new Intent(c, UploadAlarmReceiver.class); - intent.putExtra(EXTRA_IS_REPEATING, isRepeating); - PendingIntent pi = PendingIntent.getBroadcast(c, 0, intent, 0); - return pi; - } - - public static void cancelAlarm(Context c, boolean isRepeating) { - Log.d(LOG_TAG, "cancelAlarm"); - // this is to stop scheduleAlarm from constantly rescheduling, not to guard cancellation. - sIsAlreadyScheduled = false; - AlarmManager alarmManager = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE); - PendingIntent pi = createIntent(c, isRepeating); - alarmManager.cancel(pi); - } - - public static void scheduleAlarm(Context c, long secondsToWait, boolean isRepeating) { - if (sIsAlreadyScheduled) { - return; - } - - long intervalMsec = secondsToWait * 1000; - Log.d(LOG_TAG, "schedule alarm (ms):" + intervalMsec); - - sIsAlreadyScheduled = true; - AlarmManager alarmManager = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE); - PendingIntent pi = createIntent(c, isRepeating); - - long triggerAtMs = System.currentTimeMillis() + intervalMsec; - if (isRepeating) { - alarmManager.setInexactRepeating(AlarmManager.RTC, triggerAtMs, intervalMsec, pi); - } else { - alarmManager.set(AlarmManager.RTC, triggerAtMs, pi); - } - } - - @Override - public void onReceive(final Context context, Intent intent) { - Intent startServiceIntent = new Intent(context, UploadAlarmService.class); - context.startService(startServiceIntent); - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java deleted file mode 100644 index 70816371a..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java +++ /dev/null @@ -1,158 +0,0 @@ -/* 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.utils; - -import android.os.Build; -import android.util.Log; - -import org.mozilla.mozstumbler.service.AppGlobals; -import org.mozilla.mozstumbler.service.Prefs; - -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; - -public abstract class AbstractCommunicator { - - private static final String LOG_TAG = AppGlobals.makeLogTag(AbstractCommunicator.class.getSimpleName()); - private static final String NICKNAME_HEADER = "X-Nickname"; - private static final String USER_AGENT_HEADER = "User-Agent"; - private HttpURLConnection mHttpURLConnection; - private final String mUserAgent; - private static int sBytesSentTotal = 0; - private static String sMozApiKey; - - public abstract String getUrlString(); - - public static class HttpErrorException extends IOException { - private static final long serialVersionUID = -5404095858043243126L; - public final int responseCode; - - public HttpErrorException(int responseCode) { - super(); - this.responseCode = responseCode; - } - - public boolean isTemporary() { - return responseCode >= 500 && responseCode <= 599; - } - } - - public static class SyncSummary { - public int numIoExceptions; - public int totalBytesSent; - } - - public static class NetworkSendResult { - public int bytesSent; - // Zero is no error, for HTTP error cases, set this code to the error - public int errorCode = -1; - } - - public abstract NetworkSendResult cleanSend(byte[] data); - - public String getNickname() { - return null; - } - - public AbstractCommunicator() { - Prefs prefs = Prefs.getInstanceWithoutContext(); - mUserAgent = (prefs != null)? prefs.getUserAgent() : "fennec-stumbler-unset-user-agent"; - } - - private void openConnectionAndSetHeaders() { - try { - Prefs prefs = Prefs.getInstanceWithoutContext(); - if (sMozApiKey == null || prefs != null) { - sMozApiKey = prefs.getMozApiKey(); - } - URL url = new URL(getUrlString() + "?key=" + sMozApiKey); - mHttpURLConnection = (HttpURLConnection) url.openConnection(); - mHttpURLConnection.setRequestMethod("POST"); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); - } catch (IOException e) { - Log.e(LOG_TAG, "Couldn't open a connection: " + e); - } - mHttpURLConnection.setDoOutput(true); - mHttpURLConnection.setRequestProperty(USER_AGENT_HEADER, mUserAgent); - mHttpURLConnection.setRequestProperty("Content-Type", "application/json"); - - // Workaround for a bug in Android mHttpURLConnection. When the library - // reuses a stale connection, the connection may fail with an EOFException - if (Build.VERSION.SDK_INT > 13 && Build.VERSION.SDK_INT < 19) { - mHttpURLConnection.setRequestProperty("Connection", "Close"); - } - String nickname = getNickname(); - if (nickname != null) { - mHttpURLConnection.setRequestProperty(NICKNAME_HEADER, nickname); - } - } - - private byte[] zipData(byte[] data) throws IOException { - byte[] output = Zipper.zipData(data); - return output; - } - - private void sendData(byte[] data) throws IOException{ - mHttpURLConnection.setFixedLengthStreamingMode(data.length); - OutputStream out = new BufferedOutputStream(mHttpURLConnection.getOutputStream()); - out.write(data); - out.flush(); - int code = mHttpURLConnection.getResponseCode(); - final boolean isSuccessCode2XX = (code/100 == 2); - if (!isSuccessCode2XX) { - throw new HttpErrorException(code); - } - } - - public enum ZippedState { eNotZipped, eAlreadyZipped }; - /* Return the number of bytes sent. */ - public int send(byte[] data, ZippedState isAlreadyZipped) throws IOException { - openConnectionAndSetHeaders(); - String logMsg; - try { - if (isAlreadyZipped != ZippedState.eAlreadyZipped) { - data = zipData(data); - } - mHttpURLConnection.setRequestProperty("Content-Encoding","gzip"); - } catch (IOException e) { - Log.e(LOG_TAG, "Couldn't compress and send data, falling back to plain-text: ", e); - close(); - } - - try { - sendData(data); - } finally { - close(); - } - sBytesSentTotal += data.length; - logMsg = "Send data: " + String.format("%.2f", data.length / 1024.0) + " kB"; - logMsg += " Session Total:" + String.format("%.2f", sBytesSentTotal / 1024.0) + " kB"; - AppGlobals.guiLogInfo(logMsg, "#FFFFCC", true); - Log.d(LOG_TAG, logMsg); - return data.length; - } - - public InputStream getInputStream() { - try { - return mHttpURLConnection.getInputStream(); - } catch (IOException e) { - return mHttpURLConnection.getErrorStream(); - } - } - - public void close() { - if (mHttpURLConnection == null) { - return; - } - mHttpURLConnection.disconnect(); - mHttpURLConnection = null; - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/NetworkUtils.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/NetworkUtils.java deleted file mode 100644 index b3b33b02a..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/NetworkUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -/* 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.utils; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; - -public final class NetworkUtils { - private static final String LOG_TAG = AppGlobals.makeLogTag(NetworkUtils.class.getSimpleName()); - - ConnectivityManager mConnectivityManager; - - public NetworkUtils(Context context) { - mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - } - - public synchronized boolean isWifiAvailable() { - if (mConnectivityManager == null) { - Log.e(LOG_TAG, "ConnectivityManager is null!"); - return false; - } - - NetworkInfo aNet = mConnectivityManager.getActiveNetworkInfo(); - return (aNet != null && aNet.getType() == ConnectivityManager.TYPE_WIFI); - } - -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/PersistentIntentService.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/PersistentIntentService.java deleted file mode 100644 index 8387c7edd..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/PersistentIntentService.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.mozilla.mozstumbler.service.utils; - -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.app.Service; -import android.content.Intent; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; - -/* This code is copied from android IntentService, with stopSelf commented out. */ -public abstract class PersistentIntentService extends Service { - private volatile Looper mServiceLooper; - private volatile ServiceHandler mServiceHandler; - private final String mName; - private boolean mRedelivery; - - private final class ServiceHandler extends Handler { - public ServiceHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - onHandleIntent((Intent) msg.obj); - // stopSelf(msg.arg1); <-- modified from original file - } - } - - public PersistentIntentService(String name) { - super(); - mName = name; - } - - public void setIntentRedelivery(boolean enabled) { - mRedelivery = enabled; - } - - @Override - public void onCreate() { - super.onCreate(); - HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); - thread.start(); - mServiceLooper = thread.getLooper(); - mServiceHandler = new ServiceHandler(mServiceLooper); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = startId; - msg.obj = intent; - mServiceHandler.sendMessage(msg); - return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; - } - - @Override - public void onDestroy() { - mServiceLooper.quit(); - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - protected abstract void onHandleIntent(Intent intent); -} - diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/TelemetryWrapper.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/TelemetryWrapper.java deleted file mode 100644 index 91cde26f2..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/TelemetryWrapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.mozilla.mozstumbler.service.utils; - -import android.util.Log; -import org.mozilla.mozstumbler.service.AppGlobals; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class TelemetryWrapper { - private static final String LOG_TAG = AppGlobals.makeLogTag(TelemetryWrapper.class.getSimpleName()); - private static Method mAddToHistogram; - - public static void addToHistogram(String key, int value) { - if (mAddToHistogram == null) { - try { - Class<?> telemetry = Class.forName("org.mozilla.gecko.Telemetry"); - mAddToHistogram = telemetry.getMethod("addToHistogram", String.class, int.class); - } catch (ClassNotFoundException e) { - Log.d(LOG_TAG, "Class not found!"); - return; - } catch (NoSuchMethodException e) { - Log.d(LOG_TAG, "Method not found!"); - return; - } - } - - if (mAddToHistogram != null) { - try { - mAddToHistogram.invoke(null, key, value); - } - catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { - Log.d(LOG_TAG, "Got exception invoking."); - } - } - } -} diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/Zipper.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/Zipper.java deleted file mode 100644 index 90e0ee7f5..000000000 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/Zipper.java +++ /dev/null @@ -1,48 +0,0 @@ -/* 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.utils; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -public class Zipper { - public static byte[] zipData(byte[] data) throws IOException { - final ByteArrayOutputStream os = new ByteArrayOutputStream(); - GZIPOutputStream gstream = new GZIPOutputStream(os); - byte[] output; - try { - gstream.write(data); - gstream.finish(); - output = os.toByteArray(); - } finally { - gstream.close(); - os.close(); - } - return output; - } - - public static String unzipData(byte[] data) throws IOException { - StringBuilder result = new StringBuilder(); - final ByteArrayInputStream bs = new ByteArrayInputStream(data); - GZIPInputStream gstream = new GZIPInputStream(bs); - try { - InputStreamReader reader = new InputStreamReader(gstream); - BufferedReader in = new BufferedReader(reader); - String read; - while ((read = in.readLine()) != null) { - result.append(read); - } - } finally { - gstream.close(); - bs.close(); - } - return result.toString(); - } -} |