From 876181e0d84ef0f4f05c8b6b2fd54eb2fd2037dc Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 20 Apr 2022 20:58:08 +0200 Subject: [PATCH] Only update backend helpers on actual changes --- .../microg/nlp/api/AbstractBackendHelper.java | 1 + .../org/microg/nlp/api/CellBackendHelper.java | 128 ++++++++++-------- .../org/microg/nlp/api/WiFiBackendHelper.java | 26 ++-- 3 files changed, 85 insertions(+), 70 deletions(-) diff --git a/api/src/main/java/org/microg/nlp/api/AbstractBackendHelper.java b/api/src/main/java/org/microg/nlp/api/AbstractBackendHelper.java index bfae4c4..53b77c5 100644 --- a/api/src/main/java/org/microg/nlp/api/AbstractBackendHelper.java +++ b/api/src/main/java/org/microg/nlp/api/AbstractBackendHelper.java @@ -14,6 +14,7 @@ public class AbstractBackendHelper { protected final Context context; protected State state = State.DISABLED; protected boolean currentDataUsed = true; + protected long lastUpdate = 0; public AbstractBackendHelper(Context context) { if (context == null) diff --git a/api/src/main/java/org/microg/nlp/api/CellBackendHelper.java b/api/src/main/java/org/microg/nlp/api/CellBackendHelper.java index f8ff8f1..87b9320 100644 --- a/api/src/main/java/org/microg/nlp/api/CellBackendHelper.java +++ b/api/src/main/java/org/microg/nlp/api/CellBackendHelper.java @@ -38,8 +38,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; @@ -57,13 +55,15 @@ import static android.Manifest.permission.READ_PHONE_STATE; public class CellBackendHelper extends AbstractBackendHelper { private final Listener listener; private final TelephonyManager telephonyManager; - private final Set cells = new HashSet<>(); + private Set cells = new HashSet<>(); private PhoneStateListener phoneStateListener; private boolean supportsCellInfoChanged = true; public static final int MIN_UPDATE_INTERVAL = 30 * 1000; public static final int FALLBACK_UPDATE_INTERVAL = 5 * 60 * 1000; + private final static int MAX_AGE = 300000; private long lastScan = 0; + private boolean forceNextUpdate = false; /** * Create a new instance of {@link CellBackendHelper}. Call this in @@ -180,6 +180,8 @@ public class CellBackendHelper extends AbstractBackendHelper { lastScan = System.currentTimeMillis(); if (loadCells(cellInfo)) { listener.onCellsChanged(getCells()); + } else { + Log.d(TAG, "No change in Cell networks"); } } @@ -187,9 +189,8 @@ public class CellBackendHelper extends AbstractBackendHelper { * This will fix empty MNC since Android 9 with 0-prefixed MNCs. * Issue: https://issuetracker.google.com/issues/113560852 */ - @SuppressLint("SoonBlockedPrivateApi") - private void fixEmptyMnc(List cellInfo) { - if (Build.VERSION.SDK_INT < 28 || cellInfo == null) { + private void fixEmptyMnc(Set cells) { + if (Build.VERSION.SDK_INT < 28 || cells == null) { return; } @@ -201,32 +202,36 @@ public class CellBackendHelper extends AbstractBackendHelper { String mnc = networkOperator.substring(3); - for (CellInfo info : cellInfo) { - if (!info.isRegistered()) { + for (Cell cell : cells) { + if (!cell.info.isRegistered()) { continue; } Object identity = null; - if (info instanceof CellInfoGsm) { - identity = ((CellInfoGsm) info).getCellIdentity(); - } else if (info instanceof CellInfoWcdma) { - identity = ((CellInfoWcdma) info).getCellIdentity(); - } else if (info instanceof CellInfoLte) { - identity = ((CellInfoLte) info).getCellIdentity(); + if (cell.info instanceof CellInfoGsm) { + identity = ((CellInfoGsm) cell.info).getCellIdentity(); + } else if (cell.info instanceof CellInfoWcdma) { + identity = ((CellInfoWcdma) cell.info).getCellIdentity(); + } else if (cell.info instanceof CellInfoLte) { + identity = ((CellInfoLte) cell.info).getCellIdentity(); } if (identity == null) { continue; } - try { - Field mncField = CellIdentity.class.getDeclaredField("mMncStr"); - mncField.setAccessible(true); - if (mncField.get(identity) == null) { - mncField.set(identity, mnc); - } - } catch (Exception ignored) { + String mncString = null; + if (identity instanceof CellIdentityGsm) { + mncString = ((CellIdentityGsm) identity).getMncString(); + } else if (identity instanceof CellIdentityWcdma) { + mncString = ((CellIdentityWcdma) identity).getMncString(); + } else if (identity instanceof CellIdentityLte) { + mncString = ((CellIdentityLte) identity).getMncString(); + } + + if (mncString == null) { + cell.mnc = Integer.parseInt(mnc); } } } @@ -235,19 +240,15 @@ public class CellBackendHelper extends AbstractBackendHelper { * This will fix values returned by {@link TelephonyManager#getAllCellInfo()} as described * here: https://github.com/mozilla/ichnaea/issues/340 */ - @SuppressWarnings({"ChainOfInstanceofChecks", "MagicNumber", "ConstantConditions"}) - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - private void fixShortMncBug(List cellInfo) { - if (cellInfo == null) return; + private void fixShortMncBug(Set cells) { + if (cells == null) return; String networkOperator = telephonyManager.getNetworkOperator(); if (networkOperator.length() != 5) return; int realMnc = Integer.parseInt(networkOperator.substring(3)); boolean theBug = false; - for (CellInfo info : cellInfo) { - if (info instanceof CellInfoCdma) return; - if (info.isRegistered()) { - Cell cell = parseCellInfo(info); - if (cell == null) continue; + for (Cell cell : cells) { + if (cell.info instanceof CellInfoCdma) return; + if (cell.info.isRegistered()) { int infoMnc = cell.getMnc(); if (infoMnc == (realMnc * 10 + 15)) { theBug = true; @@ -255,25 +256,25 @@ public class CellBackendHelper extends AbstractBackendHelper { } } if (theBug) { - for (CellInfo info : cellInfo) { + for (Cell cell : cells) { Object identity = null; - if (info instanceof CellInfoGsm) - identity = ((CellInfoGsm) info).getCellIdentity(); - else if (info instanceof CellInfoLte) - identity = ((CellInfoLte) info).getCellIdentity(); - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && - info instanceof CellInfoWcdma) - identity = ((CellInfoWcdma) info).getCellIdentity(); + if (cell.info instanceof CellInfoGsm) + identity = ((CellInfoGsm) cell.info).getCellIdentity(); + else if (cell.info instanceof CellInfoLte) + identity = ((CellInfoLte) cell.info).getCellIdentity(); + else if (Build.VERSION.SDK_INT >= 18 && cell.info instanceof CellInfoWcdma) + identity = ((CellInfoWcdma) cell.info).getCellIdentity(); if (identity == null) continue; - try { - Field mncField = identity.getClass().getDeclaredField("mMnc"); - mncField.setAccessible(true); - int mnc = (Integer) mncField.get(identity); - if (mnc >= 25 && mnc <= 1005) { - mnc = (mnc - 15) / 10; - mncField.setInt(identity, mnc); - } - } catch (Exception ignored) { + int mnc = -1; + if (identity instanceof CellIdentityGsm) { + mnc = ((CellIdentityGsm) identity).getMnc(); + } else if (Build.VERSION.SDK_INT >= 18 && identity instanceof CellIdentityWcdma) { + mnc = ((CellIdentityWcdma) identity).getMnc(); + } else if (identity instanceof CellIdentityLte) { + mnc = ((CellIdentityLte) identity).getMnc(); + } + if (mnc >= 25 && mnc <= 1005) { + cell.mnc = (mnc - 15) / 10; } } } @@ -321,18 +322,16 @@ public class CellBackendHelper extends AbstractBackendHelper { @SuppressWarnings("unchecked") @SuppressLint({"DiscouragedPrivateApi", "deprecation"}) private synchronized boolean loadCells(List cellInfo) { - int oldHash = cells.hashCode(); - cells.clear(); - currentDataUsed = false; + Set cells = new HashSet<>(); try { if (cellInfo != null) { - fixEmptyMnc(cellInfo); - fixShortMncBug(cellInfo); for (CellInfo info : cellInfo) { Cell cell = parseCellInfo(info); if (cell == null) continue; cells.add(cell); } + fixEmptyMnc(cells); + fixShortMncBug(cells); } Method getNeighboringCellInfo = TelephonyManager.class.getDeclaredMethod("getNeighboringCellInfo"); List neighboringCellInfo = (List) getNeighboringCellInfo.invoke(telephonyManager); @@ -349,14 +348,17 @@ public class CellBackendHelper extends AbstractBackendHelper { } if (state == State.DISABLING) state = State.DISABLED; - switch (state) { - default: - case DISABLED: - return false; - case SCANNING: + if (!cells.equals(this.cells) || lastUpdate == 0 || forceNextUpdate) { + this.cells = cells; + lastUpdate = System.currentTimeMillis(); + currentDataUsed = false; + forceNextUpdate = false; + if (state == State.SCANNING) { state = State.WAITING; - return cells.hashCode() != oldHash; + } + return state != State.DISABLED; } + return false; } public synchronized Set getCells() { @@ -379,6 +381,7 @@ public class CellBackendHelper extends AbstractBackendHelper { @Override public void onCellInfoChanged(List cellInfo) { if (cellInfo != null && !cellInfo.isEmpty()) { + forceNextUpdate = true; onCellsChanged(cellInfo); } else if (supportsCellInfoChanged) { supportsCellInfoChanged = false; @@ -409,6 +412,7 @@ public class CellBackendHelper extends AbstractBackendHelper { }, new TelephonyManager.CellInfoCallback() { @Override public void onCellInfo(List cellInfo) { + forceNextUpdate = true; handleAllCellInfo(cellInfo); } }); @@ -450,7 +454,7 @@ public class CellBackendHelper extends AbstractBackendHelper { @Override public synchronized void onUpdate() { - if (!currentDataUsed) { + if (!currentDataUsed && System.currentTimeMillis() - lastUpdate < MAX_AGE) { listener.onCellsChanged(getCells()); } else { state = State.SCANNING; @@ -470,6 +474,7 @@ public class CellBackendHelper extends AbstractBackendHelper { } public static class Cell { + private CellInfo info; private CellType type; private int mcc; private int mnc; @@ -478,6 +483,11 @@ public class CellBackendHelper extends AbstractBackendHelper { private int psc; private int signal; + private Cell(CellInfo info, CellType type, int mcc, int mnc, int lac, long cid, int psc, int signal) { + this(type, mcc, mnc, lac, cid, psc, signal); + this.info = info; + } + public Cell(CellType type, int mcc, int mnc, int lac, long cid, int psc, int signal) { if (type == null) throw new IllegalArgumentException("Each cell has an type!"); diff --git a/api/src/main/java/org/microg/nlp/api/WiFiBackendHelper.java b/api/src/main/java/org/microg/nlp/api/WiFiBackendHelper.java index c336044..72adc36 100644 --- a/api/src/main/java/org/microg/nlp/api/WiFiBackendHelper.java +++ b/api/src/main/java/org/microg/nlp/api/WiFiBackendHelper.java @@ -13,6 +13,7 @@ import android.content.IntentFilter; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.os.Build; +import android.util.Log; import java.util.HashSet; import java.util.List; @@ -31,10 +32,10 @@ import static android.Manifest.permission.CHANGE_WIFI_STATE; public class WiFiBackendHelper extends AbstractBackendHelper { private final static IntentFilter wifiBroadcastFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + private final static int MAX_AGE = 60000; private final Listener listener; private final WifiManager wifiManager; - private final Set wiFis = new HashSet<>(); private final BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -42,6 +43,7 @@ public class WiFiBackendHelper extends AbstractBackendHelper { } }; + private Set wiFis = new HashSet<>(); private boolean ignoreNomap = true; /** @@ -90,7 +92,7 @@ public class WiFiBackendHelper extends AbstractBackendHelper { * Call this in {@link LocationBackendService#update()}. */ public synchronized void onUpdate() { - if (!currentDataUsed) { + if (!currentDataUsed && System.currentTimeMillis() - lastUpdate < MAX_AGE) { listener.onWiFisChanged(getWiFis()); } else { scanWiFis(); @@ -105,6 +107,8 @@ public class WiFiBackendHelper extends AbstractBackendHelper { private void onWiFisChanged() { if (loadWiFis()) { listener.onWiFisChanged(getWiFis()); + } else { + Log.d(TAG, "No change in WiFi networks"); } } @@ -128,9 +132,7 @@ public class WiFiBackendHelper extends AbstractBackendHelper { } private synchronized boolean loadWiFis() { - int oldHash = wiFis.hashCode(); - wiFis.clear(); - currentDataUsed = false; + Set wiFis = new HashSet<>(); List scanResults = wifiManager.getScanResults(); for (ScanResult scanResult : scanResults) { if (ignoreNomap && scanResult.SSID.toLowerCase(Locale.US).endsWith("_nomap")) continue; @@ -138,14 +140,16 @@ public class WiFiBackendHelper extends AbstractBackendHelper { } if (state == State.DISABLING) state = State.DISABLED; - switch (state) { - default: - case DISABLED: - return false; - case SCANNING: + if (!wiFis.equals(this.wiFis) || lastUpdate == 0) { + this.wiFis = wiFis; + lastUpdate = System.currentTimeMillis(); + currentDataUsed = false; + if (state == State.SCANNING) { state = State.WAITING; - return wiFis.hashCode() != oldHash; + } + return state != State.DISABLED; } + return false; } @SuppressWarnings("MagicNumber")