summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java43
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--location/java/android/location/LocationManager.java2
-rw-r--r--location/java/android/location/LocationManagerInternal.java44
-rw-r--r--location/java/com/android/internal/location/ILocationProvider.aidl2
-rw-r--r--location/java/com/android/internal/location/ILocationProviderManager.aidl2
-rw-r--r--location/lib/api/current.txt7
-rw-r--r--location/lib/java/com/android/location/provider/LocationProviderBase.java75
-rw-r--r--packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java2
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java122
-rw-r--r--services/core/java/com/android/server/location/AbstractLocationProvider.java47
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/location/LocationProviderProxy.java12
-rw-r--r--services/core/java/com/android/server/location/MockProvider.java17
-rw-r--r--services/core/java/com/android/server/location/MockableLocationProvider.java6
-rw-r--r--services/core/java/com/android/server/location/PassiveProvider.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java17
18 files changed, 296 insertions, 108 deletions
diff --git a/api/current.txt b/api/current.txt
index c05034744ac8..92915a6351bd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6917,6 +6917,7 @@ package android.app.admin {
method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
method public boolean requestBugreport(@NonNull android.content.ComponentName);
+ method public void requestSetLocationProviderAllowed(@NonNull android.content.ComponentName, @NonNull String, boolean);
method @Deprecated public boolean resetPassword(String, int);
method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index fa9dd274488f..e33e01ef4f58 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8847,6 +8847,49 @@ public class DevicePolicyManager {
}
/**
+ * Called by device owners to request a location provider to change its allowed state. For a
+ * provider to be enabled requires both that the master location setting is enabled, and that
+ * the provider itself is allowed. Most location providers are always allowed. Some location
+ * providers may have user consents or terms and conditions that must be accepted, or some other
+ * type of blocker before they are allowed however. Every location provider is responsible for
+ * its own allowed state.
+ *
+ * <p>This method requests that a location provider change its allowed state. For providers that
+ * are always allowed and have no state to change, this will have no effect. If the provider
+ * does require some consent, terms and conditions, or other blocking state, using this API
+ * implies that the device owner is agreeing/disagreeing to any consents, terms and conditions,
+ * etc, and the provider should make a best effort to adjust it's allowed state accordingly.
+ *
+ * <p>Location providers are generally only responsible for the current user, and callers must
+ * assume that this method will only affect provider state for the current user. Callers are
+ * responsible for tracking current user changes and re-updating provider state as necessary.
+ *
+ * <p>While providers are expected to make a best effort to honor this request, it is not a
+ * given that all providers will support such a request. If a provider does change its state as
+ * a result of this request, that may happen asynchronously after some delay. Test location
+ * providers set through {@link android.location.LocationManager#addTestProvider} will respond
+ * to this request to aide in testing.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+ * @param provider A location provider as listed by
+ * {@link android.location.LocationManager#getAllProviders()}
+ * @param providerAllowed Whether the location provider is being requested to enable or disable
+ * itself
+ * @throws SecurityException if {@code admin} is not a device owner.
+ */
+ public void requestSetLocationProviderAllowed(@NonNull ComponentName admin,
+ @NonNull String provider, boolean providerAllowed) {
+ throwIfParentInstance("requestSetLocationProviderAllowed");
+ if (mService != null) {
+ try {
+ mService.requestSetLocationProviderAllowed(admin, provider, providerAllowed);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* Called by profile or device owners to update {@link android.provider.Settings.Secure}
* settings. Validation that the value of the setting is in the correct form for the setting
* type should be performed by the caller.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3d6bf9db5535..49f2e57396f2 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -270,6 +270,7 @@ interface IDevicePolicyManager {
boolean isLockdownAdminConfiguredNetworks(in ComponentName who);
void setLocationEnabled(in ComponentName who, boolean locationEnabled);
+ void requestSetLocationProviderAllowed(in ComponentName who, in String provider, boolean providerAllowed);
boolean setTime(in ComponentName who, long millis);
boolean setTimeZone(in ComponentName who, String timeZone);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 687535c3304b..0c5fe787bbbc 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -74,7 +74,7 @@ import java.util.function.Consumer;
* still return location results, but the exact location will be obfuscated to a coarse level of
* accuracy.
*/
-@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
+@SuppressWarnings({"deprecation"})
@SystemService(Context.LOCATION_SERVICE)
@RequiresFeature(PackageManager.FEATURE_LOCATION)
public class LocationManager {
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
new file mode 100644
index 000000000000..44d9d2372665
--- /dev/null
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+
+import android.annotation.NonNull;
+
+/**
+ * Location manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class LocationManagerInternal {
+
+ /**
+ * Requests that a provider change its allowed state. A provider may or may not honor this
+ * request, and if the provider does change its state as a result, that may happen
+ * asynchronously after some delay.
+ *
+ * <p>Setting a provider's state to allowed implies that any consents or terms and conditions
+ * that may be necessary to allow the provider are agreed to. Setting a providers state to
+ * disallowed implies that any consents or terms and conditions have their agreement revoked.
+ *
+ * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
+ * @param allowed Whether the location provider is being requested to allow or disallow
+ * itself
+ * @throws IllegalArgumentException if provider is null
+ */
+ public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed);
+}
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index 4246c6cd1004..b7817ff1e1fc 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -37,4 +37,6 @@ interface ILocationProvider {
@UnsupportedAppUsage
oneway void sendExtraCommand(String command, in Bundle extras);
+
+ oneway void requestSetAllowed(boolean allowed);
}
diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl
index 85e18ba5ec4b..439039148773 100644
--- a/location/java/com/android/internal/location/ILocationProviderManager.aidl
+++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl
@@ -29,7 +29,7 @@ interface ILocationProviderManager {
void onSetAdditionalProviderPackages(in List<String> packageNames);
@UnsupportedAppUsage
- void onSetEnabled(boolean enabled);
+ void onSetAllowed(boolean allowed);
@UnsupportedAppUsage
void onSetProperties(in ProviderProperties properties);
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 5471bea549f4..49fcaabe981a 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -9,18 +9,21 @@ package com.android.location.provider {
public abstract class LocationProviderBase {
ctor public LocationProviderBase(String, com.android.location.provider.ProviderPropertiesUnbundled);
method public android.os.IBinder getBinder();
- method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) public boolean isAllowed();
+ method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
method @Deprecated protected void onDisable();
method @Deprecated protected void onDump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method @Deprecated protected void onEnable();
method @Deprecated protected int onGetStatus(android.os.Bundle);
method @Deprecated protected long onGetStatusUpdateTime();
method protected void onInit();
+ method protected void onRequestSetAllowed(boolean);
method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle);
method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource);
method public void reportLocation(android.location.Location);
method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setAdditionalProviderPackages(java.util.List<java.lang.String>);
- method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) public void setAllowed(boolean);
+ method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setProperties(com.android.location.provider.ProviderPropertiesUnbundled);
field public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
field public static final String FUSED_PROVIDER = "fused";
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index fc7bff3c6dab..f67d08e045e2 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -92,7 +92,7 @@ public abstract class LocationProviderBase {
// write locked on mBinder, read lock is optional depending on atomicity requirements
@Nullable private volatile ILocationProviderManager mManager;
private volatile ProviderProperties mProperties;
- private volatile boolean mEnabled;
+ private volatile boolean mAllowed;
private final ArrayList<String> mAdditionalProviderPackages;
public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
@@ -104,7 +104,7 @@ public abstract class LocationProviderBase {
mManager = null;
mProperties = properties.getProviderProperties();
- mEnabled = true;
+ mAllowed = true;
mAdditionalProviderPackages = new ArrayList<>(0);
}
@@ -113,35 +113,44 @@ public abstract class LocationProviderBase {
}
/**
- * Sets whether this provider is currently enabled or not. Note that this is specific to the
+ * @deprecated Use {@link #setAllowed(boolean)} instead.
+ */
+ @Deprecated
+ @RequiresApi(VERSION_CODES.Q)
+ public void setEnabled(boolean enabled) {
+ setAllowed(enabled);
+ }
+
+ /**
+ * Sets whether this provider is currently allowed or not. Note that this is specific to the
* provider only, and is not related to global location settings. This is a hint to the Location
* Manager that this provider will generally be unable to fulfill incoming requests. This
- * provider may still receive callbacks to onSetRequest while not enabled, and must decide
+ * provider may still receive callbacks to onSetRequest while not allowed, and must decide
* whether to attempt to satisfy those requests or not.
*
- * Some guidelines: providers should set their own enabled/disabled status based only on state
- * "owned" by that provider. For instance, providers should not take into account the state of
- * the location master setting when setting themselves enabled or disabled, as this state is not
- * owned by a particular provider. If a provider requires some additional user consent that is
- * particular to the provider, this should be use to set the enabled/disabled state. If the
- * provider proxies to another provider, the child provider's enabled/disabled state should be
- * taken into account in the parent's enabled/disabled state. For most providers, it is expected
- * that they will be always enabled.
+ * <p>Some guidelines: providers should set their own allowed/disallowed status based only on
+ * state "owned" by that provider. For instance, providers should not take into account the
+ * state of the location master setting when setting themselves allowed or disallowed, as this
+ * state is not owned by a particular provider. If a provider requires some additional user
+ * consent that is particular to the provider, this should be use to set the allowed/disallowed
+ * state. If the provider proxies to another provider, the child provider's allowed/disallowed
+ * state should be taken into account in the parent's allowed state. For most providers, it is
+ * expected that they will be always allowed.
*/
- @RequiresApi(VERSION_CODES.Q)
- public void setEnabled(boolean enabled) {
+ @RequiresApi(VERSION_CODES.R)
+ public void setAllowed(boolean allowed) {
synchronized (mBinder) {
- if (mEnabled == enabled) {
+ if (mAllowed == allowed) {
return;
}
- mEnabled = enabled;
+ mAllowed = allowed;
}
ILocationProviderManager manager = mManager;
if (manager != null) {
try {
- manager.onSetEnabled(mEnabled);
+ manager.onSetAllowed(mAllowed);
} catch (RemoteException | RuntimeException e) {
Log.w(mTag, e);
}
@@ -193,12 +202,20 @@ public abstract class LocationProviderBase {
}
/**
- * Returns true if this provider has been set as enabled. This will be true unless explicitly
- * set otherwise.
+ * @deprecated Use {@link #isAllowed()} instead.
*/
+ @Deprecated
@RequiresApi(VERSION_CODES.Q)
public boolean isEnabled() {
- return mEnabled;
+ return isAllowed();
+ }
+
+ /**
+ * Returns true if this provider is allowed. Providers start as allowed on construction.
+ */
+ @RequiresApi(VERSION_CODES.R)
+ public boolean isAllowed() {
+ return mAllowed;
}
/**
@@ -285,6 +302,17 @@ public abstract class LocationProviderBase {
return false;
}
+ /**
+ * Invoked when the system wishes to request that the provider sets its allowed state as
+ * desired. This implies that the caller is providing/retracting consent for any terms and
+ * conditions or consents associated with the provider.
+ *
+ * <p>It is generally only necessary to override this function if the provider has some barriers
+ * or gates for enabling/disabling itself, in which case this function should handle those
+ * appropriately. A provider that is always allowed has no need to override this function.
+ */
+ protected void onRequestSetAllowed(boolean allowed) {}
+
private final class Service extends ILocationProvider.Stub {
@Override
@@ -295,7 +323,7 @@ public abstract class LocationProviderBase {
manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages);
}
manager.onSetProperties(mProperties);
- manager.onSetEnabled(mEnabled);
+ manager.onSetAllowed(mAllowed);
} catch (RemoteException e) {
Log.w(mTag, e);
}
@@ -315,5 +343,10 @@ public abstract class LocationProviderBase {
public void sendExtraCommand(String command, Bundle extras) {
onSendExtraCommand(command, extras);
}
+
+ @Override
+ public void requestSetAllowed(boolean allowed) {
+ onRequestSetAllowed(allowed);
+ }
}
}
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index 33126510bc53..d1a379afa25e 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -205,7 +205,7 @@ public class FusedLocationServiceTest {
}
@Override
- public void onSetEnabled(boolean enabled) {
+ public void onSetAllowed(boolean allowed) {
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index de0b6fcbd4ae..3b6ff26d5f03 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -52,6 +52,7 @@ import android.location.ILocationListener;
import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
+import android.location.LocationManagerInternal;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
@@ -133,11 +134,12 @@ public class LocationManagerService extends ILocationManager.Stub {
*/
public static class Lifecycle extends SystemService {
- private LocationManagerService mService;
+ private final LocationManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new LocationManagerService(context);
+ LocalServices.addService(LocationManagerInternal.class, mService.new LocalService());
}
@Override
@@ -465,7 +467,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
for (LocationProviderManager manager : mProviderManagers) {
- manager.onUseableChangedLocked(userId);
+ manager.onEnabledChangedLocked(userId);
}
}
@@ -633,10 +635,10 @@ public class LocationManagerService extends ILocationManager.Stub {
for (LocationProviderManager manager : mProviderManagers) {
// update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
mSettingsStore.setLocationProviderAllowed(manager.getName(),
- manager.isUseable(newUserId), newUserId);
+ manager.isEnabled(newUserId), newUserId);
- manager.onUseableChangedLocked(oldUserId);
- manager.onUseableChangedLocked(newUserId);
+ manager.onEnabledChangedLocked(oldUserId);
+ manager.onEnabledChangedLocked(newUserId);
}
}
@@ -650,22 +652,22 @@ public class LocationManagerService extends ILocationManager.Stub {
// acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
protected final MockableLocationProvider mProvider;
- // useable state for parent user ids, no entry implies false. location state is only kept
+ // enabled state for parent user ids, no entry implies false. location state is only kept
// for parent user ids, the location state for a profile user id is assumed to be the same
// as for the parent. if querying this structure, ensure that the user id being used is a
// parent id or the results may be incorrect.
@GuardedBy("mLock")
- private final SparseArray<Boolean> mUseable;
+ private final SparseArray<Boolean> mEnabled;
private LocationProviderManager(String name) {
mName = name;
- mUseable = new SparseArray<>(1);
+ mEnabled = new SparseArray<>(1);
// initialize last since this lets our reference escape
mProvider = new MockableLocationProvider(mContext, mLock, this);
- // we can assume all users start with unuseable location state since the initial state
- // of all providers is disabled. no need to initialize mUseable further.
+ // we can assume all users start with disabled location state since the initial state
+ // of all providers is disabled. no need to initialize mEnabled further.
}
public String getName() {
@@ -693,13 +695,13 @@ public class LocationManagerService extends ILocationManager.Stub {
return mProvider.getState().properties;
}
- public void setMockProviderEnabled(boolean enabled) {
+ public void setMockProviderAllowed(boolean enabled) {
synchronized (mLock) {
if (!mProvider.isMock()) {
throw new IllegalArgumentException(mName + " provider is not a test provider");
}
- mProvider.setMockProviderEnabled(enabled);
+ mProvider.setMockProviderAllowed(enabled);
}
}
@@ -760,7 +762,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return;
}
- if (!GPS_PROVIDER.equals(mName) || !isUseable()) {
+ if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
Slog.w(TAG, "reportLocationBatch() called without user permission");
return;
}
@@ -771,30 +773,33 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
@Override
public void onStateChanged(State oldState, State newState) {
- if (oldState.enabled != newState.enabled) {
+ if (oldState.allowed != newState.allowed) {
// 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(mUserInfoStore.getCurrentUserId());
+ onEnabledChangedLocked(mUserInfoStore.getCurrentUserId());
}
}
- public boolean isUseable() {
- return isUseable(mUserInfoStore.getCurrentUserId());
+ public void requestSetAllowed(boolean allowed) {
+ mProvider.requestSetAllowed(allowed);
}
- public boolean isUseable(int userId) {
+ public boolean isEnabled() {
+ return isEnabled(mUserInfoStore.getCurrentUserId());
+ }
+
+ public boolean isEnabled(int userId) {
synchronized (mLock) {
// normalize user id to always refer to parent since profile state is always the
// same as parent state
userId = mUserInfoStore.getParentUserId(userId);
-
- return mUseable.get(userId, Boolean.FALSE);
+ return mEnabled.get(userId, Boolean.FALSE);
}
}
@GuardedBy("mLock")
- public void onUseableChangedLocked(int userId) {
+ public void onEnabledChangedLocked(int userId) {
if (userId == UserHandle.USER_NULL) {
// only used during initialization - we don't care about the null user
return;
@@ -804,36 +809,36 @@ public class LocationManagerService extends ILocationManager.Stub {
// as parent state
userId = mUserInfoStore.getParentUserId(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
+ // if any property that contributes to "enabled" here changes state, it MUST result
+ // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
// guarantee that it will always eventually reach the correct state.
- boolean useable = (userId == mUserInfoStore.getCurrentUserId())
- && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().enabled;
+ boolean enabled = (userId == mUserInfoStore.getCurrentUserId())
+ && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed;
- if (useable == isUseable(userId)) {
+ if (enabled == isEnabled(userId)) {
return;
}
- mUseable.put(userId, useable);
+ mEnabled.put(userId, enabled);
if (D) {
- Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
+ Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
}
// fused and passive provider never get public updates for legacy reasons
if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
// update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
- mSettingsStore.setLocationProviderAllowed(mName, useable, userId);
+ mSettingsStore.setLocationProviderAllowed(mName, enabled, userId);
Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
- .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable)
+ .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
}
- if (!useable) {
+ if (!enabled) {
// 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.
@@ -841,7 +846,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mLastLocationCoarseInterval.clear();
}
- updateProviderUseableLocked(this);
+ updateProviderEnabledLocked(this);
}
public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
@@ -854,10 +859,10 @@ public class LocationManagerService extends ILocationManager.Stub {
pw.increaseIndent();
- boolean useable = isUseable();
- pw.println("useable=" + useable);
- if (!useable) {
- pw.println("enabled=" + mProvider.getState().enabled);
+ boolean enabled = isEnabled();
+ pw.println("enabled=" + enabled);
+ if (!enabled) {
+ pw.println("allowed=" + mProvider.getState().allowed);
}
pw.println("properties=" + mProvider.getState().properties);
@@ -1009,7 +1014,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (manager == null) {
continue;
}
- if (!manager.isUseable() && !isSettingsExemptLocked(updateRecord)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) {
continue;
}
@@ -1425,7 +1430,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (FUSED_PROVIDER.equals(name)) {
continue;
}
- if (enabledOnly && !manager.isUseable()) {
+ if (enabledOnly && !manager.isEnabled()) {
continue;
}
if (criteria != null
@@ -1467,8 +1472,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private void updateProviderUseableLocked(LocationProviderManager manager) {
- boolean useable = manager.isUseable();
+ private void updateProviderEnabledLocked(LocationProviderManager manager) {
+ boolean enabled = manager.isEnabled();
ArrayList<Receiver> deadReceivers = null;
@@ -1486,7 +1491,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// Sends a notification message to the receiver
- if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), useable)) {
+ if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<>();
}
@@ -1553,7 +1558,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
|| (isForegroundOnlyMode && !record.mIsForegroundUid);
- if (!manager.isUseable() || isBatterySaverDisablingLocation) {
+ if (!manager.isEnabled() || isBatterySaverDisablingLocation) {
if (isSettingsExemptLocked(record)) {
providerRequest.setLocationSettingsIgnored(true);
providerRequest.setLowPowerMode(false);
@@ -1970,7 +1975,7 @@ public class LocationManagerService extends ILocationManager.Stub {
oldRecord.disposeLocked(false);
}
- if (!manager.isUseable() && !isSettingsExemptLocked(record)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(record)) {
// Notify the listener that updates are currently disabled - but only if the request
// does not ignore location settings
receiver.callProviderEnabledLocked(name, false);
@@ -2082,7 +2087,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- if (!manager.isUseable()) {
+ if (!manager.isEnabled()) {
return null;
}
@@ -2204,7 +2209,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
LocationProviderManager manager = getLocationProviderManager(location.getProvider());
- if (manager == null || !manager.isUseable()) {
+ if (manager == null || !manager.isEnabled()) {
return false;
}
@@ -2491,7 +2496,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
LocationProviderManager manager = getLocationProviderManager(providerName);
- return manager != null && manager.isUseable(userId);
+ return manager != null && manager.isEnabled(userId);
}
}
@@ -2549,8 +2554,8 @@ public class LocationManagerService extends ILocationManager.Stub {
long now = SystemClock.elapsedRealtime();
- // only update last location for locations that come from useable providers
- if (manager.isUseable()) {
+ // only update last location for locations that come from enabled providers
+ if (manager.isEnabled()) {
updateLastLocationLocked(location, manager.getName());
}
@@ -2560,7 +2565,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (lastLocationCoarseInterval == null) {
lastLocationCoarseInterval = new Location(location);
- if (manager.isUseable()) {
+ if (manager.isEnabled()) {
mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
}
}
@@ -2593,7 +2598,7 @@ public class LocationManagerService extends ILocationManager.Stub {
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
- if (!manager.isUseable() && !isSettingsExemptLocked(r)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(r)) {
continue;
}
@@ -2812,7 +2817,7 @@ public class LocationManagerService extends ILocationManager.Stub {
throw new IllegalArgumentException("provider doesn't exist: " + provider);
}
- manager.setMockProviderEnabled(enabled);
+ manager.setMockProviderAllowed(enabled);
}
@Override
@@ -2946,4 +2951,19 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
}
+
+ private class LocalService extends LocationManagerInternal {
+
+ @Override
+ public void requestSetProviderAllowed(String provider, boolean allowed) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+
+ synchronized (mLock) {
+ LocationProviderManager manager = getLocationProviderManager(provider);
+ if (manager != null) {
+ manager.requestSetAllowed(allowed);
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index ed6a759409d4..5afa48a2b34d 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -79,9 +79,9 @@ public abstract class AbstractLocationProvider {
Collections.emptySet());
/**
- * The provider's enabled state.
+ * The provider's allowed state.
*/
- public final boolean enabled;
+ public final boolean allowed;
/**
* The provider's properties.
@@ -93,18 +93,18 @@ public abstract class AbstractLocationProvider {
*/
public final Set<String> providerPackageNames;
- private State(boolean enabled, ProviderProperties properties,
+ private State(boolean allowed, ProviderProperties properties,
Set<String> providerPackageNames) {
- this.enabled = enabled;
+ this.allowed = allowed;
this.properties = properties;
this.providerPackageNames = Objects.requireNonNull(providerPackageNames);
}
- private State withEnabled(boolean enabled) {
- if (enabled == this.enabled) {
+ private State withAllowed(boolean allowed) {
+ if (allowed == this.allowed) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -112,7 +112,7 @@ public abstract class AbstractLocationProvider {
if (properties.equals(this.properties)) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -120,7 +120,7 @@ public abstract class AbstractLocationProvider {
if (providerPackageNames.equals(this.providerPackageNames)) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -133,13 +133,13 @@ public abstract class AbstractLocationProvider {
return false;
}
State state = (State) o;
- return enabled == state.enabled && properties == state.properties
+ return allowed == state.allowed && properties == state.properties
&& providerPackageNames.equals(state.providerPackageNames);
}
@Override
public int hashCode() {
- return Objects.hash(enabled, properties, providerPackageNames);
+ return Objects.hash(allowed, properties, providerPackageNames);
}
}
@@ -259,10 +259,10 @@ public abstract class AbstractLocationProvider {
}
/**
- * The current enabled state of this provider.
+ * The current allowed state of this provider.
*/
- protected boolean isEnabled() {
- return mInternalState.get().state.enabled;
+ protected boolean isAllowed() {
+ return mInternalState.get().state.allowed;
}
/**
@@ -281,10 +281,10 @@ public abstract class AbstractLocationProvider {
}
/**
- * Call this method to report a change in provider enabled/disabled status.
+ * Call this method to report a change in provider allowed status.
*/
- protected void setEnabled(boolean enabled) {
- setState(state -> state.withEnabled(enabled));
+ protected void setAllowed(boolean allowed) {
+ setState(state -> state.withAllowed(allowed));
}
/**
@@ -358,6 +358,19 @@ public abstract class AbstractLocationProvider {
protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
/**
+ * Requests a provider to enable itself for the given user id.
+ */
+ public final void requestSetAllowed(boolean allowed) {
+ // all calls into the provider must be moved onto the provider thread to prevent deadlock
+ mExecutor.execute(() -> onRequestSetAllowed(allowed));
+ }
+
+ /**
+ * Always invoked on the provider executor.
+ */
+ protected void onRequestSetAllowed(boolean allowed) {}
+
+ /**
* Dumps debug or log information. May be invoked from any thread.
*/
public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 15cf190952d1..306e1e3afcd7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -729,7 +729,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}, UserHandle.USER_ALL);
setProperties(PROPERTIES);
- setEnabled(true);
+ setAllowed(true);
}
/**
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 805b018a8f45..cf299fe9bb2a 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -97,8 +97,8 @@ public class LocationProviderProxy extends AbstractLocationProvider {
// executed on binder thread
@Override
- public void onSetEnabled(boolean enabled) {
- setEnabled(enabled);
+ public void onSetAllowed(boolean allowed) {
+ setAllowed(allowed);
}
// executed on binder thread
@@ -169,6 +169,14 @@ public class LocationProviderProxy extends AbstractLocationProvider {
}
@Override
+ public void onRequestSetAllowed(boolean allowed) {
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ service.requestSetAllowed(allowed);
+ });
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("service=" + mServiceWatcher);
}
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 60c9fc12c201..bcec8b12b371 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -42,9 +42,9 @@ public class MockProvider extends AbstractLocationProvider {
setProperties(properties);
}
- /** Sets the enabled state of this mock provider. */
- public void setProviderEnabled(boolean enabled) {
- setEnabled(enabled);
+ /** Sets the allowed state of this mock provider. */
+ public void setProviderAllowed(boolean allowed) {
+ setAllowed(allowed);
}
/** Sets the location to report for this mock provider. */
@@ -56,10 +56,15 @@ public class MockProvider extends AbstractLocationProvider {
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("last mock location=" + mLocation);
+ public void onSetRequest(ProviderRequest request) {}
+
+ @Override
+ protected void onRequestSetAllowed(boolean allowed) {
+ setAllowed(allowed);
}
@Override
- public void onSetRequest(ProviderRequest request) {}
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("last mock location=" + mLocation);
+ }
}
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index f50dfe7edbb7..18615f87609f 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -170,13 +170,13 @@ public class MockableLocationProvider extends AbstractLocationProvider {
}
/**
- * Sets the mock provider implementation's enabled state. Will throw an exception if the mock
+ * Sets the mock provider implementation's allowed state. Will throw an exception if the mock
* provider is not currently the active implementation.
*/
- public void setMockProviderEnabled(boolean enabled) {
+ public void setMockProviderAllowed(boolean allowed) {
synchronized (mOwnerLock) {
Preconditions.checkState(isMock());
- mMockProvider.setProviderEnabled(enabled);
+ mMockProvider.setProviderAllowed(allowed);
}
}
/**
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index b33877069d70..ef157a39fa28 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -56,7 +56,7 @@ public class PassiveProvider extends AbstractLocationProvider {
mReportLocation = false;
setProperties(PROPERTIES);
- setEnabled(true);
+ setAllowed(true);
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b6953f6e3e36..5dc5d4e37662 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -177,6 +177,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.location.LocationManager;
+import android.location.LocationManagerInternal;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
@@ -315,7 +316,6 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
-import java.util.stream.Collectors;
/**
* Implementation of the device policy APIs.
@@ -2049,6 +2049,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return mContext.getSystemService(LocationManager.class);
}
+ LocationManagerInternal getLocationManagerInternal() {
+ return LocalServices.getService(LocationManagerInternal.class);
+ }
+
IWindowManager getIWindowManager() {
return IWindowManager.Stub
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -11534,6 +11538,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public void requestSetLocationProviderAllowed(ComponentName who, String provider,
+ boolean providerAllowed) {
+ Objects.requireNonNull(who, "ComponentName is null");
+ enforceDeviceOwner(who);
+
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getLocationManagerInternal().requestSetProviderAllowed(provider,
+ providerAllowed));
+ }
+
+ @Override
public boolean setTime(ComponentName who, long millis) {
Objects.requireNonNull(who, "ComponentName is null in setTime");
enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(who);