From b5e1153d03dc5e830519a21224f308248450fae4 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 12 Nov 2019 18:23:50 -0800 Subject: LocationManager: cache isLocationEnabledForUser This method is in the hot path for all location tasks but whether location is enabled for a particular user doesn't change that often. Cache the result and invalidate from system_server in order to reduce CPU consumption. Test: boots, works, gets location Bug: 140788621 Change-Id: I84ad2c570e7024187a728071dcbb6f72b177e17a --- .../java/android/location/LocationManager.java | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'location') diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 19085bff0033..6028a8a90141 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -35,6 +35,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.app.AlarmManager; import android.app.PendingIntent; +import android.app.PropertyInvalidatedCache; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; @@ -84,6 +85,23 @@ import java.util.function.Consumer; @RequiresFeature(PackageManager.FEATURE_LOCATION) public class LocationManager { + @GuardedBy("mLock") + private PropertyInvalidatedCache mLocationEnabledCache = + new PropertyInvalidatedCache( + 4, + CACHE_KEY_LOCATION_ENABLED_PROPERTY) { + @Override + protected Boolean recompute(Integer userHandle) { + try { + return mService.isLocationEnabledForUser(userHandle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + }; + + private final Object mLock = new Object(); + /** * For apps targeting Android K and above, supplied {@link PendingIntent}s must be targeted to a * specific package. @@ -462,6 +480,13 @@ public class LocationManager { */ @SystemApi public boolean isLocationEnabledForUser(@NonNull UserHandle userHandle) { + synchronized (mLock) { + if (mLocationEnabledCache != null) { + return mLocationEnabledCache.query(userHandle.getIdentifier()); + } + } + + // fallback if cache is disabled try { return mService.isLocationEnabledForUser(userHandle.getIdentifier()); } catch (RemoteException e) { @@ -3107,6 +3132,29 @@ public class LocationManager { public void onLocationBatch(List locations) { execute((listener) -> listener.onLocationBatch(locations)); } + + } + } + + /** + * @hide + */ + public static final String CACHE_KEY_LOCATION_ENABLED_PROPERTY = + "cache_key.location_enabled"; + + /** + * @hide + */ + public static void invalidateLocalLocationEnabledCaches() { + PropertyInvalidatedCache.invalidateCache(CACHE_KEY_LOCATION_ENABLED_PROPERTY); + } + + /** + * @hide + */ + public void disableLocalLocationEnabledCaches() { + synchronized (mLock) { + mLocationEnabledCache = null; } } } -- cgit v1.2.3