From 03b610a3f8e5874517761621c9cfeec0c7013c1d Mon Sep 17 00:00:00 2001 From: Alexey Illarionov Date: Sat, 25 Jan 2014 23:56:30 +0400 Subject: [PATCH] Optionally use the new getAllCellInfo API (#72) --- .../mozstumbler/cellscanner/CellInfo.java | 48 +++++ .../cellscanner/DefaultCellScanner.java | 172 +++++++++++++++--- 2 files changed, 199 insertions(+), 21 deletions(-) diff --git a/src/org/mozilla/mozstumbler/cellscanner/CellInfo.java b/src/org/mozilla/mozstumbler/cellscanner/CellInfo.java index a9f57e58f..0cc4e1e00 100644 --- a/src/org/mozilla/mozstumbler/cellscanner/CellInfo.java +++ b/src/org/mozilla/mozstumbler/cellscanner/CellInfo.java @@ -219,6 +219,54 @@ void setNeighboringCellInfo(NeighboringCellInfo nci, String networkOperator) { 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; + } + + 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); diff --git a/src/org/mozilla/mozstumbler/cellscanner/DefaultCellScanner.java b/src/org/mozilla/mozstumbler/cellscanner/DefaultCellScanner.java index 74d558344..649ce2851 100644 --- a/src/org/mozilla/mozstumbler/cellscanner/DefaultCellScanner.java +++ b/src/org/mozilla/mozstumbler/cellscanner/DefaultCellScanner.java @@ -1,7 +1,21 @@ package org.mozilla.mozstumbler.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; @@ -17,6 +31,8 @@ public class DefaultCellScanner implements CellScanner.CellScannerImpl { private static final String LOGTAG = DefaultCellScanner.class.getName(); + private static final GetAllCellInfoScannerImpl sGetAllInfoCellScanner; + private final TelephonyManager mTelephonyManager; private final int mPhoneType; @@ -24,6 +40,18 @@ public class DefaultCellScanner implements CellScanner.CellScannerImpl { private volatile int mSignalStrength; private volatile int mCdmaDbm; + interface GetAllCellInfoScannerImpl { + List getAllCellInfo(TelephonyManager tm); + } + + static { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + sGetAllInfoCellScanner = new GetAllCellInfoScannerMr2(); + }else { + sGetAllInfoCellScanner = new GetAllCellInfoScannerDummy(); + } + } + DefaultCellScanner(Context context) { mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (mTelephonyManager == null) { @@ -56,42 +84,71 @@ public void stop() { @Override public List getCellInfo() { - String networkOperator; - final CellLocation cl = mTelephonyManager.getCellLocation(); - if (cl == null) { - return Collections.emptyList(); + List records = new ArrayList(); + + List allCells = sGetAllInfoCellScanner.getAllCellInfo(mTelephonyManager); + if (allCells.isEmpty()) { + CellInfo currentCell = getCurrentCellInfo(); + if (currentCell == null) { + return records; + } + records.add(currentCell); + }else { + records.addAll(allCells); } - Collection cells = mTelephonyManager.getNeighboringCellInfo(); - networkOperator = mTelephonyManager.getNetworkOperator(); + // 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(); } - final List records = new ArrayList(1 + (cells == null ? 0 : cells.size())); - final CellInfo info = new CellInfo(mPhoneType); + return networkOperator; + } + + private CellInfo getCurrentCellInfo() { + final CellLocation currentCell; + 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(cl, + info.setCellLocation(currentCell, mTelephonyManager.getNetworkType(), - networkOperator, + getNetworkOperator(), signalStrength == CellInfo.UNKNOWN_SIGNAL ? null : signalStrength, cdmaDbm == CellInfo.UNKNOWN_SIGNAL ? null : cdmaDbm); - records.add(info); + return info; } catch (IllegalArgumentException iae) { - Log.e(LOGTAG, "Skip invalid or incomplete CellLocation: " + cl, iae); + Log.e(LOGTAG, "Skip invalid or incomplete CellLocation: " + currentCell, iae); } + return null; + } - if (cells != null) { - for (NeighboringCellInfo nci : cells) { - try { - final CellInfo record = new CellInfo(mPhoneType); - record.setNeighboringCellInfo(nci, networkOperator); - records.add(record); - } catch (IllegalArgumentException iae) { - Log.e(LOGTAG, "Skip invalid or incomplete NeighboringCellInfo: " + nci, iae); - } + private List getNeighboringCells() { + Collection cells = mTelephonyManager.getNeighboringCellInfo(); + if (cells == null || cells.isEmpty()) { + return Collections.emptyList(); + } + + String networkOperator = getNetworkOperator(); + List records = new ArrayList(cells.size()); + for (NeighboringCellInfo nci : cells) { + try { + final CellInfo record = new CellInfo(mPhoneType); + record.setNeighboringCellInfo(nci, networkOperator); + records.add(record); + } catch (IllegalArgumentException iae) { + Log.e(LOGTAG, "Skip invalid or incomplete NeighboringCellInfo: " + nci, iae); } } return records; @@ -107,4 +164,77 @@ public void onSignalStrengthsChanged(SignalStrength ss) { } } }; + + private static class GetAllCellInfoScannerDummy implements GetAllCellInfoScannerImpl { + @Override + public List getAllCellInfo(TelephonyManager tm) { + return Collections.emptyList(); + } + } + + @TargetApi(18) + private static class GetAllCellInfoScannerMr2 implements GetAllCellInfoScannerImpl { + @Override + public List getAllCellInfo(TelephonyManager tm) { + final List observed = tm.getAllCellInfo(); + if (observed == null || observed.isEmpty()) { + return Collections.emptyList(); + } + + List cells = new ArrayList(observed.size()); + for (android.telephony.CellInfo observedCell : observed) { + 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); + } + } 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); + } else if (observedCell instanceof CellInfoLte) { + CellIdentityLte ident = ((CellInfoLte) observedCell).getCellIdentity(); + if (ident.getMnc() != Integer.MAX_VALUE && ident.getMnc() != 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()); + } + } else if (observedCell instanceof CellInfoWcdma) { + CellIdentityWcdma ident = ((CellInfoWcdma) observedCell).getCellIdentity(); + if (ident.getMnc() != Integer.MAX_VALUE && ident.getMnc() != 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); + } + } else { + Log.i(LOGTAG, "Skipped CellInfo of unknown class: " + observedCell.toString()); + } + } + return cells; + } + } }