diff --git a/play-services-location-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java b/play-services-location-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java index 0ad9e872..3ec7ac1b 100644 --- a/play-services-location-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java +++ b/play-services-location-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java @@ -22,7 +22,10 @@ import android.content.Context; import android.location.Location; import android.location.LocationManager; import android.os.Binder; +import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; +import android.util.Log; import com.google.android.gms.location.ILocationListener; import com.google.android.gms.location.LocationRequest; @@ -39,17 +42,19 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.location.LocationManager.GPS_PROVIDER; -import static android.location.LocationManager.NETWORK_PROVIDER; import static com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY; import static com.google.android.gms.location.LocationRequest.PRIORITY_NO_POWER; public class GoogleLocationManager implements LocationChangeListener { private static final String TAG = "GmsLocManager"; private static final String MOCK_PROVIDER = "mock"; + private static final long VERIFY_CURRENT_REQUESTS_INTERVAL_MS = 5000; // 5 seconds private static final long SWITCH_ON_FRESHNESS_CLIFF_MS = 30000; // 30 seconds private static final String ACCESS_MOCK_LOCATION = "android.permission.ACCESS_MOCK_LOCATION"; private final Context context; + private final Handler handler; + private final Runnable verifyCurrentRequestsRunnable = this::verifyCurrentRequests; private final RealLocationProvider gpsProvider; private final UnifiedLocationProvider networkProvider; private final MockLocationProvider mockProvider; @@ -69,6 +74,7 @@ public class GoogleLocationManager implements LocationChangeListener { this.networkProvider = null; } mockProvider = new MockLocationProvider(this); + handler = new Handler(Looper.getMainLooper()); } public void invokeOnceReady(Runnable runnable) { @@ -203,6 +209,7 @@ public class GoogleLocationManager implements LocationChangeListener { } catch (RemoteException ignored) { } } + verifyCurrentRequests(); } public void setMockMode(boolean mockMode) { @@ -217,6 +224,22 @@ public class GoogleLocationManager implements LocationChangeListener { mockProvider.setLocation(mockLocation); } + private void verifyCurrentRequests() { + handler.removeCallbacks(verifyCurrentRequestsRunnable); + try { + for (int i = 0; i < currentRequests.size(); i++) { + LocationRequestHelper request = currentRequests.get(i); + if (!request.isActive()) { + removeLocationUpdates(request); + i--; + } + } + } catch (Exception e) { + Log.w(TAG, e); + } + handler.postDelayed(verifyCurrentRequestsRunnable, VERIFY_CURRENT_REQUESTS_INTERVAL_MS); + } + @Override public void onLocationChanged() { for (int i = 0; i < currentRequests.size(); i++) { diff --git a/play-services-location-core/src/main/java/org/microg/gms/location/LocationRequestHelper.java b/play-services-location-core/src/main/java/org/microg/gms/location/LocationRequestHelper.java index ad67ae31..d1991efb 100644 --- a/play-services-location-core/src/main/java/org/microg/gms/location/LocationRequestHelper.java +++ b/play-services-location-core/src/main/java/org/microg/gms/location/LocationRequestHelper.java @@ -89,12 +89,33 @@ public class LocationRequestHelper { this.callback = data.callback; } + public boolean isActive() { + if (!hasCoarsePermission()) return false; + if (listener != null) { + try { + return listener.asBinder().isBinderAlive(); + } catch (Exception e) { + return false; + } + } else if (pendingIntent != null) { + return true; + } else if (callback != null) { + try { + return callback.asBinder().isBinderAlive(); + } catch (Exception e) { + return false; + } + } else { + return false; + } + } + /** * @return whether to continue sending reports to this {@link LocationRequestHelper} */ public boolean report(Location location) { if (location == null) return true; - if (!hasCoarsePermission()) return false; + if (!isActive()) return false; if (lastReport != null) { if (location.getTime() - lastReport.getTime() < locationRequest.getFastestInterval()) { return true; diff --git a/play-services-location-core/src/main/java/org/microg/gms/location/UnifiedLocationProvider.kt b/play-services-location-core/src/main/java/org/microg/gms/location/UnifiedLocationProvider.kt index e56e6c9f..fa952dca 100644 --- a/play-services-location-core/src/main/java/org/microg/gms/location/UnifiedLocationProvider.kt +++ b/play-services-location-core/src/main/java/org/microg/gms/location/UnifiedLocationProvider.kt @@ -82,23 +82,26 @@ class UnifiedLocationProvider(context: Context?, changeListener: LocationChangeL Log.d(TAG, "unified network: no longer requesting location update") client.removeLocationUpdates(listener) connected.set(false) - } else if (!requests.isEmpty()) { + } else if (requests.isNotEmpty()) { var minTime = Long.MAX_VALUE + var maxUpdates = Int.MAX_VALUE val sb = StringBuilder() var opPackageName: String? = null for (request in requests) { if (request.locationRequest.interval < minTime) { opPackageName = request.packageName minTime = request.locationRequest.interval + maxUpdates = request.locationRequest.numUpdates } if (sb.isNotEmpty()) sb.append(", ") sb.append("${request.packageName}:${request.locationRequest.interval}ms") } client.opPackageName = opPackageName - Log.d(TAG, "unified network: requesting location updates with interval ${minTime}ms ($sb)") - if (!connected.get() || connectedMinTime != minTime) { - client.requestLocationUpdates(listener, minTime) + if (minTime <= 0) { + client.forceNextUpdate = true } + Log.d(TAG, "unified network: requesting location updates with interval ${minTime}ms ($sb)") + client.requestLocationUpdates(listener, minTime, maxUpdates) connected.set(true) connectedMinTime = minTime }