Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5e1153d authored by Tim Murray's avatar Tim Murray
Browse files

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
parent 58b9a11b
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -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<Integer, Boolean> mLocationEnabledCache =
            new PropertyInvalidatedCache<Integer, Boolean>(
                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<Location> 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;
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -149,7 +149,13 @@ public class LocationManagerService extends ILocationManager.Stub {

        @Override
        public void onStart() {
            // enable client caches by doing the first invalidate
            LocationManager.invalidateLocalLocationEnabledCaches();

            publishBinderService(Context.LOCATION_SERVICE, mService);
            // disable caching for whatever process contains LocationManagerService
            ((LocationManager) mService.mContext.getSystemService(LocationManager.class))
                    .disableLocalLocationEnabledCaches();
        }

        @Override
@@ -439,6 +445,7 @@ public class LocationManagerService extends ILocationManager.Stub {

    private void onLocationModeChanged(int userId) {
        boolean enabled = mSettingsHelper.isLocationEnabled(userId);
        LocationManager.invalidateLocalLocationEnabledCaches();

        if (D) {
            Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
@@ -2538,6 +2545,8 @@ public class LocationManagerService extends ILocationManager.Stub {
        }
        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
                "Requires WRITE_SECURE_SETTINGS permission");

        LocationManager.invalidateLocalLocationEnabledCaches();
        mSettingsHelper.setLocationEnabled(enabled, userId);
    }