summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoonil Nagarkar <sooniln@google.com>2019-12-04 16:05:08 -0800
committerSoonil Nagarkar <sooniln@google.com>2019-12-05 12:22:57 -0800
commit06e37f67de54ea047039ef9a98eb37861ece89c7 (patch)
tree2db3714a89202e62b7104902a8d7b445353bffab
parent4d4e91db5e61aa5765b28a4afdaae7ee915cabc6 (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.txt2
-rw-r--r--location/java/android/location/LocationManager.java35
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java144
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);
}
}