Merge "Add DPM API to request location provider enable"
This commit is contained in:
committed by
Android (Google) Code Review
commit
614210991b
@@ -6919,6 +6919,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);
|
||||
|
||||
@@ -8854,6 +8854,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
44
location/java/android/location/LocationManagerInternal.java
Normal file
44
location/java/android/location/LocationManagerInternal.java
Normal file
@@ -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);
|
||||
}
|
||||
@@ -37,4 +37,6 @@ interface ILocationProvider {
|
||||
|
||||
@UnsupportedAppUsage
|
||||
oneway void sendExtraCommand(String command, in Bundle extras);
|
||||
|
||||
oneway void requestSetAllowed(boolean allowed);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
* 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
|
||||
* 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.
|
||||
* @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 allowed, and must decide
|
||||
* whether to attempt to satisfy those requests or not.
|
||||
*
|
||||
* <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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ public class FusedLocationServiceTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetEnabled(boolean enabled) {
|
||||
public void onSetAllowed(boolean allowed) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,6 +357,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.
|
||||
*/
|
||||
|
||||
@@ -729,7 +729,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
}, UserHandle.USER_ALL);
|
||||
|
||||
setProperties(PROPERTIES);
|
||||
setEnabled(true);
|
||||
setAllowed(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -168,6 +168,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -56,7 +56,7 @@ public class PassiveProvider extends AbstractLocationProvider {
|
||||
mReportLocation = false;
|
||||
|
||||
setProperties(PROPERTIES);
|
||||
setEnabled(true);
|
||||
setAllowed(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -180,6 +180,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;
|
||||
@@ -2096,6 +2097,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));
|
||||
@@ -11552,6 +11557,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
.write();
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user