diff options
| author | 2019-12-13 02:02:20 +0000 | |
|---|---|---|
| committer | 2019-12-13 02:02:20 +0000 | |
| commit | 74798fd9076badd23b9c236e9d3ba78f22636970 (patch) | |
| tree | 85e989007df75f8a6bc4b193785cf52c29ae5fc1 | |
| parent | 24ca88cf305068a7133e5b879735a585d977a66d (diff) | |
| parent | 3f128405bf7da679f00db684be5d524936f2e609 (diff) | |
Merge "Assorted location cleanup"
| -rw-r--r-- | services/core/java/com/android/server/GnssManagerService.java | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LocationManagerService.java | 129 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationSettingsStore.java | 109 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationUsageLogger.java (renamed from services/core/java/com/android/server/LocationUsageLogger.java) | 220 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java | 1 |
5 files changed, 231 insertions, 229 deletions
diff --git a/services/core/java/com/android/server/GnssManagerService.java b/services/core/java/com/android/server/GnssManagerService.java index cbf2a622fd2e..bbcfdc63f3f1 100644 --- a/services/core/java/com/android/server/GnssManagerService.java +++ b/services/core/java/com/android/server/GnssManagerService.java @@ -56,6 +56,7 @@ import com.android.server.location.GnssMeasurementCorrectionsProvider; import com.android.server.location.GnssMeasurementsProvider; import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssStatusListenerHelper; +import com.android.server.location.LocationUsageLogger; import com.android.server.location.RemoteListenerHelper; import java.io.FileDescriptor; diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 6300ab878d49..cad917b073a5 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -104,6 +104,7 @@ import com.android.server.location.LocationRequestStatistics; import com.android.server.location.LocationRequestStatistics.PackageProviderKey; import com.android.server.location.LocationRequestStatistics.PackageStatistics; import com.android.server.location.LocationSettingsStore; +import com.android.server.location.LocationUsageLogger; import com.android.server.location.MockProvider; import com.android.server.location.PassiveProvider; import com.android.server.pm.permission.PermissionManagerServiceInternal; @@ -158,21 +159,15 @@ public class LocationManagerService extends ILocationManager.Stub { } } - private static final String TAG = "LocationManagerService"; + public static final String TAG = "LocationManagerService"; public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); private static final String WAKELOCK_KEY = "*location*"; - // Location resolution level: no location data whatsoever private static final int RESOLUTION_LEVEL_NONE = 0; - // Location resolution level: coarse location data only private static final int RESOLUTION_LEVEL_COARSE = 1; - // Location resolution level: fine location data private static final int RESOLUTION_LEVEL_FINE = 2; - private static final String ACCESS_LOCATION_EXTRA_COMMANDS = - android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; - private static final String NETWORK_LOCATION_SERVICE_ACTION = "com.android.location.service.v3.NetworkLocationProvider"; private static final String FUSED_LOCATION_SERVICE_ACTION = @@ -198,6 +193,8 @@ public class LocationManagerService extends ILocationManager.Stub { private final Object mLock = new Object(); private final Context mContext; private final Handler mHandler; + private final LocationSettingsStore mSettingsStore; + private final LocationUsageLogger mLocationUsageLogger; private AppOpsManager mAppOps; private PackageManager mPackageManager; @@ -205,8 +202,6 @@ public class LocationManagerService extends ILocationManager.Stub { private ActivityManager mActivityManager; private UserManager mUserManager; - private LocationSettingsStore mSettingsStore; - private GeofenceManager mGeofenceManager; private LocationFudger mLocationFudger; private GeocoderProxy mGeocodeProvider; @@ -219,12 +214,12 @@ public class LocationManagerService extends ILocationManager.Stub { // list of currently active providers @GuardedBy("mLock") - private final ArrayList<LocationProvider> mProviders = new ArrayList<>(); + private final ArrayList<LocationProviderManager> mProviders = new ArrayList<>(); // list of non-mock providers, so that when mock providers replace real providers, they can be // later re-replaced @GuardedBy("mLock") - private final ArrayList<LocationProvider> mRealProviders = new ArrayList<>(); + private final ArrayList<LocationProviderManager> mRealProviders = new ArrayList<>(); @GuardedBy("mLock") private final HashMap<Object, Receiver> mReceivers = new HashMap<>(); @@ -251,12 +246,10 @@ public class LocationManagerService extends ILocationManager.Stub { @PowerManager.LocationPowerSaveMode private int mBatterySaverMode; - @GuardedBy("mLock") - private final LocationUsageLogger mLocationUsageLogger; - private LocationManagerService(Context context) { mContext = context; mHandler = FgThread.getHandler(); + mSettingsStore = new LocationSettingsStore(mContext, mHandler); mLocationUsageLogger = new LocationUsageLogger(); // Let the package manager query which are the default location @@ -274,6 +267,8 @@ public class LocationManagerService extends ILocationManager.Stub { } private void onSystemReady() { + mSettingsStore.onSystemReady(); + synchronized (mLock) { mPackageManager = mContext.getPackageManager(); mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -281,7 +276,6 @@ public class LocationManagerService extends ILocationManager.Stub { mActivityManager = mContext.getSystemService(ActivityManager.class); mUserManager = mContext.getSystemService(UserManager.class); - mSettingsStore = new LocationSettingsStore(mContext, mHandler); mLocationFudger = new LocationFudger(mContext, mHandler); mGeofenceManager = new GeofenceManager(mContext, mSettingsStore); @@ -421,14 +415,14 @@ public class LocationManagerService extends ILocationManager.Stub { for (Receiver receiver : mReceivers.values()) { receiver.updateMonitoring(true); } - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @GuardedBy("mLock") private void onPermissionsChangedLocked() { - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @@ -448,7 +442,7 @@ public class LocationManagerService extends ILocationManager.Stub { mBatterySaverMode = newLocationMode; - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @@ -456,7 +450,7 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private void onScreenStateChangedLocked() { if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) { - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @@ -472,7 +466,7 @@ public class LocationManagerService extends ILocationManager.Stub { intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabledForUser(userId)); mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { p.onUseableChangedLocked(userId); } } @@ -527,21 +521,21 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private void onBackgroundThrottleIntervalChangedLocked() { - for (LocationProvider provider : mProviders) { + for (LocationProviderManager provider : mProviders) { applyRequirementsLocked(provider); } } @GuardedBy("mLock") private void onBackgroundThrottleWhitelistChangedLocked() { - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @GuardedBy("lock") private void onIgnoreSettingsWhitelistChangedLocked() { - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { applyRequirementsLocked(p); } } @@ -630,14 +624,15 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private void initializeProvidersLocked() { // create a passive location provider, which is always enabled - LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER); + LocationProviderManager passiveProviderManager = new LocationProviderManager( + PASSIVE_PROVIDER); addProviderLocked(passiveProviderManager); mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager); passiveProviderManager.attachLocked(mPassiveProvider); if (GnssManagerService.isGnssSupported()) { // Create a gps location provider manager - LocationProvider gnssProviderManager = new LocationProvider(GPS_PROVIDER); + LocationProviderManager gnssProviderManager = new LocationProviderManager(GPS_PROVIDER); mRealProviders.add(gnssProviderManager); addProviderLocked(gnssProviderManager); @@ -668,7 +663,8 @@ public class LocationManagerService extends ILocationManager.Stub { ensureFallbackFusedProviderPresentLocked(pkgs); // bind to network provider - LocationProvider networkProviderManager = new LocationProvider(NETWORK_PROVIDER); + LocationProviderManager networkProviderManager = new LocationProviderManager( + NETWORK_PROVIDER); LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind( mContext, networkProviderManager, @@ -685,7 +681,7 @@ public class LocationManagerService extends ILocationManager.Stub { } // bind to fused provider - LocationProvider fusedProviderManager = new LocationProvider(FUSED_PROVIDER); + LocationProviderManager fusedProviderManager = new LocationProviderManager(FUSED_PROVIDER); LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind( mContext, fusedProviderManager, @@ -758,7 +754,7 @@ public class LocationManagerService extends ILocationManager.Stub { Boolean.parseBoolean(fragments[7]) /* supportsBearing */, Integer.parseInt(fragments[8]) /* powerRequirement */, Integer.parseInt(fragments[9]) /* accuracy */); - LocationProvider testProviderManager = new LocationProvider(name); + LocationProviderManager testProviderManager = new LocationProviderManager(name); addProviderLocked(testProviderManager); testProviderManager.attachLocked( new MockProvider(mContext, testProviderManager, properties)); @@ -780,7 +776,7 @@ public class LocationManagerService extends ILocationManager.Stub { onUserProfilesChangedLocked(); // let providers know the current user has changed - for (LocationProvider p : mProviders) { + for (LocationProviderManager p : mProviders) { p.onUseableChangedLocked(oldUserId); p.onUseableChangedLocked(mCurrentUserId); } @@ -789,7 +785,7 @@ public class LocationManagerService extends ILocationManager.Stub { /** * Location provider manager, manages a LocationProvider. */ - class LocationProvider implements AbstractLocationProvider.LocationProviderManager { + class LocationProviderManager implements AbstractLocationProvider.LocationProviderManager { private final String mName; @@ -807,7 +803,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Nullable private ProviderProperties mProperties; - private LocationProvider(String name) { + private LocationProviderManager(String name) { mName = name; mProvider = null; @@ -944,7 +940,7 @@ public class LocationManagerService extends ILocationManager.Stub { return; } synchronized (mLock) { - LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER); + LocationProviderManager gpsProvider = getLocationProviderLocked(GPS_PROVIDER); if (gpsProvider == null || !gpsProvider.isUseableLocked()) { Slog.w(TAG, "reportLocationBatch() called without user permission"); return; @@ -1035,7 +1031,7 @@ public class LocationManagerService extends ILocationManager.Stub { } } - private class MockLocationProvider extends LocationProvider { + private class MockLocationProvider extends LocationProviderManager { private ProviderRequest mCurrentRequest; @@ -1185,7 +1181,8 @@ public class LocationManagerService extends ILocationManager.Stub { // See if receiver has any enabled update records. Also note if any update records // are high power (has a high power provider with an interval under a threshold). for (UpdateRecord updateRecord : mUpdateRecords.values()) { - LocationProvider provider = getLocationProviderLocked(updateRecord.mProvider); + LocationProviderManager provider = getLocationProviderLocked( + updateRecord.mProvider); if (provider == null) { continue; } @@ -1461,7 +1458,7 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void addProviderLocked(LocationProvider provider) { + private void addProviderLocked(LocationProviderManager provider) { Preconditions.checkState(getLocationProviderLocked(provider.getName()) == null); mProviders.add(provider); @@ -1472,7 +1469,7 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void removeProviderLocked(LocationProvider provider) { + private void removeProviderLocked(LocationProviderManager provider) { if (mProviders.remove(provider)) { // it would be more correct to call this for all users, but we know this can only // affect the current user since providers are disabled for non-current users @@ -1482,8 +1479,8 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") @Nullable - private LocationProvider getLocationProviderLocked(String providerName) { - for (LocationProvider provider : mProviders) { + private LocationProviderManager getLocationProviderLocked(String providerName) { + for (LocationProviderManager provider : mProviders) { if (providerName.equals(provider.getName())) { return provider; } @@ -1534,7 +1531,7 @@ public class LocationManagerService extends ILocationManager.Stub { // network and fused providers are ok with COARSE or FINE return RESOLUTION_LEVEL_COARSE; } else { - for (LocationProvider lp : mProviders) { + for (LocationProviderManager lp : mProviders) { if (!lp.getName().equals(provider)) { continue; } @@ -1634,7 +1631,7 @@ public class LocationManagerService extends ILocationManager.Stub { public List<String> getAllProviders() { synchronized (mLock) { ArrayList<String> providers = new ArrayList<>(mProviders.size()); - for (LocationProvider provider : mProviders) { + for (LocationProviderManager provider : mProviders) { String name = provider.getName(); if (FUSED_PROVIDER.equals(name)) { continue; @@ -1655,7 +1652,7 @@ public class LocationManagerService extends ILocationManager.Stub { int allowedResolutionLevel = getCallerAllowedResolutionLevel(); synchronized (mLock) { ArrayList<String> providers = new ArrayList<>(mProviders.size()); - for (LocationProvider provider : mProviders) { + for (LocationProviderManager provider : mProviders) { String name = provider.getName(); if (FUSED_PROVIDER.equals(name)) { continue; @@ -1705,7 +1702,7 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void updateProviderUseableLocked(LocationProvider provider) { + private void updateProviderUseableLocked(LocationProviderManager provider) { boolean useable = provider.isUseableLocked(); ArrayList<Receiver> deadReceivers = null; @@ -1744,14 +1741,14 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private void applyRequirementsLocked(String providerName) { - LocationProvider provider = getLocationProviderLocked(providerName); + LocationProviderManager provider = getLocationProviderLocked(providerName); if (provider != null) { applyRequirementsLocked(provider); } } @GuardedBy("mLock") - private void applyRequirementsLocked(LocationProvider provider) { + private void applyRequirementsLocked(LocationProviderManager provider) { ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName()); WorkSource worksource = new WorkSource(); ProviderRequest providerRequest = new ProviderRequest(); @@ -2201,7 +2198,7 @@ public class LocationManagerService extends ILocationManager.Stub { throw new IllegalArgumentException("provider name must not be null"); } - LocationProvider provider = getLocationProviderLocked(name); + LocationProviderManager provider = getLocationProviderLocked(name); if (provider == null) { throw new IllegalArgumentException("provider doesn't exist: " + name); } @@ -2323,7 +2320,7 @@ public class LocationManagerService extends ILocationManager.Stub { // or use the fused provider String name = request.getProvider(); if (name == null) name = LocationManager.FUSED_PROVIDER; - LocationProvider provider = getLocationProviderLocked(name); + LocationProviderManager provider = getLocationProviderLocked(name); if (provider == null) return null; // only the current user or location providers may get location this way @@ -2453,7 +2450,7 @@ public class LocationManagerService extends ILocationManager.Stub { "Access Fine Location permission not granted to inject Location"); synchronized (mLock) { - LocationProvider provider = getLocationProviderLocked(location.getProvider()); + LocationProviderManager provider = getLocationProviderLocked(location.getProvider()); if (provider == null || !provider.isUseableLocked()) { return false; } @@ -2624,6 +2621,10 @@ public class LocationManagerService extends ILocationManager.Stub { // throw NullPointerException to remain compatible with previous implementation throw new NullPointerException(); } + + mContext.enforceCallingOrSelfPermission( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null); + synchronized (mLock) { checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(), providerName); @@ -2633,13 +2634,7 @@ public class LocationManagerService extends ILocationManager.Stub { LocationStatsEnums.API_SEND_EXTRA_COMMAND, providerName); - // and check for ACCESS_LOCATION_EXTRA_COMMANDS - if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) - != PERMISSION_GRANTED)) { - throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); - } - - LocationProvider provider = getLocationProviderLocked(providerName); + LocationProviderManager provider = getLocationProviderLocked(providerName); if (provider != null) { provider.sendExtraCommand(command, extras); } @@ -2662,7 +2657,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public ProviderProperties getProviderProperties(String providerName) { synchronized (mLock) { - LocationProvider provider = getLocationProviderLocked(providerName); + LocationProviderManager provider = getLocationProviderLocked(providerName); if (provider == null) { return null; } @@ -2675,7 +2670,7 @@ public class LocationManagerService extends ILocationManager.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, Manifest.permission.READ_DEVICE_CONFIG + " permission required"); synchronized (mLock) { - for (LocationProvider provider : mProviders) { + for (LocationProviderManager provider : mProviders) { if (provider.getPackagesLocked().contains(packageName)) { return true; } @@ -2689,7 +2684,7 @@ public class LocationManagerService extends ILocationManager.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, Manifest.permission.READ_DEVICE_CONFIG + " permission required"); synchronized (mLock) { - LocationProvider provider = getLocationProviderLocked(providerName); + LocationProviderManager provider = getLocationProviderLocked(providerName); return provider == null ? Collections.emptyList() : provider.getPackagesLocked(); } } @@ -2758,7 +2753,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (FUSED_PROVIDER.equals(providerName)) return false; synchronized (mLock) { - LocationProvider provider = getLocationProviderLocked(providerName); + LocationProviderManager provider = getLocationProviderLocked(providerName); return provider != null && provider.isUseableLocked(userId); } } @@ -2797,7 +2792,7 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void handleLocationChangedLocked(Location location, LocationProvider provider) { + private void handleLocationChangedLocked(Location location, LocationProviderManager provider) { if (!mProviders.contains(provider)) { return; } @@ -3029,7 +3024,7 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { long identity = Binder.clearCallingIdentity(); try { - LocationProvider oldProvider = getLocationProviderLocked(name); + LocationProviderManager oldProvider = getLocationProviderLocked(name); if (oldProvider != null) { removeProviderLocked(oldProvider); } @@ -3053,7 +3048,7 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { long identity = Binder.clearCallingIdentity(); try { - LocationProvider testProvider = getLocationProviderLocked(name); + LocationProviderManager testProvider = getLocationProviderLocked(name); if (testProvider == null || !testProvider.isMock()) { return; } @@ -3061,8 +3056,8 @@ public class LocationManagerService extends ILocationManager.Stub { removeProviderLocked(testProvider); // reinstate real provider if available - LocationProvider realProvider = null; - for (LocationProvider provider : mRealProviders) { + LocationProviderManager realProvider = null; + for (LocationProviderManager provider : mRealProviders) { if (name.equals(provider.getName())) { realProvider = provider; break; @@ -3086,7 +3081,7 @@ public class LocationManagerService extends ILocationManager.Stub { } synchronized (mLock) { - LocationProvider testProvider = getLocationProviderLocked(providerName); + LocationProviderManager testProvider = getLocationProviderLocked(providerName); if (testProvider == null || !testProvider.isMock()) { throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown"); } @@ -3110,7 +3105,7 @@ public class LocationManagerService extends ILocationManager.Stub { } synchronized (mLock) { - LocationProvider testProvider = getLocationProviderLocked(providerName); + LocationProviderManager testProvider = getLocationProviderLocked(providerName); if (testProvider == null || !testProvider.isMock()) { throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown"); } @@ -3128,7 +3123,7 @@ public class LocationManagerService extends ILocationManager.Stub { } synchronized (mLock) { - LocationProvider testProvider = getLocationProviderLocked(providerName); + LocationProviderManager testProvider = getLocationProviderLocked(providerName); if (testProvider == null || !testProvider.isMock()) { throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown"); } @@ -3237,7 +3232,7 @@ public class LocationManagerService extends ILocationManager.Stub { ipw.println("Location Providers:"); ipw.increaseIndent(); - for (LocationProvider provider : mProviders) { + for (LocationProviderManager provider : mProviders) { provider.dumpLocked(fd, ipw, args); } ipw.decreaseIndent(); diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java index 3d18d4a12e44..f625452975c0 100644 --- a/services/core/java/com/android/server/location/LocationSettingsStore.java +++ b/services/core/java/com/android/server/location/LocationSettingsStore.java @@ -34,6 +34,7 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.SystemConfig; @@ -113,6 +114,16 @@ public class LocationSettingsStore { () -> SystemConfig.getInstance().getAllowIgnoreLocationSettings(), handler); } + /** Called when system is ready. */ + public synchronized void onSystemReady() { + mLocationMode.register(); + mBackgroundThrottleIntervalMs.register(); + mLocationPackageBlacklist.register(); + mLocationPackageWhitelist.register(); + mBackgroundThrottlePackageWhitelist.register(); + mIgnoreSettingsPackageWhitelist.register(); + } + /** * Retrieve if location is enabled or not. */ @@ -300,13 +311,25 @@ public class LocationSettingsStore { private abstract static class ObservingSetting extends ContentObserver { private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners; + private boolean mRegistered; - private ObservingSetting(Context context, String settingName, Handler handler) { + private ObservingSetting(Handler handler) { super(handler); mListeners = new CopyOnWriteArrayList<>(); + } + + protected boolean isRegistered() { + return mRegistered; + } + + protected void register(Context context, Uri uri) { + if (mRegistered) { + return; + } context.getContentResolver().registerContentObserver( - getUriFor(settingName), false, this, UserHandle.USER_ALL); + uri, false, this, UserHandle.USER_ALL); + mRegistered = true; } public void addListener(UserSettingChangedListener listener) { @@ -317,8 +340,6 @@ public class LocationSettingsStore { mListeners.remove(listener); } - protected abstract Uri getUriFor(String settingName); - @Override public void onChange(boolean selfChange, Uri uri, int userId) { for (UserSettingChangedListener listener : mListeners) { @@ -333,20 +354,19 @@ public class LocationSettingsStore { private final String mSettingName; private IntegerSecureSetting(Context context, String settingName, Handler handler) { - super(context, settingName, handler); + super(handler); mContext = context; mSettingName = settingName; } + private void register() { + register(mContext, Settings.Secure.getUriFor(mSettingName)); + } + public int getValueForUser(int defaultValue, int userId) { return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName, defaultValue, userId); } - - @Override - protected Uri getUriFor(String settingName) { - return Settings.Secure.getUriFor(settingName); - } } private static class StringListCachedSecureSetting extends ObservingSetting { @@ -354,31 +374,44 @@ public class LocationSettingsStore { private final Context mContext; private final String mSettingName; - private int mCachedUserId = UserHandle.USER_NULL; + @GuardedBy("this") + private int mCachedUserId; + @GuardedBy("this") private List<String> mCachedValue; private StringListCachedSecureSetting(Context context, String settingName, Handler handler) { - super(context, settingName, handler); + super(handler); mContext = context; mSettingName = settingName; + + mCachedUserId = UserHandle.USER_NULL; + } + + public synchronized void register() { + register(mContext, Settings.Secure.getUriFor(mSettingName)); } public synchronized List<String> getValueForUser(int userId) { Preconditions.checkArgument(userId != UserHandle.USER_NULL); + List<String> value = mCachedValue; if (userId != mCachedUserId) { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), mSettingName, userId); if (TextUtils.isEmpty(setting)) { - mCachedValue = Collections.emptyList(); + value = Collections.emptyList(); } else { - mCachedValue = Arrays.asList(setting.split(",")); + value = Arrays.asList(setting.split(",")); + } + + if (isRegistered()) { + mCachedUserId = userId; + mCachedValue = value; } - mCachedUserId = userId; } - return mCachedValue; + return value; } public synchronized void invalidateForUser(int userId) { @@ -393,11 +426,6 @@ public class LocationSettingsStore { invalidateForUser(userId); super.onChange(selfChange, uri, userId); } - - @Override - protected Uri getUriFor(String settingName) { - return Settings.Secure.getUriFor(settingName); - } } private static class LongGlobalSetting extends ObservingSetting { @@ -406,20 +434,19 @@ public class LocationSettingsStore { private final String mSettingName; private LongGlobalSetting(Context context, String settingName, Handler handler) { - super(context, settingName, handler); + super(handler); mContext = context; mSettingName = settingName; } + public void register() { + register(mContext, Settings.Global.getUriFor(mSettingName)); + } + public long getValue(long defaultValue) { return Settings.Global.getLong(mContext.getContentResolver(), mSettingName, defaultValue); } - - @Override - protected Uri getUriFor(String settingName) { - return Settings.Global.getUriFor(settingName); - } } private static class StringSetCachedGlobalSetting extends ObservingSetting { @@ -428,29 +455,42 @@ public class LocationSettingsStore { private final String mSettingName; private final Supplier<ArraySet<String>> mBaseValuesSupplier; + @GuardedBy("this") private boolean mValid; + @GuardedBy("this") private ArraySet<String> mCachedValue; private StringSetCachedGlobalSetting(Context context, String settingName, Supplier<ArraySet<String>> baseValuesSupplier, Handler handler) { - super(context, settingName, handler); + super(handler); mContext = context; mSettingName = settingName; mBaseValuesSupplier = baseValuesSupplier; + + mValid = false; + } + + public synchronized void register() { + register(mContext, Settings.Global.getUriFor(mSettingName)); } public synchronized Set<String> getValue() { + ArraySet<String> value = mCachedValue; if (!mValid) { - mCachedValue = new ArraySet<>(mBaseValuesSupplier.get()); + value = new ArraySet<>(mBaseValuesSupplier.get()); String setting = Settings.Global.getString(mContext.getContentResolver(), mSettingName); if (!TextUtils.isEmpty(setting)) { - mCachedValue.addAll(Arrays.asList(setting.split(","))); + value.addAll(Arrays.asList(setting.split(","))); + } + + if (isRegistered()) { + mValid = true; + mCachedValue = value; } - mValid = true; } - return mCachedValue; + return value; } public synchronized void invalidate() { @@ -463,10 +503,5 @@ public class LocationSettingsStore { invalidate(); super.onChange(selfChange, uri, userId); } - - @Override - protected Uri getUriFor(String settingName) { - return Settings.Global.getUriFor(settingName); - } } } diff --git a/services/core/java/com/android/server/LocationUsageLogger.java b/services/core/java/com/android/server/location/LocationUsageLogger.java index a8a3cc47cfb0..755438b1a413 100644 --- a/services/core/java/com/android/server/LocationUsageLogger.java +++ b/services/core/java/com/android/server/location/LocationUsageLogger.java @@ -14,37 +14,113 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.location; + +import static com.android.server.LocationManagerService.TAG; import android.app.ActivityManager; import android.location.Geofence; import android.location.LocationManager; import android.location.LocationRequest; -import android.os.SystemClock; import android.stats.location.LocationStatsEnums; import android.util.Log; import android.util.StatsLog; +import com.android.internal.annotations.GuardedBy; + import java.time.Instant; /** * Logger for Location API usage logging. */ public class LocationUsageLogger { - private static final String TAG = "LocationUsageLogger"; - private static final boolean D = Log.isLoggable(TAG, Log.DEBUG); private static final int ONE_SEC_IN_MILLIS = 1000; private static final int ONE_MINUTE_IN_MILLIS = 60000; private static final int ONE_HOUR_IN_MILLIS = 3600000; - private long mLastApiUsageLogHour = 0; + private static final int API_USAGE_LOG_HOURLY_CAP = 60; + @GuardedBy("this") + private long mLastApiUsageLogHour = 0; + @GuardedBy("this") private int mApiUsageLogHourlyCount = 0; - private static final int API_USAGE_LOG_HOURLY_CAP = 60; + /** + * Log a location API usage event. + */ + public void logLocationApiUsage(int usageType, int apiInUse, + String packageName, LocationRequest locationRequest, + boolean hasListener, boolean hasIntent, + Geofence geofence, int activityImportance) { + try { + if (hitApiUsageLogCap()) { + return; + } + + boolean isLocationRequestNull = locationRequest == null; + boolean isGeofenceNull = geofence == null; + + StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, + apiInUse, packageName, + isLocationRequestNull + ? LocationStatsEnums.PROVIDER_UNKNOWN + : bucketizeProvider(locationRequest.getProvider()), + isLocationRequestNull + ? LocationStatsEnums.QUALITY_UNKNOWN + : locationRequest.getQuality(), + isLocationRequestNull + ? LocationStatsEnums.INTERVAL_UNKNOWN + : bucketizeInterval(locationRequest.getInterval()), + isLocationRequestNull + ? LocationStatsEnums.DISTANCE_UNKNOWN + : bucketizeDistance( + locationRequest.getSmallestDisplacement()), + isLocationRequestNull ? 0 : locationRequest.getNumUpdates(), + // only log expireIn for USAGE_STARTED + isLocationRequestNull || usageType == LocationStatsEnums.USAGE_ENDED + ? LocationStatsEnums.EXPIRATION_UNKNOWN + : bucketizeExpireIn(locationRequest.getExpireIn()), + getCallbackType(apiInUse, hasListener, hasIntent), + isGeofenceNull + ? LocationStatsEnums.RADIUS_UNKNOWN + : bucketizeRadius(geofence.getRadius()), + categorizeActivityImportance(activityImportance)); + } catch (Exception e) { + // Swallow exceptions to avoid crashing LMS. + Log.w(TAG, "Failed to log API usage to statsd.", e); + } + } - private static int providerNameToStatsdEnum(String provider) { + /** + * Log a location API usage event. + */ + public void logLocationApiUsage(int usageType, int apiInUse, String providerName) { + try { + if (hitApiUsageLogCap()) { + return; + } + + StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, apiInUse, + /* package_name= */ null, + bucketizeProvider(providerName), + LocationStatsEnums.QUALITY_UNKNOWN, + LocationStatsEnums.INTERVAL_UNKNOWN, + LocationStatsEnums.DISTANCE_UNKNOWN, + /* numUpdates= */ 0, + LocationStatsEnums.EXPIRATION_UNKNOWN, + getCallbackType( + apiInUse, + /* isListenerNull= */ true, + /* isIntentNull= */ true), + /* bucketizedRadius= */ 0, + LocationStatsEnums.IMPORTANCE_UNKNOWN); + } catch (Exception e) { + Log.w(TAG, "Failed to log API usage to statsd.", e); + } + } + + private static int bucketizeProvider(String provider) { if (LocationManager.NETWORK_PROVIDER.equals(provider)) { return LocationStatsEnums.PROVIDER_NETWORK; } else if (LocationManager.GPS_PROVIDER.equals(provider)) { @@ -58,8 +134,7 @@ public class LocationUsageLogger { } } - private static int bucketizeIntervalToStatsdEnum(long interval) { - // LocationManager already converts negative values to 0. + private static int bucketizeInterval(long interval) { if (interval < ONE_SEC_IN_MILLIS) { return LocationStatsEnums.INTERVAL_BETWEEN_0_SEC_AND_1_SEC; } else if (interval < ONE_SEC_IN_MILLIS * 5) { @@ -75,9 +150,8 @@ public class LocationUsageLogger { } } - private static int bucketizeSmallestDisplacementToStatsdEnum(float smallestDisplacement) { - // LocationManager already converts negative values to 0. - if (smallestDisplacement == 0) { + private static int bucketizeDistance(float smallestDisplacement) { + if (smallestDisplacement <= 0) { return LocationStatsEnums.DISTANCE_ZERO; } else if (smallestDisplacement > 0 && smallestDisplacement <= 100) { return LocationStatsEnums.DISTANCE_BETWEEN_0_AND_100; @@ -86,7 +160,7 @@ public class LocationUsageLogger { } } - private static int bucketizeRadiusToStatsdEnum(float radius) { + private static int bucketizeRadius(float radius) { if (radius < 0) { return LocationStatsEnums.RADIUS_NEGATIVE; } else if (radius < 100) { @@ -104,14 +178,11 @@ public class LocationUsageLogger { } } - private static int getBucketizedExpireIn(long expireAt) { - if (expireAt == Long.MAX_VALUE) { + private static int bucketizeExpireIn(long expireIn) { + if (expireIn == Long.MAX_VALUE) { return LocationStatsEnums.EXPIRATION_NO_EXPIRY; } - long elapsedRealtime = SystemClock.elapsedRealtime(); - long expireIn = Math.max(0, expireAt - elapsedRealtime); - if (expireIn < 20 * ONE_SEC_IN_MILLIS) { return LocationStatsEnums.EXPIRATION_BETWEEN_0_AND_20_SEC; } else if (expireIn < ONE_MINUTE_IN_MILLIS) { @@ -129,8 +200,8 @@ public class LocationUsageLogger { if (importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return LocationStatsEnums.IMPORTANCE_TOP; } else if (importance == ActivityManager - .RunningAppProcessInfo - .IMPORTANCE_FOREGROUND_SERVICE) { + .RunningAppProcessInfo + .IMPORTANCE_FOREGROUND_SERVICE) { return LocationStatsEnums.IMPORTANCE_FORGROUND_SERVICE; } else { return LocationStatsEnums.IMPORTANCE_BACKGROUND; @@ -154,117 +225,16 @@ public class LocationUsageLogger { } } - // Update the hourly count of APIUsage log event. - // Returns false if hit the hourly log cap. - private boolean checkApiUsageLogCap() { - if (D) { - Log.d(TAG, "checking APIUsage log cap."); - } - + private synchronized boolean hitApiUsageLogCap() { long currentHour = Instant.now().toEpochMilli() / ONE_HOUR_IN_MILLIS; if (currentHour > mLastApiUsageLogHour) { mLastApiUsageLogHour = currentHour; mApiUsageLogHourlyCount = 0; - return true; + return false; } else { mApiUsageLogHourlyCount = Math.min( - mApiUsageLogHourlyCount + 1, API_USAGE_LOG_HOURLY_CAP); - return mApiUsageLogHourlyCount < API_USAGE_LOG_HOURLY_CAP; - } - } - - /** - * Log a Location API usage event to Statsd. - * Logging event is capped at 60 per hour. Usage events exceeding - * the cap will be dropped by LocationUsageLogger. - */ - public void logLocationApiUsage(int usageType, int apiInUse, - String packageName, LocationRequest locationRequest, - boolean hasListener, boolean hasIntent, - Geofence geofence, int activityImportance) { - try { - if (!checkApiUsageLogCap()) { - return; - } - - boolean isLocationRequestNull = locationRequest == null; - boolean isGeofenceNull = geofence == null; - if (D) { - Log.d(TAG, "log API Usage to statsd. usageType: " + usageType + ", apiInUse: " - + apiInUse + ", packageName: " + (packageName == null ? "" : packageName) - + ", locationRequest: " - + (isLocationRequestNull ? "" : locationRequest.toString()) - + ", hasListener: " + hasListener - + ", hasIntent: " + hasIntent - + ", geofence: " - + (isGeofenceNull ? "" : geofence.toString()) - + ", importance: " + activityImportance); - } - - StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, - apiInUse, packageName, - isLocationRequestNull - ? LocationStatsEnums.PROVIDER_UNKNOWN - : providerNameToStatsdEnum(locationRequest.getProvider()), - isLocationRequestNull - ? LocationStatsEnums.QUALITY_UNKNOWN - : locationRequest.getQuality(), - isLocationRequestNull - ? LocationStatsEnums.INTERVAL_UNKNOWN - : bucketizeIntervalToStatsdEnum(locationRequest.getInterval()), - isLocationRequestNull - ? LocationStatsEnums.DISTANCE_UNKNOWN - : bucketizeSmallestDisplacementToStatsdEnum( - locationRequest.getSmallestDisplacement()), - isLocationRequestNull ? 0 : locationRequest.getNumUpdates(), - // only log expireIn for USAGE_STARTED - isLocationRequestNull || usageType == LocationStatsEnums.USAGE_ENDED - ? LocationStatsEnums.EXPIRATION_UNKNOWN - : getBucketizedExpireIn(locationRequest.getExpireAt()), - getCallbackType(apiInUse, hasListener, hasIntent), - isGeofenceNull - ? LocationStatsEnums.RADIUS_UNKNOWN - : bucketizeRadiusToStatsdEnum(geofence.getRadius()), - categorizeActivityImportance(activityImportance)); - } catch (Exception e) { - // Swallow exceptions to avoid crashing LMS. - Log.w(TAG, "Failed to log API usage to statsd.", e); - } - } - - /** - * Log a Location API usage event to Statsd. - * Logging event is capped at 60 per hour. Usage events exceeding - * the cap will be dropped by LocationUsageLogger. - */ - public void logLocationApiUsage(int usageType, int apiInUse, String providerName) { - try { - if (!checkApiUsageLogCap()) { - return; - } - - if (D) { - Log.d(TAG, "log API Usage to statsd. usageType: " + usageType + ", apiInUse: " - + apiInUse + ", providerName: " + providerName); - } - - StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, apiInUse, - /* package_name= */ null, - providerNameToStatsdEnum(providerName), - LocationStatsEnums.QUALITY_UNKNOWN, - LocationStatsEnums.INTERVAL_UNKNOWN, - LocationStatsEnums.DISTANCE_UNKNOWN, - /* numUpdates= */ 0, - LocationStatsEnums.EXPIRATION_UNKNOWN, - getCallbackType( - apiInUse, - /* isListenerNull= */ true, - /* isIntentNull= */ true), - /* bucketizedRadius= */ 0, - LocationStatsEnums.IMPORTANCE_UNKNOWN); - } catch (Exception e) { - // Swallow exceptions to avoid crashing LMS. - Log.w(TAG, "Failed to log API usage to statsd.", e); + mApiUsageLogHourlyCount + 1, API_USAGE_LOG_HOURLY_CAP); + return mApiUsageLogHourlyCount >= API_USAGE_LOG_HOURLY_CAP; } } } diff --git a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java index 9692c257079d..8b5444c2c55c 100644 --- a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java @@ -61,6 +61,7 @@ import com.android.server.location.GnssMeasurementsProvider.GnssMeasurementProvi import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; import com.android.server.location.GnssStatusListenerHelper; +import com.android.server.location.LocationUsageLogger; import org.junit.Before; import org.junit.Test; |