From d2471eea6c0b122531ee978be1188aeff1a897c2 Mon Sep 17 00:00:00 2001 From: Garvan Keeley Date: Thu, 13 Nov 2014 11:54:00 -0500 Subject: [PATCH] Bug 1095914 - Copy over CellScanner from mozstumbler github. r=nalexander This has a few important changes: 1) Null-check the TelephonyManager availability. 2) The cell scanning code was split to remove wcdma scanning on Fennec due to an older API level on Fennec. This is no longer the case. CellScannerNoWCDMA.java renamed to CellScannerImplementation.java. 3) Remove broadcastsync on the timer thread, have the timer thread message back to the owning class through a handler (guaranteed thread-safe mechanism to notify the owning class that work is done). --- .../service/stumblerthread/Reporter.java | 1 + .../stumblerthread/StumblerService.java | 11 -- .../datahandling/DataStorageManager.java | 4 +- .../stumblerthread/scanners/ScanManager.java | 4 - .../scanners/cellscanner/CellScanner.java | 117 +++++++++++------- ...MA.java => CellScannerImplementation.java} | 99 ++++++++++----- .../stumbler/stumbler_sources.mozbuild | 2 +- 7 files changed, 145 insertions(+), 93 deletions(-) rename mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/{CellScannerNoWCDMA.java => CellScannerImplementation.java} (76%) 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 index b3edf6285ae0..0faa47c634b3 100644 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java +++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java @@ -32,6 +32,7 @@ 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. */ 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 index 40b31df3bb4f..0f2648c81ae0 100644 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java +++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java @@ -17,7 +17,6 @@ import org.mozilla.mozstumbler.service.stumblerthread.blocklist.WifiBlockListInt import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager; import org.mozilla.mozstumbler.service.stumblerthread.scanners.ScanManager; import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellScanner; -import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellScannerNoWCDMA; import org.mozilla.mozstumbler.service.uploadthread.UploadAlarmReceiver; import org.mozilla.mozstumbler.service.utils.NetworkUtils; import org.mozilla.mozstumbler.service.utils.PersistentIntentService; @@ -109,10 +108,6 @@ public class StumblerService extends PersistentIntentService return mScanManager.getCellInfoCount(); } - public int getCurrentCellInfoCount() { - return mScanManager.getCurrentCellInfoCount(); - } - public boolean isGeofenced () { return mScanManager.isGeofenced(); } @@ -125,10 +120,6 @@ public class StumblerService extends PersistentIntentService NetworkUtils.createGlobalInstance(this); DataStorageManager.createGlobalInstance(this, this); - if (!CellScanner.isCellScannerImplSet()) { - CellScanner.setCellScannerImpl(new CellScannerNoWCDMA(this)); - } - mReporter.startup(this); } @@ -144,8 +135,6 @@ public class StumblerService extends PersistentIntentService public void onDestroy() { super.onDestroy(); - UploadAlarmReceiver.cancelAlarm(this, !mScanManager.isPassiveMode()); - if (!mScanManager.isScanning()) { return; } 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 index fc70f9647518..00fa336d0ce5 100644 --- 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 @@ -424,8 +424,8 @@ public class DataStorageManager { } mCurrentReports.reports.add(report); - mCurrentReports.wifiCount = wifiCount; - mCurrentReports.cellCount = cellCount; + mCurrentReports.wifiCount += wifiCount; + mCurrentReports.cellCount += cellCount; if (mCurrentReports.reports.size() >= MAX_REPORTS_IN_MEMORY) { // save to disk 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 index 6d8b488b0f8b..5a0b4f25aa23 100644 --- 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 @@ -158,10 +158,6 @@ public class ScanManager { return (mCellScanner == null)? 0 :mCellScanner.getCellInfoCount(); } - public int getCurrentCellInfoCount() { - return (mCellScanner == null)? 0 :mCellScanner.getCurrentCellInfoCount(); - } - public int getLocationCount() { return (mGPSScanner == null)? 0 : mGPSScanner.getLocationCount(); } 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 index 809f6b6c5489..83e7ef95d382 100644 --- 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 @@ -4,21 +4,28 @@ 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.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; - -import org.mozilla.mozstumbler.service.AppGlobals; +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."; @@ -30,47 +37,30 @@ public class CellScanner { private static final long CELL_MIN_UPDATE_TIME = 1000; // milliseconds private final Context mContext; - private static CellScannerImpl sImpl; private Timer mCellScanTimer; private final Set mCells = new HashSet(); - private int mCurrentCellInfoCount; + private final ReportFlushedReceiver mReportFlushedReceiver = new ReportFlushedReceiver(); + private final AtomicBoolean mReportWasFlushed = new AtomicBoolean(); + private Handler mBroadcastScannedHandler; + private final CellScannerImpl mCellScannerImplementation; public ArrayList sTestingModeCellInfoArray; public interface CellScannerImpl { - public void start(); - - public void stop(); - - public List getCellInfo(); + void start(); + boolean isStarted(); + boolean isSupportedOnThisDevice(); + void stop(); + List getCellInfo(); } public CellScanner(Context context) { mContext = context; - } - - private static synchronized CellScannerImpl getImplementation() { - return sImpl; - } - - public static synchronized boolean isCellScannerImplSet() { - return sImpl != null; - } - - /* Fennec doesn't support the apis needed for full scanning, we have different implementations.*/ - public static synchronized void setCellScannerImpl(CellScannerImpl cellScanner) { - sImpl = cellScanner; + mCellScannerImplementation = new CellScannerImplementation(context); } public void start(final ActiveOrPassiveStumbling stumblingMode) { - if (getImplementation() == null) { - return; - } - - try { - getImplementation().start(); - } catch (UnsupportedOperationException uoe) { - Log.e(LOG_TAG, "Cell scanner probe failed", uoe); + if (!mCellScannerImplementation.isSupportedOnThisDevice()) { return; } @@ -78,58 +68,95 @@ public class CellScanner { 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 Handler() { + @Override + public void handleMessage(Message msg) { + Intent intent = (Intent) msg.obj; + LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(intent); + } + }; + + mCellScannerImplementation.start(); + mCellScanTimer = new Timer(); mCellScanTimer.schedule(new TimerTask() { int mPassiveScanCount; @Override public void run() { - if (getImplementation() == null) { + if (!mCellScannerImplementation.isStarted()) { return; } if (stumblingMode == ActiveOrPassiveStumbling.PASSIVE_STUMBLING && - mPassiveScanCount++ > AppGlobals.PASSIVE_MODE_MAX_SCANS_PER_GPS) + mPassiveScanCount++ > AppGlobals.PASSIVE_MODE_MAX_SCANS_PER_GPS) { mPassiveScanCount = 0; stop(); return; } - //if (SharedConstants.isDebug) Log.d(LOG_TAG, "Cell Scanning Timer fired"); + final long curTime = System.currentTimeMillis(); ArrayList cells = (sTestingModeCellInfoArray != null)? sTestingModeCellInfoArray : - new ArrayList(getImplementation().getCellInfo()); + new ArrayList(mCellScannerImplementation.getCellInfo()); + + if (mReportWasFlushed.getAndSet(false)) { + clearCells(); + } - mCurrentCellInfoCount = cells.size(); if (cells.isEmpty()) { return; } - for (CellInfo cell: cells) mCells.add(cell.getCellIdentity()); + + 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); - LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(intent); + // 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); } - public void stop() { + 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; } - if (getImplementation() != null) { - getImplementation().stop(); - } + mCellScannerImplementation.stop(); } - public int getCellInfoCount() { + public synchronized int getCellInfoCount() { return mCells.size(); } - public int getCurrentCellInfoCount() { - return mCurrentCellInfoCount; + private class ReportFlushedReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context c, Intent i) { + mReportWasFlushed.set(true); + } } } diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerNoWCDMA.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java similarity index 76% rename from mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerNoWCDMA.java rename to mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java index b29324664d0b..37f27d8adf89 100644 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerNoWCDMA.java +++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java @@ -10,35 +10,40 @@ 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; -/* Fennec does not yet support the api level for WCDMA import */ -public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { +public class CellScannerImplementation implements CellScanner.CellScannerImpl { - protected static String LOG_TAG = AppGlobals.makeLogTag(CellScannerNoWCDMA.class.getSimpleName()); + 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; - protected volatile int mCdmaDbm; + + protected volatile int mSignalStrength = CellInfo.UNKNOWN_SIGNAL; + protected volatile int mCdmaDbm = CellInfo.UNKNOWN_SIGNAL; private PhoneStateListener mPhoneStateListener; @@ -53,13 +58,28 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { List getAllCellInfo(TelephonyManager tm); } - public CellScannerNoWCDMA(Context context) { + 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 void start() { - if (mIsStarted) { + public synchronized boolean isStarted() { + return mIsStarted; + } + + @Override + public synchronized void start() { + if (mIsStarted || !isSupportedOnThisDevice()) { return; } mIsStarted = true; @@ -72,23 +92,8 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { } mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - if (mTelephonyManager == null) { - throw new UnsupportedOperationException("TelephonyManager service is not available"); - } - - mPhoneType = mTelephonyManager.getPhoneType(); - - if (mPhoneType != TelephonyManager.PHONE_TYPE_GSM - && mPhoneType != TelephonyManager.PHONE_TYPE_CDMA) { - throw new UnsupportedOperationException("Unexpected Phone Type: " + mPhoneType); - } - mSignalStrength = CellInfo.UNKNOWN_SIGNAL; - mCdmaDbm = CellInfo.UNKNOWN_SIGNAL; } - mSignalStrength = CellInfo.UNKNOWN_SIGNAL; - mCdmaDbm = CellInfo.UNKNOWN_SIGNAL; - mPhoneStateListener = new PhoneStateListener() { @Override public void onSignalStrengthsChanged(SignalStrength ss) { @@ -103,9 +108,9 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { } @Override - public void stop() { + public synchronized void stop() { mIsStarted = false; - if (mTelephonyManager != null) { + if (mTelephonyManager != null && mPhoneStateListener != null) { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); } mSignalStrength = CellInfo.UNKNOWN_SIGNAL; @@ -113,7 +118,7 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { } @Override - public List getCellInfo() { + public synchronized List getCellInfo() { List records = new ArrayList(); List allCells = mGetAllInfoCellScanner.getAllCellInfo(mTelephonyManager); @@ -186,10 +191,39 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { return records; } + + @TargetApi(18) + protected boolean addWCDMACellToList(List 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 cells, - android.telephony.CellInfo observedCell, - TelephonyManager tm) { + android.telephony.CellInfo observedCell, + TelephonyManager tm) { + if (tm.getPhoneType() == 0) { + return false; + } + boolean added = false; if (observedCell instanceof CellInfoGsm) { CellIdentityGsm ident = ((CellInfoGsm) observedCell).getCellIdentity(); @@ -226,10 +260,15 @@ public class CellScannerNoWCDMA implements CellScanner.CellScannerImpl { ident.getTac(), strength.getAsuLevel(), strength.getTimingAdvance()); - cells.add(cell); - added = true; + cells.add(cell); + added = true; } } + + if (!added && Build.VERSION.SDK_INT >= 18) { + added = addWCDMACellToList(cells, observedCell, tm); + } + return added; } diff --git a/mobile/android/stumbler/stumbler_sources.mozbuild b/mobile/android/stumbler/stumbler_sources.mozbuild index e721e9df72dc..af27dc4d147e 100644 --- a/mobile/android/stumbler/stumbler_sources.mozbuild +++ b/mobile/android/stumbler/stumbler_sources.mozbuild @@ -17,7 +17,7 @@ stumbler_sources = [ 'java/org/mozilla/mozstumbler/service/stumblerthread/Reporter.java', 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellInfo.java', 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScanner.java', - 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerNoWCDMA.java', + 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/cellscanner/CellScannerImplementation.java', 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/GPSScanner.java', 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/LocationBlockList.java', 'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java',