diff options
author | Soonil Nagarkar <sooniln@google.com> | 2019-12-04 16:05:08 -0800 |
---|---|---|
committer | Soonil Nagarkar <sooniln@google.com> | 2019-12-05 12:22:57 -0800 |
commit | 06e37f67de54ea047039ef9a98eb37861ece89c7 (patch) | |
tree | 2db3714a89202e62b7104902a8d7b445353bffab | |
parent | 4d4e91db5e61aa5765b28a4afdaae7ee915cabc6 (diff) |
Update location broadcast behavior
Updates location broadcast behavior in preparation for future changes
that will remove writes to LOCATION_PROVIDERS_ALLOWED. These changes
ensure that clients can properly listen for changes to provider enabled
status without being reliant on the deprecated
LOCATION_PROVIDERS_ALLOWED.
Bug: 145752928
Test: presubmits
Change-Id: I073749a895a6a206023290d83ea815a361353460
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | location/java/android/location/LocationManager.java | 35 | ||||
-rw-r--r-- | services/core/java/com/android/server/LocationManagerService.java | 144 |
3 files changed, 100 insertions, 81 deletions
diff --git a/api/current.txt b/api/current.txt index 884bc5aa73a8..db575ef93c64 100644 --- a/api/current.txt +++ b/api/current.txt @@ -23263,6 +23263,8 @@ package android.location { method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback); method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback); method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback); + field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED"; + field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED"; field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME"; field public static final String GPS_PROVIDER = "gps"; field public static final String KEY_LOCATION_CHANGED = "location"; diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index c0041722c475..1f8c1d5352b0 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -164,25 +164,52 @@ public class LocationManager { * Broadcast intent action when the set of enabled location providers changes. To check the * status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider - * whose state has changed. + * whose state has changed. From Android R and above, will include a boolean intent extra, + * {@link #EXTRA_PROVIDER_ENABLED}, with the enabled state of the provider. * * @see #EXTRA_PROVIDER_NAME + * @see #EXTRA_PROVIDER_ENABLED + * @see #isProviderEnabled(String) */ public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED"; /** * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name - * of the location provider that has changed, to be used with location provider APIs. + * of the location provider that has changed. + * + * @see #PROVIDERS_CHANGED_ACTION + * @see #EXTRA_PROVIDER_ENABLED */ public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME"; /** - * Broadcast intent action when the device location mode changes. To check the location mode, - * use {@link #isLocationEnabled()}. + * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the + * boolean enabled state of the location provider that has changed. + * + * @see #PROVIDERS_CHANGED_ACTION + * @see #EXTRA_PROVIDER_NAME + */ + public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED"; + + /** + * Broadcast intent action when the device location enabled state changes. From Android R and + * above, will include a boolean intent extra, {@link #EXTRA_LOCATION_ENABLED}, with the enabled + * state of location. + * + * @see #EXTRA_LOCATION_ENABLED + * @see #isLocationEnabled() */ public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED"; /** + * Intent extra included with {@link #MODE_CHANGED_ACTION} broadcasts, containing the boolean + * enabled state of location. + * + * @see #MODE_CHANGED_ACTION + */ + public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED"; + + /** * Broadcast intent action indicating that a high power location requests * has either started or stopped being active. The current state of * active location requests should be read from AppOpsManager using diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index f3089c1092e6..c7c6dcffbb5f 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -81,6 +81,7 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -339,7 +340,7 @@ public class LocationManagerService extends ILocationManager.Stub { mSettingsStore.addOnLocationEnabledChangedListener((userId) -> { synchronized (mLock) { - onLocationModeChangedLocked(userId, true); + onLocationModeChangedLocked(userId); } }); mSettingsStore.addOnLocationProvidersAllowedChangedListener((userId) -> { @@ -467,36 +468,24 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void onLocationModeChangedLocked(int userId, boolean broadcast) { - if (!isCurrentProfileLocked(userId)) { - return; - } - + private void onLocationModeChangedLocked(int userId) { if (D) { - Log.d(TAG, "location enabled is now " + isLocationEnabled()); + Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId)); } - for (LocationProvider p : mProviders) { - p.onLocationModeChangedLocked(); - } + Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); + intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabled()); + mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); - if (broadcast) { - // needs to be sent to everyone because we don't know which user may have changed - // LOCATION_MODE state. - mContext.sendBroadcastAsUser( - new Intent(LocationManager.MODE_CHANGED_ACTION), - UserHandle.ALL); + for (LocationProvider p : mProviders) { + p.onLocationModeChangedLocked(userId); } } @GuardedBy("mLock") private void onProviderAllowedChangedLocked(int userId) { - if (!isCurrentProfileLocked(userId)) { - return; - } - for (LocationProvider p : mProviders) { - p.onAllowedChangedLocked(); + p.onAllowedChangedLocked(userId); } } @@ -798,21 +787,14 @@ public class LocationManagerService extends ILocationManager.Stub { Log.d(TAG, "foreground user is changing to " + userId); } - // let providers know the current user is on the way out before changing the user - for (LocationProvider p : mProviders) { - p.onUserChangingLocked(); - } - + int oldUserId = userId; mCurrentUserId = userId; onUserProfilesChangedLocked(); - // if the user changes, per-user settings may also have changed - onLocationModeChangedLocked(userId, false); - onProviderAllowedChangedLocked(userId); - - // always force useability to be rechecked, even if no per-user settings have changed + // let providers know the current user has changed for (LocationProvider p : mProviders) { - p.onUseableChangedLocked(false); + p.onCurrentUserChangedLocked(oldUserId); + p.onCurrentUserChangedLocked(mCurrentUserId); } } @@ -832,7 +814,7 @@ public class LocationManagerService extends ILocationManager.Stub { protected AbstractLocationProvider mProvider; @GuardedBy("mLock") - private boolean mUseable; // combined state + private SparseArray<Boolean> mUseable; // combined state for each user id @GuardedBy("mLock") private boolean mAllowed; // state of LOCATION_PROVIDERS_ALLOWED @GuardedBy("mLock") @@ -851,7 +833,7 @@ public class LocationManagerService extends ILocationManager.Stub { mIsManagedBySettings = isManagedBySettings; mProvider = null; - mUseable = false; + mUseable = new SparseArray<>(1); mAllowed = !mIsManagedBySettings; mEnabled = false; mProperties = null; @@ -876,7 +858,10 @@ public class LocationManagerService extends ILocationManager.Stub { } mProvider = provider; - onUseableChangedLocked(false); + + // 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 + onUseableChangedLocked(false, mCurrentUserId); } public String getName() { @@ -943,8 +928,8 @@ public class LocationManagerService extends ILocationManager.Stub { pw.increaseIndent(); - pw.println("useable=" + mUseable); - if (!mUseable) { + pw.println("useable=" + isUseableLocked(mCurrentUserId)); + if (!isUseableLocked(mCurrentUserId)) { pw.println("attached=" + (mProvider != null)); if (mIsManagedBySettings) { pw.println("allowed=" + mAllowed); @@ -1009,7 +994,10 @@ public class LocationManagerService extends ILocationManager.Stub { } mEnabled = enabled; - onUseableChangedLocked(false); + + // 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 + onUseableChangedLocked(false, mCurrentUserId); } } @@ -1021,12 +1009,20 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - public void onLocationModeChangedLocked() { - onUseableChangedLocked(false); + public void onLocationModeChangedLocked(int userId) { + if (!isCurrentProfileLocked(userId)) { + return; + } + + onUseableChangedLocked(false, userId); } @GuardedBy("mLock") - public void onAllowedChangedLocked() { + public void onAllowedChangedLocked(int userId) { + if (!isCurrentProfileLocked(userId)) { + return; + } + if (mIsManagedBySettings) { boolean allowed = mSettingsStore.getLocationProvidersAllowed( mCurrentUserId).contains(mName); @@ -1040,37 +1036,36 @@ public class LocationManagerService extends ILocationManager.Stub { } mAllowed = allowed; - onUseableChangedLocked(true); + onUseableChangedLocked(true, userId); } } @GuardedBy("mLock") - public boolean isUseableLocked() { - return isUseableForUserLocked(mCurrentUserId); + public void onCurrentUserChangedLocked(int userId) { + onUseableChangedLocked(false, userId); } @GuardedBy("mLock") - public boolean isUseableForUserLocked(int userId) { - return isCurrentProfileLocked(userId) && mUseable; + public boolean isUseableLocked() { + return isUseableLocked(mCurrentUserId); } @GuardedBy("mLock") - private boolean isUseableIgnoringAllowedLocked() { - return mProvider != null && mProviders.contains(this) && isLocationEnabled() - && mEnabled; + public boolean isUseableLocked(int userId) { + return mUseable.get(userId, Boolean.FALSE); } @GuardedBy("mLock") - public void onUseableChangedLocked(boolean isAllowedChanged) { + public void onUseableChangedLocked(boolean isAllowedChanged, int userId) { // if any property that contributes to "useability" here changes state, it MUST result // in a direct or indrect call to onUseableChangedLocked. this allows the provider to // guarantee that it will always eventually reach the correct state. - boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked(); + boolean useableIgnoringAllowed = mProvider != null && mProviders.contains(this) + && isCurrentProfileLocked(userId) && isLocationEnabledForUser(userId) + && mEnabled; boolean useable = useableIgnoringAllowed && mAllowed; - // update deprecated provider allowed settings for backwards compatibility, and do this - // even if there is no change in overall useability state. this may result in trying to - // overwrite the same value, but Settings handles deduping this. + // update deprecated provider allowed settings for backwards compatibility if (mIsManagedBySettings) { // a "-" change derived from the allowed setting should not be overwritten, but a // "+" change should be corrected if necessary @@ -1079,33 +1074,31 @@ public class LocationManagerService extends ILocationManager.Stub { mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+" + mName, - mCurrentUserId); + userId); } else if (!useableIgnoringAllowed) { Settings.Secure.putStringForUser( mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-" + mName, - mCurrentUserId); + userId); } - // needs to be sent to all users because whether or not a provider is enabled for - // a given user is complicated... we broadcast to everyone and let them figure it - // out via isProviderEnabled() Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION); intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + intent.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable); + mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); } - if (useable == mUseable) { + if (useable == isUseableLocked(userId)) { return; } - mUseable = useable; + mUseable.put(userId, useable); if (D) { - Log.d(TAG, mName + " provider useable is now " + mUseable); + Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable); } - if (!mUseable) { + if (!useable) { // If any provider has been disabled, clear all last locations for all // providers. This is to be on the safe side in case a provider has location // derived from this disabled provider. @@ -1115,15 +1108,6 @@ public class LocationManagerService extends ILocationManager.Stub { updateProviderUseableLocked(this); } - - @GuardedBy("mLock") - public void onUserChangingLocked() { - // when the user is about to change, we set this provider to un-useable, and notify all - // of the current user clients. when the user is finished changing, useability will be - // updated back via onLocationModeChanged() and onAllowedChanged(). - mUseable = false; - updateProviderUseableLocked(this); - } } private class MockLocationProvider extends LocationProvider { @@ -1557,14 +1541,20 @@ public class LocationManagerService extends ILocationManager.Stub { mProviders.add(provider); - provider.onAllowedChangedLocked(); // allowed state may change while provider was inactive - provider.onUseableChangedLocked(false); + // allowed state may change while provider was inactive + provider.onAllowedChangedLocked(mCurrentUserId); + + // 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 + provider.onUseableChangedLocked(false, mCurrentUserId); } @GuardedBy("mLock") private void removeProviderLocked(LocationProvider provider) { if (mProviders.remove(provider)) { - provider.onUseableChangedLocked(false); + // 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 + provider.onUseableChangedLocked(false, mCurrentUserId); } } @@ -2851,7 +2841,7 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { LocationProvider provider = getLocationProviderLocked(providerName); - return provider != null && provider.isUseableForUserLocked(userId); + return provider != null && provider.isUseableLocked(userId); } } |