summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapi/system-current.txt3
-rw-r--r--api/test-current.txt2
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--location/java/android/location/ILocationManager.aidl2
-rw-r--r--location/java/android/location/LocationManager.java80
-rw-r--r--location/java/android/location/LocationManagerInternal.java13
-rw-r--r--location/java/android/location/util/identity/CallerIdentity.java (renamed from services/core/java/com/android/server/location/CallerIdentity.java)81
-rw-r--r--location/java/android/location/util/listeners/AbstractListenerManager.java31
-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.java61
-rw-r--r--packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java34
-rw-r--r--packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java3
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java88
-rw-r--r--services/core/java/com/android/server/LocationManagerServiceUtils.java3
-rw-r--r--services/core/java/com/android/server/location/AbstractLocationProvider.java68
-rw-r--r--services/core/java/com/android/server/location/AppOpsHelper.java3
-rw-r--r--services/core/java/com/android/server/location/GeofenceManager.java1
-rw-r--r--services/core/java/com/android/server/location/GeofenceState.java1
-rw-r--r--services/core/java/com/android/server/location/GnssAntennaInfoProvider.java3
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java3
-rw-r--r--services/core/java/com/android/server/location/GnssMeasurementsProvider.java3
-rw-r--r--services/core/java/com/android/server/location/GnssNavigationMessageProvider.java3
-rw-r--r--services/core/java/com/android/server/location/GnssStatusProvider.java3
-rw-r--r--services/core/java/com/android/server/location/LocationPermissionUtil.java62
-rw-r--r--services/core/java/com/android/server/location/LocationProviderProxy.java171
-rw-r--r--services/core/java/com/android/server/location/MockProvider.java3
-rw-r--r--services/core/java/com/android/server/location/MockableLocationProvider.java17
-rw-r--r--services/core/java/com/android/server/location/PassiveProvider.java3
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssListenerManager.java (renamed from services/core/java/com/android/server/location/util/listeners/GnssListenerManager.java)93
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssManagerService.java29
-rw-r--r--services/core/java/com/android/server/location/util/listeners/IdentifiedRegistration.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java24
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/MockableLocationProviderTest.java (renamed from services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java)46
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java16
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java (renamed from services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java)3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/test/ProviderListenerCapture.java61
38 files changed, 600 insertions, 435 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index a0144ad825f1..b5fb5387ec87 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4164,7 +4164,8 @@ package android.location {
method public boolean isExtraLocationControllerPackageEnabled();
method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.LOCATION_HARDWARE}) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
diff --git a/api/test-current.txt b/api/test-current.txt
index 352297c95d42..2da651ecf20c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1387,7 +1387,7 @@ package android.location {
method @NonNull public String[] getBackgroundThrottlingWhitelist();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @NonNull public String[] getIgnoreSettingsWhitelist();
- method @Nullable @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
+ method @Deprecated @Nullable @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
method @NonNull public java.util.List<android.location.LocationRequest> getTestProviderCurrentRequests(String);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 885117018c50..c2dbf4711ee0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4987,9 +4987,10 @@
<feature android:featureId="CountryDetector" android:label="@string/country_detector"/>
<!-- Feature Id for Location service. -->
<feature android:featureId="LocationService" android:label="@string/location_service"/>
+ <!-- Feature Id for Gnss service. -->
+ <feature android:featureId="GnssService" android:label="@string/gnss_service"/>
<!-- Feature Id for Sensor Notification service. -->
- <feature android:featureId="SensorNotificationService"
- android:label="@string/sensor_notification_service"/>
+ <feature android:featureId="SensorNotificationService" android:label="@string/sensor_notification_service"/>
<!-- Feature Id for Twilight service. -->
<feature android:featureId="TwilightService" android:label="@string/twilight_service"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9483bf209108..74b602de69d0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -425,6 +425,8 @@
<string name="country_detector">Country Detector</string>
<!-- Feature Id for Location service. [CHAR LIMIT=NONE]-->
<string name="location_service">Location Service</string>
+ <!-- Feature Id for Gnss service. [CHAR LIMIT=NONE]-->
+ <string name="gnss_service">GNSS Service</string>
<!-- Feature Id for Sensor Notification service. [CHAR LIMIT=NONE]-->
<string name="sensor_notification_service">Sensor Notification Service</string>
<!-- Feature Id for Twilight service. [CHAR LIMIT=NONE]-->
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index b7346308042f..6f543c31d9a3 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -96,7 +96,7 @@ interface ILocationManager
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
String getBestProvider(in Criteria criteria, boolean enabledOnly);
ProviderProperties getProviderProperties(String provider);
- boolean isProviderPackage(String packageName);
+ boolean isProviderPackage(String provider, String packageName);
List<String> getProviderPackages(String provider);
void setExtraLocationControllerPackage(String packageName);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 7523f07674ea..0bf7add422cf 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -64,7 +64,6 @@ import com.android.internal.location.ProviderProperties;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledRunnable;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
@@ -313,10 +312,9 @@ public class LocationManager {
private static final long GET_CURRENT_LOCATION_MAX_TIMEOUT_MS = 30 * 1000;
- private final Context mContext;
-
+ final Context mContext;
@UnsupportedAppUsage
- private final ILocationManager mService;
+ final ILocationManager mService;
@GuardedBy("mListeners")
private final ArrayMap<LocationListener, LocationListenerTransport> mListeners =
@@ -1403,15 +1401,36 @@ public class LocationManager {
* otherwise.
*
* @hide
+ * @deprecated Prefer {@link #isProviderPackage(String, String)} instead.
*/
+ @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
public boolean isProviderPackage(@NonNull String packageName) {
try {
- return mService.isProviderPackage(packageName);
+ return mService.isProviderPackage(null, packageName);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return false;
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns true if the given provider corresponds to the given package name. If the given
+ * provider is null, this will return true if any provider corresponds to the given package
+ * name.
+ *
+ * @param provider a provider listed by {@link #getAllProviders()} or null
+ * @param packageName the package name to test if it is a provider
+ * @return true if the given arguments correspond to a provider
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+ public boolean isProviderPackage(@Nullable String provider, @NonNull String packageName) {
+ try {
+ return mService.isProviderPackage(provider, packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1420,16 +1439,17 @@ public class LocationManager {
* and an empty list if no package is associated with the provider.
*
* @hide
+ * @deprecated Prefer {@link #isProviderPackage(String, String)} instead.
*/
@TestApi
+ @Deprecated
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
@Nullable
public List<String> getProviderPackages(@NonNull String provider) {
try {
return mService.getProviderPackages(provider);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return Collections.emptyList();
+ throw e.rethrowFromSystemServer();
}
}
@@ -2470,7 +2490,7 @@ public class LocationManager {
@Nullable
private ICancellationSignal mRemoteCancellationSignal;
- private GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer) {
+ GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer) {
Preconditions.checkArgument(executor != null, "illegal null executor");
Preconditions.checkArgument(consumer != null, "illegal null consumer");
mExecutor = executor;
@@ -2595,7 +2615,7 @@ public class LocationManager {
private final LocationListener mListener;
@Nullable private volatile Executor mExecutor = null;
- private LocationListenerTransport(@NonNull LocationListener listener) {
+ LocationListenerTransport(@NonNull LocationListener listener) {
Preconditions.checkArgument(listener != null, "invalid null listener");
mListener = listener;
}
@@ -2769,7 +2789,7 @@ public class LocationManager {
private final OnNmeaMessageListener mListener;
- private NmeaAdapter(OnNmeaMessageListener listener) {
+ NmeaAdapter(OnNmeaMessageListener listener) {
mListener = listener;
}
@@ -2783,7 +2803,7 @@ public class LocationManager {
private final GpsStatus.Listener mGpsListener;
- private GpsAdapter(GpsStatus.Listener gpsListener) {
+ GpsAdapter(GpsStatus.Listener gpsListener) {
mGpsListener = gpsListener;
}
@@ -2813,8 +2833,11 @@ public class LocationManager {
private @Nullable IGnssStatusListener mListenerTransport;
- private volatile @Nullable GnssStatus mGnssStatus;
- private volatile int mTtff;
+ volatile @Nullable GnssStatus mGnssStatus;
+ volatile int mTtff;
+
+ GnssStatusListenerManager() {
+ }
public GnssStatus getGnssStatus() {
return mGnssStatus;
@@ -2862,6 +2885,9 @@ public class LocationManager {
}
private class GnssStatusListener extends IGnssStatusListener.Stub {
+ GnssStatusListener() {
+ }
+
@Override
public void onGnssStarted() {
deliverToListeners(GnssStatus.Callback::onStarted);
@@ -2905,6 +2931,9 @@ public class LocationManager {
@Nullable
private IGnssMeasurementsListener mListenerTransport;
+ GnssMeasurementsListenerManager() {
+ }
+
@Override
protected boolean registerService(GnssRequest request) {
Preconditions.checkState(mListenerTransport == null);
@@ -2947,6 +2976,9 @@ public class LocationManager {
}
private class GnssMeasurementsListener extends IGnssMeasurementsListener.Stub {
+ GnssMeasurementsListener() {
+ }
+
@Override
public void onGnssMeasurementsReceived(final GnssMeasurementsEvent event) {
deliverToListeners((callback) -> callback.onGnssMeasurementsReceived(event));
@@ -2965,6 +2997,9 @@ public class LocationManager {
@Nullable
private IGnssNavigationMessageListener mListenerTransport;
+ GnssNavigationMessageListenerManager() {
+ }
+
@Override
protected boolean registerService(Void ignored) {
Preconditions.checkState(mListenerTransport == null);
@@ -2994,6 +3029,9 @@ public class LocationManager {
}
private class GnssNavigationMessageListener extends IGnssNavigationMessageListener.Stub {
+ GnssNavigationMessageListener() {
+ }
+
@Override
public void onGnssNavigationMessageReceived(GnssNavigationMessage event) {
deliverToListeners((listener) -> listener.onGnssNavigationMessageReceived(event));
@@ -3012,6 +3050,9 @@ public class LocationManager {
@Nullable
private IGnssAntennaInfoListener mListenerTransport;
+ GnssAntennaInfoListenerManager() {
+ }
+
@Override
protected boolean registerService(Void ignored) {
Preconditions.checkState(mListenerTransport == null);
@@ -3041,6 +3082,9 @@ public class LocationManager {
}
private class GnssAntennaInfoListener extends IGnssAntennaInfoListener.Stub {
+ GnssAntennaInfoListener() {
+ }
+
@Override
public void onGnssAntennaInfoReceived(List<GnssAntennaInfo> infos) {
deliverToListeners(callback -> callback.onGnssAntennaInfoReceived(infos));
@@ -3055,6 +3099,9 @@ public class LocationManager {
@Nullable
private IBatchedLocationCallback mListenerTransport;
+ BatchedLocationCallbackManager() {
+ }
+
@Override
protected boolean registerService(Void ignored) {
Preconditions.checkState(mListenerTransport == null);
@@ -3083,6 +3130,9 @@ public class LocationManager {
}
private class BatchedLocationCallback extends IBatchedLocationCallback.Stub {
+ BatchedLocationCallback() {
+ }
+
@Override
public void onLocationBatch(List<Location> locations) {
deliverToListeners((listener) -> listener.onLocationBatch(locations));
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index 6006d5079b07..542737b479e2 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -18,6 +18,8 @@ package android.location;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.location.util.identity.CallerIdentity;
/**
* Location manager local system service interface.
@@ -36,13 +38,14 @@ public abstract class LocationManagerInternal {
public abstract boolean isProviderEnabledForUser(@NonNull String provider, int userId);
/**
- * Returns true if the given package belongs to a location provider, and so should be afforded
- * some special privileges.
+ * Returns true if the given identity is a location provider.
*
- * @param packageName The package name to check
- * @return True is the given package belongs to a location provider, false otherwise
+ * @param provider The provider to check, or null to check every provider
+ * @param identity The identity to match
+ * @return True if the given identity matches either the given location provider or any
+ * provider, and false otherwise
*/
- public abstract boolean isProviderPackage(@NonNull String packageName);
+ public abstract boolean isProvider(@Nullable String provider, @NonNull CallerIdentity identity);
/**
* Should only be used by GNSS code.
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/location/java/android/location/util/identity/CallerIdentity.java
index b84fd13415fc..15641eb3bb6f 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/location/java/android/location/util/identity/CallerIdentity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.location;
+package android.location.util.identity;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Binder;
+import android.os.Process;
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,7 +37,9 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
- * Represents the calling process's uid, pid, and package name.
+ * Identifying information on a caller.
+ *
+ * @hide
*/
public final class CallerIdentity {
@@ -77,6 +80,26 @@ public final class CallerIdentity {
}
/**
+ * Construct a CallerIdentity for test purposes.
+ */
+ @VisibleForTesting
+ public static CallerIdentity forTest(int uid, int pid, String packageName,
+ @Nullable String featureId, @PermissionLevel int permissionLevel) {
+
+ return new CallerIdentity(uid, pid, packageName, featureId,
+ permissionLevel);
+ }
+
+ /**
+ * Creates a CallerIdentity for the current process and context.
+ */
+ public static CallerIdentity fromContext(Context context) {
+ return new CallerIdentity(Process.myUid(), Process.myPid(),
+ context.getPackageName(), context.getFeatureId(),
+ getPermissionLevel(context, Binder.getCallingPid(), Binder.getCallingUid()));
+ }
+
+ /**
* Creates a CallerIdentity from the current binder identity, using the given package and
* feature id. The package will be checked to enforce it belongs to the calling uid, and a
* security exception will be thrown if it is invalid.
@@ -100,42 +123,55 @@ public final class CallerIdentity {
public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
@Nullable String featureId) {
return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(),
- UserHandle.getCallingUserId(), packageName, featureId,
- getBinderPermissionLevel(context));
+ packageName, featureId,
+ getPermissionLevel(context, Binder.getCallingPid(), Binder.getCallingUid()));
}
/**
* Throws a security exception if the caller does not hold a location permission.
*/
- public static void enforceCallingOrSelfLocationPermission(Context context) {
- enforceLocationPermission(Binder.getCallingUid(), getBinderPermissionLevel(context));
+ public static void enforceCallingOrSelfLocationPermission(Context context,
+ @PermissionLevel int desiredPermissionLevel) {
+ enforceLocationPermission(Binder.getCallingUid(),
+ getPermissionLevel(context, Binder.getCallingPid(), Binder.getCallingUid()),
+ desiredPermissionLevel);
}
/**
* Returns false if the caller does not hold a location permission, true otherwise.
*/
- public static boolean checkCallingOrSelfLocationPermission(Context context) {
- return checkLocationPermission(getBinderPermissionLevel(context));
+ public static boolean checkCallingOrSelfLocationPermission(Context context,
+ @PermissionLevel int desiredPermissionLevel) {
+ return checkLocationPermission(
+ getPermissionLevel(context, Binder.getCallingPid(), Binder.getCallingUid()),
+ desiredPermissionLevel);
}
- private static void enforceLocationPermission(int uid, @PermissionLevel int permissionLevel) {
- if (checkLocationPermission(permissionLevel)) {
+ private static void enforceLocationPermission(int uid, @PermissionLevel int permissionLevel,
+ @PermissionLevel int desiredPermissionLevel) {
+ if (checkLocationPermission(permissionLevel, desiredPermissionLevel)) {
return;
}
- throw new SecurityException("uid " + uid + " does not have " + ACCESS_COARSE_LOCATION
- + " or " + ACCESS_FINE_LOCATION + ".");
+ if (desiredPermissionLevel == PERMISSION_COARSE) {
+ throw new SecurityException("uid " + uid + " does not have " + ACCESS_COARSE_LOCATION
+ + " or " + ACCESS_FINE_LOCATION + ".");
+ } else if (desiredPermissionLevel == PERMISSION_FINE) {
+ throw new SecurityException("uid " + uid + " does not have " + ACCESS_FINE_LOCATION
+ + ".");
+ }
}
- private static boolean checkLocationPermission(@PermissionLevel int permissionLevel) {
- return permissionLevel >= PERMISSION_COARSE;
+ private static boolean checkLocationPermission(@PermissionLevel int permissionLevel,
+ @PermissionLevel int desiredPermissionLevel) {
+ return permissionLevel >= desiredPermissionLevel;
}
- private static @PermissionLevel int getBinderPermissionLevel(Context context) {
- if (context.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) {
+ private static @PermissionLevel int getPermissionLevel(Context context, int pid, int uid) {
+ if (context.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
return PERMISSION_FINE;
}
- if (context.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) {
+ if (context.checkPermission(ACCESS_COARSE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
return PERMISSION_COARSE;
}
@@ -164,12 +200,11 @@ public final class CallerIdentity {
*/
public final @PermissionLevel int permissionLevel;
- @VisibleForTesting
- public CallerIdentity(int uid, int pid, int userId, String packageName,
+ private CallerIdentity(int uid, int pid, String packageName,
@Nullable String featureId, @PermissionLevel int permissionLevel) {
this.uid = uid;
this.pid = pid;
- this.userId = userId;
+ this.userId = UserHandle.getUserId(uid);
this.packageName = Objects.requireNonNull(packageName);
this.featureId = featureId;
this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE,
@@ -179,8 +214,8 @@ public final class CallerIdentity {
/**
* Throws a security exception if the CallerIdentity does not hold a location permission.
*/
- public void enforceLocationPermission() {
- enforceLocationPermission(uid, permissionLevel);
+ public void enforceLocationPermission(@PermissionLevel int desiredPermissionLevel) {
+ enforceLocationPermission(uid, permissionLevel, desiredPermissionLevel);
}
@Override
diff --git a/location/java/android/location/util/listeners/AbstractListenerManager.java b/location/java/android/location/util/listeners/AbstractListenerManager.java
index facb74766f2c..09c1eb2ae153 100644
--- a/location/java/android/location/util/listeners/AbstractListenerManager.java
+++ b/location/java/android/location/util/listeners/AbstractListenerManager.java
@@ -156,8 +156,15 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
// this class does not support adding listeners reentrantly
Preconditions.checkState(!mReentrancyGuard.isReentrant());
+ if (mRegistrations.isEmpty()) {
+ onRegister();
+ }
+
if (!registration.register()) {
registration.unregister();
+ if (mRegistrations.isEmpty()) {
+ onUnregister();
+ }
return;
}
@@ -210,6 +217,10 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
onRegistrationRemoved(key, registration);
registration.unregister();
updateService();
+
+ if (mRegistrations.isEmpty()) {
+ onUnregister();
+ }
}
/**
@@ -316,10 +327,26 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
protected abstract void unregisterService();
/**
+ * Invoked before the first registration occurs. This is a convenient entry point for
+ * registering listeners, etc, which only need to be present while there are any registrations.
+ * This method will always be invoked before a corresponding call to
+ * {@link Registration#onRegister()} and {@link #onActive()}.
+ */
+ protected void onRegister() {}
+
+ /**
+ * Invoked after the last unregistration occurs. This is a convenient entry point for
+ * unregistering listeners, etc, which only need to be present while there are any
+ * registrations. This method will always be after a corresponding call to
+ * {@link Registration#onUnregister()} and {@link #onInactive()}.
+ */
+ protected void onUnregister() {}
+
+ /**
* Invoked when the listener goes from having no active registrations to having some active
* registrations. This is a convenient entry point for registering listeners, etc, which only
* need to be present while there are active registrations. This method will always be invoked
- * before a corrosponding call to {@link #registerService(Object)}.
+ * before a corresponding call to {@link #registerService(Object)}.
*/
protected void onActive() {}
@@ -327,7 +354,7 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
* Invoked when the listener goes from having some active registrations to having no active
* registrations. This is a convenient entry point for unregistering listeners, etc, which only
* need to be present while there are active registrations. This method will always be invoked
- * after a corrosponding call to {@link #unregisterService()}.
+ * after a corresponding call to {@link #unregisterService()}.
*/
protected void onInactive() {}
diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl
index 439039148773..1bdedd57f321 100644
--- a/location/java/com/android/internal/location/ILocationProviderManager.aidl
+++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl
@@ -26,7 +26,7 @@ import com.android.internal.location.ProviderProperties;
*/
interface ILocationProviderManager {
- void onSetAdditionalProviderPackages(in List<String> packageNames);
+ void onSetFeatureId(String featureId);
@UnsupportedAppUsage
void onSetAllowed(boolean allowed);
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 9cc30d0d751e..4d0acea15263 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -7,7 +7,8 @@ package com.android.location.provider {
}
public abstract class LocationProviderBase {
- ctor public LocationProviderBase(String, com.android.location.provider.ProviderPropertiesUnbundled);
+ ctor @Deprecated public LocationProviderBase(String, com.android.location.provider.ProviderPropertiesUnbundled);
+ ctor @RequiresApi(android.os.Build.VERSION_CODES.R) public LocationProviderBase(android.content.Context, String, com.android.location.provider.ProviderPropertiesUnbundled);
method public android.os.IBinder getBinder();
method @RequiresApi(android.os.Build.VERSION_CODES.R) public boolean isAllowed();
method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
@@ -20,11 +21,11 @@ package com.android.location.provider {
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 @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setAdditionalProviderPackages(java.util.List<java.lang.String>);
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 @Deprecated 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 d3fb58fe257e..624e8d1b702b 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -39,7 +39,6 @@ import com.android.internal.location.ProviderRequest;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -65,7 +64,10 @@ public abstract class LocationProviderBase {
* Bundle key for a version of the location containing no GPS data.
* Allows location providers to flag locations as being safe to
* feed to LocationFudger.
+ *
+ * @deprecated Do not use from Android R onwards.
*/
+ @Deprecated
public static final String EXTRA_NO_GPS_LOCATION = Location.EXTRA_NO_GPS_LOCATION;
/**
@@ -76,8 +78,9 @@ public abstract class LocationProviderBase {
*/
public static final String FUSED_PROVIDER = LocationManager.FUSED_PROVIDER;
- private final String mTag;
- private final IBinder mBinder;
+ final String mTag;
+ final String mFeatureId;
+ final IBinder mBinder;
/**
* This field may be removed in the future, do not rely on it.
@@ -90,13 +93,30 @@ public abstract class LocationProviderBase {
protected final ILocationManager mLocationManager;
// write locked on mBinder, read lock is optional depending on atomicity requirements
- @Nullable private volatile ILocationProviderManager mManager;
- private volatile ProviderProperties mProperties;
- private volatile boolean mAllowed;
- private final ArrayList<String> mAdditionalProviderPackages;
+ @Nullable
+ volatile ILocationProviderManager mManager;
+ volatile ProviderProperties mProperties;
+ volatile boolean mAllowed;
+ /**
+ * @deprecated Prefer
+ * {@link #LocationProviderBase(Context, String, ProviderPropertiesUnbundled)}.
+ */
+ @Deprecated
public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
+ this(null, tag, properties);
+ }
+
+ /**
+ * This constructor associates the feature id of the given context with this location provider.
+ * The location service may afford special privileges to incoming calls identified as belonging
+ * to this location provider.
+ */
+ @RequiresApi(VERSION_CODES.R)
+ public LocationProviderBase(Context context, String tag,
+ ProviderPropertiesUnbundled properties) {
mTag = tag;
+ mFeatureId = context != null ? context.getFeatureId() : null;
mBinder = new Service();
mLocationManager = ILocationManager.Stub.asInterface(
@@ -105,7 +125,6 @@ public abstract class LocationProviderBase {
mManager = null;
mProperties = properties.getProviderProperties();
mAllowed = true;
- mAdditionalProviderPackages = new ArrayList<>(0);
}
public IBinder getBinder() {
@@ -183,23 +202,12 @@ public abstract class LocationProviderBase {
* another package may issue location requests on behalf of this package in the course of
* providing location. This will inform location services to treat the other packages as
* location providers as well.
+ *
+ * @deprecated On Android R and above this has no effect.
*/
+ @Deprecated
@RequiresApi(VERSION_CODES.Q)
- public void setAdditionalProviderPackages(List<String> packageNames) {
- synchronized (mBinder) {
- mAdditionalProviderPackages.clear();
- mAdditionalProviderPackages.addAll(packageNames);
- }
-
- ILocationProviderManager manager = mManager;
- if (manager != null) {
- try {
- manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages);
- } catch (RemoteException | RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
+ public void setAdditionalProviderPackages(List<String> packageNames) {}
/**
* @deprecated Use {@link #isAllowed()} instead.
@@ -317,12 +325,15 @@ public abstract class LocationProviderBase {
private final class Service extends ILocationProvider.Stub {
+ Service() {
+ }
+
@Override
public void setLocationProviderManager(ILocationProviderManager manager) {
synchronized (mBinder) {
try {
- if (!mAdditionalProviderPackages.isEmpty()) {
- manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages);
+ if (mFeatureId != null) {
+ manager.onSetFeatureId(mFeatureId);
}
manager.onSetProperties(mProperties);
manager.onSetAllowed(mAllowed);
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
index fb7dbc8aca5c..781efc118429 100644
--- a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
+++ b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
@@ -30,9 +30,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
-import android.os.Bundle;
import android.os.Looper;
-import android.os.Parcelable;
import android.os.WorkSource;
import com.android.internal.annotations.GuardedBy;
@@ -64,7 +62,7 @@ public class FusedLocationProvider extends LocationProviderBase {
private static final long MAX_LOCATION_COMPARISON_NS = 11 * 1000000000L; // 11 seconds
- private final Object mLock = new Object();
+ final Object mLock = new Object();
private final Context mContext;
private final LocationManager mLocationManager;
@@ -73,7 +71,7 @@ public class FusedLocationProvider extends LocationProviderBase {
private final BroadcastReceiver mUserChangeReceiver;
@GuardedBy("mLock")
- private ProviderRequestUnbundled mRequest;
+ ProviderRequestUnbundled mRequest;
@GuardedBy("mLock")
private WorkSource mWorkSource;
@GuardedBy("mLock")
@@ -84,12 +82,12 @@ public class FusedLocationProvider extends LocationProviderBase {
@GuardedBy("mLock")
@Nullable private Location mFusedLocation;
@GuardedBy("mLock")
- @Nullable private Location mGpsLocation;
+ @Nullable Location mGpsLocation;
@GuardedBy("mLock")
- @Nullable private Location mNetworkLocation;
+ @Nullable Location mNetworkLocation;
public FusedLocationProvider(Context context) {
- super(TAG, PROPERTIES);
+ super(context, TAG, PROPERTIES);
mContext = context;
mLocationManager = context.getSystemService(LocationManager.class);
@@ -232,7 +230,7 @@ public class FusedLocationProvider extends LocationProviderBase {
}
@GuardedBy("mLock")
- private void reportBestLocationLocked() {
+ void reportBestLocationLocked() {
Location bestLocation = chooseBestLocation(mGpsLocation, mNetworkLocation);
if (bestLocation == mFusedLocation) {
return;
@@ -243,28 +241,10 @@ public class FusedLocationProvider extends LocationProviderBase {
return;
}
- // copy NO_GPS_LOCATION extra from mNetworkLocation into mFusedLocation
- if (mNetworkLocation != null) {
- Bundle srcExtras = mNetworkLocation.getExtras();
- if (srcExtras != null) {
- Parcelable srcParcelable =
- srcExtras.getParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION);
- if (srcParcelable instanceof Location) {
- Bundle dstExtras = mFusedLocation.getExtras();
- if (dstExtras == null) {
- dstExtras = new Bundle();
- mFusedLocation.setExtras(dstExtras);
- }
- dstExtras.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION,
- srcParcelable);
- }
- }
- }
-
reportLocation(mFusedLocation);
}
- private void onUserChanged() {
+ void onUserChanged() {
// clear cached locations when the user changes to prevent leaking user information
synchronized (mLock) {
mFusedLocation = null;
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 d1a379afa25e..38f3bcdb62fe 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
@@ -52,7 +52,6 @@ import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
-import java.util.List;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -200,7 +199,7 @@ public class FusedLocationServiceTest {
}
@Override
- public void onSetAdditionalProviderPackages(List<String> packageNames) {
+ public void onSetFeatureId(String featureId) {
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 2c4309fb1610..cf0b3af07aee 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -24,11 +24,10 @@ import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
+import static android.location.util.identity.CallerIdentity.PERMISSION_COARSE;
+import static android.location.util.identity.CallerIdentity.PERMISSION_FINE;
import static android.os.PowerManager.locationPowerSaveModeToString;
-import static com.android.server.location.CallerIdentity.PERMISSION_COARSE;
-import static com.android.server.location.CallerIdentity.PERMISSION_FINE;
-
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import android.Manifest;
@@ -62,6 +61,8 @@ import android.location.LocationManagerInternal;
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.LocationTime;
+import android.location.util.identity.CallerIdentity;
+import android.location.util.identity.CallerIdentity.PermissionLevel;
import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -95,8 +96,6 @@ import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.AbstractLocationProvider.State;
import com.android.server.location.AppForegroundHelper;
import com.android.server.location.AppOpsHelper;
-import com.android.server.location.CallerIdentity;
-import com.android.server.location.CallerIdentity.PermissionLevel;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
@@ -128,7 +127,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
-import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -229,7 +227,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// @GuardedBy("mLock")
// hold lock for write or to prevent write, no lock for read
- private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
+ final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
new CopyOnWriteArrayList<>();
@GuardedBy("mLock")
@@ -243,7 +241,7 @@ public class LocationManagerService extends ILocationManager.Stub {
@PowerManager.LocationPowerSaveMode
private int mBatterySaverMode;
- private LocationManagerService(Context context) {
+ LocationManagerService(Context context) {
mContext = context.createFeatureContext(FEATURE_ID);
mHandler = FgThread.getHandler();
mLocalService = new LocalService();
@@ -278,7 +276,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// most startup is deferred until systemReady()
}
- private void onSystemReady() {
+ void onSystemReady() {
mAppOpsHelper.onSystemReady();
mUserInfoHelper.onSystemReady();
mSettingsHelper.onSystemReady();
@@ -358,7 +356,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- private void onSystemThirdPartyAppsCanStart() {
+ void onSystemThirdPartyAppsCanStart() {
synchronized (mLock) {
// prepare providers
initializeProvidersLocked();
@@ -666,7 +664,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
protected final MockableLocationProvider mProvider;
- private LocationProviderManager(String name) {
+ LocationProviderManager(String name) {
mName = name;
mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
mEnabled = new SparseArray<>(2);
@@ -716,8 +714,9 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- public Set<String> getPackages() {
- return mProvider.getState().providerPackageNames;
+ @Nullable
+ public CallerIdentity getProviderIdentity() {
+ return mProvider.getState().identity;
}
@Nullable
@@ -1395,7 +1394,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Nullable
- private LocationProviderManager getLocationProviderManager(String providerName) {
+ LocationProviderManager getLocationProviderManager(String providerName) {
for (LocationProviderManager manager : mProviderManagers) {
if (providerName.equals(manager.getName())) {
return manager;
@@ -1419,7 +1418,7 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
- if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext)) {
+ if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext, PERMISSION_COARSE)) {
return Collections.emptyList();
}
@@ -1653,7 +1652,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return true;
}
- return mLocalService.isProviderPackage(callerIdentity.packageName);
+ return mLocalService.isProvider(null, callerIdentity);
}
@@ -1667,8 +1666,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return true;
}
- return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.packageName);
-
+ return mLocalService.isProvider(null, record.mReceiver.mCallerIdentity);
}
private class UpdateRecord {
@@ -1850,7 +1848,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
- identity.enforceLocationPermission();
+ identity.enforceLocationPermission(PERMISSION_COARSE);
WorkSource workSource = request.getWorkSource();
if (workSource != null && !workSource.isEmpty()) {
@@ -2002,7 +2000,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// unsafe is ok because app ops will verify the package name
CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
- identity.enforceLocationPermission();
+ identity.enforceLocationPermission(PERMISSION_COARSE);
if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, identity.packageName)) {
return null;
@@ -2114,7 +2112,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
- identity.enforceLocationPermission();
+ identity.enforceLocationPermission(PERMISSION_COARSE);
Objects.requireNonNull(intent);
@@ -2254,7 +2252,7 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
- CallerIdentity.enforceCallingOrSelfLocationPermission(mContext);
+ CallerIdentity.enforceCallingOrSelfLocationPermission(mContext, PERMISSION_COARSE);
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
@@ -2288,16 +2286,40 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public boolean isProviderPackage(String packageName) {
+ public boolean isProviderPackage(String provider, String packageName) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
- return mLocalService.isProviderPackage(packageName);
+
+ for (LocationProviderManager manager : mProviderManagers) {
+ if (provider != null && !provider.equals(manager.getName())) {
+ continue;
+ }
+ CallerIdentity identity = manager.getProviderIdentity();
+ if (identity == null) {
+ continue;
+ }
+ if (identity.packageName.equals(packageName)) {
+ return true;
+ }
+ }
+
+ return false;
}
@Override
- public List<String> getProviderPackages(String providerName) {
+ public List<String> getProviderPackages(String provider) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
- LocationProviderManager manager = getLocationProviderManager(providerName);
- return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
+
+ LocationProviderManager manager = getLocationProviderManager(provider);
+ if (manager == null) {
+ return Collections.emptyList();
+ }
+
+ CallerIdentity identity = manager.getProviderIdentity();
+ if (identity == null) {
+ return Collections.emptyList();
+ }
+
+ return Collections.singletonList(identity.packageName);
}
@Override
@@ -2426,7 +2448,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
if (!mUserInfoHelper.isCurrentUserId(identity.userId)
- && !isProviderPackage(identity.packageName)) {
+ && !mLocalService.isProvider(null, identity)) {
continue;
}
@@ -2725,6 +2747,8 @@ public class LocationManagerService extends ILocationManager.Stub {
private class LocalService extends LocationManagerInternal {
+ LocalService() {}
+
@Override
public boolean isProviderEnabledForUser(@NonNull String provider, int userId) {
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -2739,12 +2763,16 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public boolean isProviderPackage(String packageName) {
+ public boolean isProvider(String provider, CallerIdentity identity) {
for (LocationProviderManager manager : mProviderManagers) {
- if (manager.getPackages().contains(packageName)) {
+ if (provider != null && !provider.equals(manager.getName())) {
+ continue;
+ }
+ if (identity.equals(manager.getProviderIdentity())) {
return true;
}
}
+
return false;
}
diff --git a/services/core/java/com/android/server/LocationManagerServiceUtils.java b/services/core/java/com/android/server/LocationManagerServiceUtils.java
index f50a885dd20c..7ffbc31bc949 100644
--- a/services/core/java/com/android/server/LocationManagerServiceUtils.java
+++ b/services/core/java/com/android/server/LocationManagerServiceUtils.java
@@ -17,11 +17,10 @@
package com.android.server;
import android.annotation.NonNull;
+import android.location.util.identity.CallerIdentity;
import android.os.IBinder;
import android.os.RemoteException;
-import com.android.server.location.CallerIdentity;
-
import java.util.NoSuchElementException;
/**
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index e9d94a5430fe..d45ab561f3c6 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -19,21 +19,18 @@ package com.android.server.location;
import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;
import android.annotation.Nullable;
-import android.content.Context;
import android.location.Location;
+import android.location.util.identity.CallerIdentity;
import android.os.Binder;
import android.os.Bundle;
-import android.util.ArraySet;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator;
@@ -78,8 +75,7 @@ public abstract class AbstractLocationProvider {
* Default state value for a location provider that is disabled with no properties and an
* empty provider package list.
*/
- public static final State EMPTY_STATE = new State(false, null,
- Collections.emptySet());
+ public static final State EMPTY_STATE = new State(false, null, null);
/**
* The provider's allowed state.
@@ -92,39 +88,37 @@ public abstract class AbstractLocationProvider {
@Nullable public final ProviderProperties properties;
/**
- * The provider's package name list - provider packages may be afforded special privileges.
+ * The provider's identity - providers may be afforded special privileges.
*/
- public final Set<String> providerPackageNames;
+ @Nullable public final CallerIdentity identity;
- private State(boolean allowed, ProviderProperties properties,
- Set<String> providerPackageNames) {
+ private State(boolean allowed, ProviderProperties properties, CallerIdentity identity) {
this.allowed = allowed;
this.properties = properties;
- this.providerPackageNames = Objects.requireNonNull(providerPackageNames);
+ this.identity = identity;
}
- private State withAllowed(boolean allowed) {
+ State withAllowed(boolean allowed) {
if (allowed == this.allowed) {
return this;
} else {
- return new State(allowed, properties, providerPackageNames);
+ return new State(allowed, properties, identity);
}
}
- private State withProperties(ProviderProperties properties) {
- if (properties.equals(this.properties)) {
+ State withProperties(@Nullable ProviderProperties properties) {
+ if (Objects.equals(properties, this.properties)) {
return this;
} else {
- return new State(allowed, properties, providerPackageNames);
+ return new State(allowed, properties, identity);
}
}
- private State withProviderPackageNames(Set<String> providerPackageNames) {
- if (providerPackageNames.equals(this.providerPackageNames)) {
+ State withIdentity(@Nullable CallerIdentity identity) {
+ if (Objects.equals(identity, this.identity)) {
return this;
} else {
- return new State(allowed, properties,
- Collections.unmodifiableSet(new ArraySet<>(providerPackageNames)));
+ return new State(allowed, properties, identity);
}
}
@@ -138,12 +132,12 @@ public abstract class AbstractLocationProvider {
}
State state = (State) o;
return allowed == state.allowed && properties == state.properties
- && providerPackageNames.equals(state.providerPackageNames);
+ && Objects.equals(identity, state.identity);
}
@Override
public int hashCode() {
- return Objects.hash(allowed, properties, providerPackageNames);
+ return Objects.hash(allowed, properties, identity);
}
}
@@ -153,12 +147,12 @@ public abstract class AbstractLocationProvider {
@Nullable public final Listener listener;
public final State state;
- private InternalState(@Nullable Listener listener, State state) {
+ InternalState(@Nullable Listener listener, State state) {
this.listener = listener;
this.state = state;
}
- private InternalState withListener(Listener listener) {
+ InternalState withListener(Listener listener) {
if (listener == this.listener) {
return this;
} else {
@@ -166,7 +160,7 @@ public abstract class AbstractLocationProvider {
}
}
- private InternalState withState(State state) {
+ InternalState withState(State state) {
if (state.equals(this.state)) {
return this;
} else {
@@ -174,7 +168,7 @@ public abstract class AbstractLocationProvider {
}
}
- private InternalState withState(UnaryOperator<State> operator) {
+ InternalState withState(UnaryOperator<State> operator) {
return withState(operator.apply(state));
}
}
@@ -187,14 +181,17 @@ public abstract class AbstractLocationProvider {
// before it was set, and should not miss any updates that occur after it was set).
private final AtomicReference<InternalState> mInternalState;
- protected AbstractLocationProvider(Executor executor, Context context) {
- this(executor, Collections.singleton(context.getPackageName()));
+
+ protected AbstractLocationProvider(Executor executor) {
+ mExecutor = executor;
+ mInternalState = new AtomicReference<>(
+ new InternalState(null, State.EMPTY_STATE));
}
- protected AbstractLocationProvider(Executor executor, Set<String> packageNames) {
+ protected AbstractLocationProvider(Executor executor, CallerIdentity identity) {
mExecutor = executor;
mInternalState = new AtomicReference<>(
- new InternalState(null, State.EMPTY_STATE.withProviderPackageNames(packageNames)));
+ new InternalState(null, State.EMPTY_STATE.withIdentity(identity)));
}
/**
@@ -275,10 +272,11 @@ public abstract class AbstractLocationProvider {
}
/**
- * The current package set of this provider.
+ * The current identity of this provider.
*/
- protected Set<String> getProviderPackages() {
- return mInternalState.get().state.providerPackageNames;
+ @Nullable
+ protected CallerIdentity getIdentity() {
+ return mInternalState.get().state.identity;
}
/**
@@ -298,8 +296,8 @@ public abstract class AbstractLocationProvider {
/**
* Call this method to report a change in provider packages.
*/
- protected void setPackageNames(Set<String> packageNames) {
- setState(state -> state.withProviderPackageNames(packageNames));
+ protected void setIdentity(CallerIdentity identity) {
+ setState(state -> state.withIdentity(identity));
}
/**
diff --git a/services/core/java/com/android/server/location/AppOpsHelper.java b/services/core/java/com/android/server/location/AppOpsHelper.java
index 9c279166ac8a..1df40f2e9ffc 100644
--- a/services/core/java/com/android/server/location/AppOpsHelper.java
+++ b/services/core/java/com/android/server/location/AppOpsHelper.java
@@ -25,6 +25,7 @@ import static com.android.server.LocationManagerService.TAG;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
+import android.location.util.identity.CallerIdentity;
import android.os.Binder;
import android.util.Log;
@@ -85,7 +86,7 @@ public class AppOpsHelper {
});
}
- private void onAppOpChanged(String packageName) {
+ void onAppOpChanged(String packageName) {
if (D) {
Log.v(TAG, "location appop changed for " + packageName);
}
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 195b059b7374..1607283de33b 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -25,6 +25,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
+import android.location.util.identity.CallerIdentity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
diff --git a/services/core/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
index 13318bfa6492..7d0a90b0f589 100644
--- a/services/core/java/com/android/server/location/GeofenceState.java
+++ b/services/core/java/com/android/server/location/GeofenceState.java
@@ -20,6 +20,7 @@ package com.android.server.location;
import android.app.PendingIntent;
import android.location.Geofence;
import android.location.Location;
+import android.location.util.identity.CallerIdentity;
/**
* Represents state associated with a geofence
diff --git a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
index 4926a1c7f6e0..1dc34556402a 100644
--- a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
@@ -18,12 +18,13 @@ package com.android.server.location;
import android.location.GnssAntennaInfo;
import android.location.IGnssAntennaInfoListener;
+import android.location.util.identity.CallerIdentity;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.gnss.GnssListenerManager;
import com.android.server.location.gnss.GnssManagerService;
-import com.android.server.location.util.listeners.GnssListenerManager;
import java.util.List;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8984ba8e034b..010e86960a14 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -39,6 +39,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
+import android.location.util.identity.CallerIdentity;
import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Binder;
@@ -620,7 +621,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
public GnssLocationProvider(Context context, UserInfoHelper userInfoHelper,
SettingsHelper settingsHelper, AppOpsHelper appOpsHelper,
AppForegroundHelper appForegroundHelper, LocationUsageLogger logger) {
- super(FgThread.getExecutor(), context);
+ super(FgThread.getExecutor(), CallerIdentity.fromContext(context));
ensureInitialized();
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index c3e055d2efb2..52391d3e55a8 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -19,14 +19,15 @@ package com.android.server.location;
import android.location.GnssMeasurementsEvent;
import android.location.GnssRequest;
import android.location.IGnssMeasurementsListener;
+import android.location.util.identity.CallerIdentity;
import android.os.IBinder;
import android.os.RemoteException;
import android.stats.location.LocationStatsEnums;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.gnss.GnssListenerManager;
import com.android.server.location.gnss.GnssManagerService;
-import com.android.server.location.util.listeners.GnssListenerManager;
import java.util.List;
import java.util.Objects;
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 10f7c4cb34eb..85d3b66d4213 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -18,12 +18,13 @@ package com.android.server.location;
import android.location.GnssNavigationMessage;
import android.location.IGnssNavigationMessageListener;
+import android.location.util.identity.CallerIdentity;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.gnss.GnssListenerManager;
import com.android.server.location.gnss.GnssManagerService;
-import com.android.server.location.util.listeners.GnssListenerManager;
/**
* An base implementation for GPS navigation messages provider.
diff --git a/services/core/java/com/android/server/location/GnssStatusProvider.java b/services/core/java/com/android/server/location/GnssStatusProvider.java
index 7d9ff2c55907..ab2c40e0478c 100644
--- a/services/core/java/com/android/server/location/GnssStatusProvider.java
+++ b/services/core/java/com/android/server/location/GnssStatusProvider.java
@@ -17,13 +17,14 @@
package com.android.server.location;
import android.location.IGnssStatusListener;
+import android.location.util.identity.CallerIdentity;
import android.os.IBinder;
import android.os.RemoteException;
import android.stats.location.LocationStatsEnums;
import android.util.Log;
+import com.android.server.location.gnss.GnssListenerManager;
import com.android.server.location.gnss.GnssManagerService;
-import com.android.server.location.util.listeners.GnssListenerManager;
/**
* Implementation of a handler for {@link IGnssStatusListener}.
diff --git a/services/core/java/com/android/server/location/LocationPermissionUtil.java b/services/core/java/com/android/server/location/LocationPermissionUtil.java
deleted file mode 100644
index 80b93b5e8ef6..000000000000
--- a/services/core/java/com/android/server/location/LocationPermissionUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.server.location;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/**
- * Encapsulates utility functions and classes related to location permission checking.
- */
-public final class LocationPermissionUtil {
- /**
- * Returns true if the calling process identified by {@code callerIdentity} is enabled to
- * report location to AppOps service before providing device location identifiable information
- * to its clients. Packages with these permissions must report any reporting of location
- * information to apps, via AppOps.
- *
- * <p>The calling package represented by {@code callerIdentity} is considered a part of the
- * extended Location Manager Service if it has all of the permissions below.
- * <ul>
- * <li>{@link android.Manifest.permission#LOCATION_HARDWARE}
- * <li>{@link android.Manifest.permission#UPDATE_APP_OPS_STATS}
- * </ul>
- *
- * <p>Any package with these permissions, that passes along location information from Android
- * framework to apps, must report to AppOps, similarly to Location Manager Service - i.e.
- * whenever it reports device location or location identifiable information such as
- * GNSS status, GNSS measurements, etc. to its clients.
- */
- public static boolean doesCallerReportToAppOps(Context context, CallerIdentity callerIdentity) {
- return hasPermissionLocationHardware(context, callerIdentity)
- && hasPermissionUpdateAppOpsStats(context, callerIdentity);
- }
-
- private static boolean hasPermissionLocationHardware(Context context,
- CallerIdentity callerIdentity) {
- return context.checkPermission(android.Manifest.permission.LOCATION_HARDWARE,
- callerIdentity.pid, callerIdentity.uid) == PackageManager.PERMISSION_GRANTED;
- }
-
- private static boolean hasPermissionUpdateAppOpsStats(Context context,
- CallerIdentity callerIdentity) {
- return context.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
- callerIdentity.pid, callerIdentity.uid) == PackageManager.PERMISSION_GRANTED;
- }
-
- private LocationPermissionUtil() {}
-}
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 87208a7f36f5..696b571f419a 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -16,20 +16,16 @@
package com.android.server.location;
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.location.Location;
+import android.location.util.identity.CallerIdentity;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.ArraySet;
-import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.location.ILocationProvider;
@@ -41,18 +37,12 @@ import com.android.server.ServiceWatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.List;
/**
* Proxy for ILocationProvider implementations.
*/
public class LocationProviderProxy extends AbstractLocationProvider {
- private static final String TAG = "LocationProviderProxy";
-
- private static final int MAX_ADDITIONAL_PACKAGES = 2;
-
/**
* Creates and registers this proxy. If no suitable service is available for the proxy, returns
* null.
@@ -69,76 +59,13 @@ public class LocationProviderProxy extends AbstractLocationProvider {
}
}
- private final ILocationProviderManager.Stub mManager = new ILocationProviderManager.Stub() {
- // executed on binder thread
- @Override
- public void onSetAdditionalProviderPackages(List<String> packageNames) {
- int maxCount = Math.min(MAX_ADDITIONAL_PACKAGES, packageNames.size());
- ArraySet<String> allPackages = new ArraySet<>(maxCount + 1);
- for (String packageName : packageNames) {
- if (packageNames.size() >= maxCount) {
- return;
- }
-
- try {
- mContext.getPackageManager().getPackageInfo(packageName, MATCH_SYSTEM_ONLY);
- allPackages.add(packageName);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, mServiceWatcher + " specified unknown additional provider package: "
- + packageName);
- }
- }
-
- synchronized (mLock) {
- if (!mBound) {
- return;
- }
-
- // add the binder package
- ComponentName service = mServiceWatcher.getBoundService().component;
- if (service != null) {
- allPackages.add(service.getPackageName());
- }
-
- setPackageNames(allPackages);
- }
- }
-
- // executed on binder thread
- @Override
- public void onSetAllowed(boolean allowed) {
- synchronized (mLock) {
- if (mBound) {
- setAllowed(allowed);
- }
- }
- }
-
- // executed on binder thread
- @Override
- public void onSetProperties(ProviderProperties properties) {
- synchronized (mLock) {
- if (mBound) {
- setProperties(properties);
- }
- }
- }
-
- // executed on binder thread
- @Override
- public void onReportLocation(Location location) {
- reportLocation(location);
- }
- };
+ final Object mLock = new Object();
- // also used to synchronized any state changes (setEnabled, setProperties, setState, etc)
- private final Object mLock = new Object();
-
- private final Context mContext;
- private final ServiceWatcher mServiceWatcher;
+ final Context mContext;
+ final ServiceWatcher mServiceWatcher;
@GuardedBy("mLock")
- private boolean mBound;
+ Proxy mProxy;
private volatile ProviderRequest mRequest;
@@ -146,13 +73,13 @@ public class LocationProviderProxy extends AbstractLocationProvider {
int nonOverlayPackageResId) {
// safe to use direct executor since our locks are not acquired in a code path invoked by
// our owning provider
- super(DIRECT_EXECUTOR, Collections.emptySet());
+ super(DIRECT_EXECUTOR);
mContext = context;
mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), action, this::onBind,
this::onUnbind, enableOverlayResId, nonOverlayPackageResId);
- mBound = false;
+ mProxy = null;
mRequest = ProviderRequest.EMPTY_REQUEST;
}
@@ -164,25 +91,19 @@ public class LocationProviderProxy extends AbstractLocationProvider {
ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
synchronized (mLock) {
- mBound = true;
-
- provider.setLocationProviderManager(mManager);
+ mProxy = new Proxy();
+ provider.setLocationProviderManager(mProxy);
ProviderRequest request = mRequest;
if (!request.equals(ProviderRequest.EMPTY_REQUEST)) {
provider.setRequest(request, request.workSource);
}
-
- ComponentName service = mServiceWatcher.getBoundService().component;
- if (service != null) {
- setPackageNames(Collections.singleton(service.getPackageName()));
- }
}
}
private void onUnbind() {
synchronized (mLock) {
- mBound = false;
+ mProxy = null;
setState(State.EMPTY_STATE);
}
}
@@ -208,4 +129,76 @@ public class LocationProviderProxy extends AbstractLocationProvider {
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mServiceWatcher.dump(fd, pw, args);
}
+
+ private class Proxy extends ILocationProviderManager.Stub {
+
+ Proxy() {}
+
+ // executed on binder thread
+ @Override
+ public void onSetFeatureId(String featureId) {
+ synchronized (mLock) {
+ if (mProxy != this) {
+ return;
+ }
+
+ ComponentName service = mServiceWatcher.getBoundService().component;
+ if (service == null) {
+ return;
+ }
+
+ // we don't need to verify the package name because we're getting it straight from
+ // the service watcher
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext,
+ service.getPackageName(), featureId);
+ setIdentity(identity);
+ }
+ }
+
+ // executed on binder thread
+ @Override
+ public void onSetProperties(ProviderProperties properties) {
+ synchronized (mLock) {
+ if (mProxy != this) {
+ return;
+ }
+
+ // if no identity is set yet, set it now
+ if (getIdentity() == null) {
+ ComponentName service = mServiceWatcher.getBoundService().component;
+ if (service != null) {
+ // we don't need to verify the package name because we're getting it
+ // straight from the service watcher
+ setIdentity(CallerIdentity.fromBinderUnsafe(mContext,
+ service.getPackageName(), null));
+ }
+ }
+
+ setProperties(properties);
+ }
+ }
+
+ // executed on binder thread
+ @Override
+ public void onSetAllowed(boolean allowed) {
+ synchronized (mLock) {
+ if (mProxy != this) {
+ return;
+ }
+
+ setAllowed(allowed);
+ }
+ }
+
+ // executed on binder thread
+ @Override
+ public void onReportLocation(Location location) {
+ synchronized (mLock) {
+ if (mProxy != this) {
+ return;
+ }
+ reportLocation(location);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 5ec06ca25581..160e641aee9e 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -27,7 +27,6 @@ import com.android.internal.location.ProviderRequest;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
/**
* A mock location provider used by LocationManagerService to implement test providers.
@@ -40,7 +39,7 @@ public class MockProvider extends AbstractLocationProvider {
public MockProvider(ProviderProperties properties) {
// using a direct executor is ok because this class has no locks that could deadlock
- super(DIRECT_EXECUTOR, Collections.emptySet());
+ super(DIRECT_EXECUTOR);
setProperties(properties);
}
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index 0f358e97bc98..54af1c84d36b 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -28,7 +28,6 @@ import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
import java.util.List;
/**
@@ -48,10 +47,10 @@ import java.util.List;
*/
public class MockableLocationProvider extends AbstractLocationProvider {
- private final Object mOwnerLock;
+ final Object mOwnerLock;
@GuardedBy("mOwnerLock")
- @Nullable private AbstractLocationProvider mProvider;
+ @Nullable AbstractLocationProvider mProvider;
@GuardedBy("mOwnerLock")
@Nullable private AbstractLocationProvider mRealProvider;
@GuardedBy("mOwnerLock")
@@ -72,7 +71,7 @@ public class MockableLocationProvider extends AbstractLocationProvider {
public MockableLocationProvider(Object ownerLock, Listener listener) {
// using a direct executor is acceptable because all inbound calls are delegated to the
// actual provider implementations which will use their own executors
- super(DIRECT_EXECUTOR, Collections.emptySet());
+ super(DIRECT_EXECUTOR);
mOwnerLock = ownerLock;
mRequest = ProviderRequest.EMPTY_REQUEST;
@@ -236,8 +235,12 @@ public class MockableLocationProvider extends AbstractLocationProvider {
synchronized (mOwnerLock) {
provider = mProvider;
pw.println("allowed=" + getState().allowed);
- pw.println("properties=" + getState().properties);
- pw.println("packages=" + getState().providerPackageNames);
+ if (getState().identity != null) {
+ pw.println("identity=" + getState().identity);
+ }
+ if (getState().properties != null) {
+ pw.println("properties=" + getState().properties);
+ }
pw.println("request=" + mRequest);
}
@@ -254,7 +257,7 @@ public class MockableLocationProvider extends AbstractLocationProvider {
private final AbstractLocationProvider mListenerProvider;
- private ListenerWrapper(AbstractLocationProvider listenerProvider) {
+ ListenerWrapper(AbstractLocationProvider listenerProvider) {
mListenerProvider = listenerProvider;
}
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index 1ba38cc4d999..f37992a456ac 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -21,6 +21,7 @@ import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
+import android.location.util.identity.CallerIdentity;
import android.os.Bundle;
import com.android.internal.location.ProviderProperties;
@@ -53,7 +54,7 @@ public class PassiveProvider extends AbstractLocationProvider {
public PassiveProvider(Context context) {
// using a direct executor is ok because this class has no locks that could deadlock
- super(DIRECT_EXECUTOR, context);
+ super(DIRECT_EXECUTOR, CallerIdentity.fromContext(context));
mReportLocation = false;
diff --git a/services/core/java/com/android/server/location/util/listeners/GnssListenerManager.java b/services/core/java/com/android/server/location/gnss/GnssListenerManager.java
index 5da3542fe651..e4c8315a3f5c 100644
--- a/services/core/java/com/android/server/location/util/listeners/GnssListenerManager.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerManager.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package com.android.server.location.util.listeners;
+package com.android.server.location.gnss;
import android.annotation.Nullable;
-import android.location.LocationManager;
import android.location.LocationManagerInternal;
+import android.location.util.identity.CallerIdentity;
import android.location.util.listeners.AbstractListenerManager;
import android.os.Binder;
import android.os.IBinder;
@@ -31,9 +31,9 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
import com.android.server.location.AppForegroundHelper;
import com.android.server.location.AppOpsHelper;
-import com.android.server.location.CallerIdentity;
import com.android.server.location.SettingsHelper;
import com.android.server.location.UserInfoHelper;
+import com.android.server.location.util.listeners.IdentifiedRegistration;
import java.util.Objects;
@@ -115,6 +115,18 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
return getIdentity().userId == userId;
}
+ boolean onLocationEnabledChanged(int userId) {
+ if (userId == getIdentity().userId) {
+ return onActiveChanged();
+ }
+
+ return false;
+ }
+
+ boolean onBackgroundThrottlePackageWhitelistChanged() {
+ return onActiveChanged();
+ }
+
boolean onAppOpsChanged(String packageName) {
if (getIdentity().packageName.equals(packageName)) {
boolean appOpsAllowed = mAppOpsHelper.checkLocationAccess(getIdentity());
@@ -144,9 +156,11 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
private boolean onActiveChanged() {
synchronized (this) {
+ // TODO: we should be checking if the gps provider is enabled, not location
boolean active = mAppOpsAllowed
&& (mForeground || isBackgroundRestrictionExempt(getIdentity()))
- && mUserInfoHelper.isCurrentUserId(getIdentity().userId);
+ && mUserInfoHelper.isCurrentUserId(getIdentity().userId)
+ && mSettingsHelper.isLocationEnabled(getIdentity().userId);
if (active != mActive) {
mActive = active;
return true;
@@ -156,6 +170,19 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
return false;
}
+ private boolean isBackgroundRestrictionExempt(CallerIdentity identity) {
+ if (identity.uid == Process.SYSTEM_UID) {
+ return true;
+ }
+
+ if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
+ identity.packageName)) {
+ return true;
+ }
+
+ return mLocationManagerInternal.isProvider(null, identity);
+ }
+
@Override
public void binderDied() {
IBinder key = mKey;
@@ -193,6 +220,16 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
protected final AppForegroundHelper mAppForegroundHelper;
protected final LocationManagerInternal mLocationManagerInternal;
+ private final UserInfoHelper.UserListener mUserChangedListener = this::onUserChanged;
+ private final SettingsHelper.UserSettingChangedListener mLocationEnabledChangedListener =
+ this::onLocationEnabledChanged;
+ private final SettingsHelper.GlobalSettingChangedListener
+ mBackgroundThrottlePackageWhitelistChangedListener =
+ this::onBackgroundThrottlePackageWhitelistChanged;
+ private final AppOpsHelper.LocationAppOpListener mAppOpsChangedListener = this::onAppOpsChanged;
+ private final AppForegroundHelper.AppForegroundListener mAppForegroundChangedListener =
+ this::onAppForegroundChanged;
+
protected GnssListenerManager(UserInfoHelper userInfoHelper, SettingsHelper settingsHelper,
AppOpsHelper appOpsHelper, AppForegroundHelper appForegroundHelper) {
mUserInfoHelper = userInfoHelper;
@@ -201,10 +238,6 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
mAppForegroundHelper = appForegroundHelper;
mLocationManagerInternal = Objects.requireNonNull(
LocalServices.getService(LocationManagerInternal.class));
-
- mUserInfoHelper.addListener(this::onUserChanged);
- mAppOpsHelper.addListener(this::onAppOpsChanged);
- mAppForegroundHelper.addListener(this::onAppForegroundChanged);
}
/**
@@ -236,8 +269,27 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
protected boolean isActive(GnssRegistration registration) {
// we don't have an easy listener for provider enabled status changes available, so we
// check it every time, which should be pretty cheap
- return registration.isActive() && mLocationManagerInternal.isProviderEnabledForUser(
- LocationManager.GPS_PROVIDER, registration.getIdentity().userId);
+ return registration.isActive();
+ }
+
+ @Override
+ protected void onRegister() {
+ mUserInfoHelper.addListener(mUserChangedListener);
+ mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
+ mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
+ mBackgroundThrottlePackageWhitelistChangedListener);
+ mAppOpsHelper.addListener(mAppOpsChangedListener);
+ mAppForegroundHelper.addListener(mAppForegroundChangedListener);
+ }
+
+ @Override
+ protected void onUnregister() {
+ mUserInfoHelper.removeListener(mUserChangedListener);
+ mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
+ mSettingsHelper.removeOnBackgroundThrottlePackageWhitelistChangedListener(
+ mBackgroundThrottlePackageWhitelistChangedListener);
+ mAppOpsHelper.removeListener(mAppOpsChangedListener);
+ mAppForegroundHelper.removeListener(mAppForegroundChangedListener);
}
private void onUserChanged(int userId, int change) {
@@ -246,6 +298,14 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
}
}
+ private void onLocationEnabledChanged(int userId) {
+ updateRegistrations(registration -> registration.onLocationEnabledChanged(userId));
+ }
+
+ private void onBackgroundThrottlePackageWhitelistChanged() {
+ updateRegistrations(GnssRegistration::onBackgroundThrottlePackageWhitelistChanged);
+ }
+
private void onAppOpsChanged(String packageName) {
updateRegistrations(registration -> registration.onAppOpsChanged(packageName));
}
@@ -254,19 +314,6 @@ public abstract class GnssListenerManager<TRequest, TListener extends IInterface
updateRegistrations(registration -> registration.onForegroundChanged(uid, foreground));
}
- boolean isBackgroundRestrictionExempt(CallerIdentity callerIdentity) {
- if (callerIdentity.uid == Process.SYSTEM_UID) {
- return true;
- }
-
- if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
- callerIdentity.packageName)) {
- return true;
- }
-
- return mLocationManagerInternal.isProviderPackage(callerIdentity.packageName);
- }
-
/**
* May be overridden by subclasses to provide extra debug information.
*/
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 0067b1a43659..e5cbb7e2893f 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.location.gnss;
import static android.location.LocationManager.GPS_PROVIDER;
+import static android.location.util.identity.CallerIdentity.PERMISSION_FINE;
import android.Manifest;
import android.annotation.Nullable;
@@ -32,6 +33,7 @@ import android.location.IGpsGeofenceHardware;
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManagerInternal;
+import android.location.util.identity.CallerIdentity;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -43,7 +45,6 @@ import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.location.AppForegroundHelper;
import com.android.server.location.AppOpsHelper;
-import com.android.server.location.CallerIdentity;
import com.android.server.location.GnssAntennaInfoProvider;
import com.android.server.location.GnssBatchingProvider;
import com.android.server.location.GnssCapabilitiesProvider;
@@ -66,6 +67,8 @@ public class GnssManagerService {
public static final String TAG = "GnssManager";
public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
+ private static final String FEATURE_ID = "GnssService";
+
public static boolean isGnssSupported() {
return GnssLocationProvider.isSupported();
}
@@ -114,7 +117,7 @@ public class GnssManagerService {
GnssLocationProvider gnssLocationProvider) {
Preconditions.checkState(isGnssSupported());
- mContext = context;
+ mContext = context.createFeatureContext(FEATURE_ID);
mSettingsHelper = settingsHelper;
mAppOpsHelper = appOpsHelper;
mAppForegroundHelper = appForegroundHelper;
@@ -185,7 +188,6 @@ public class GnssManagerService {
*/
public int getGnssBatchSize(String packageName) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
synchronized (mGnssBatchingLock) {
return mGnssBatchingProvider.getBatchSize();
@@ -199,7 +201,6 @@ public class GnssManagerService {
public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
String featureId) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
if (!mAppOpsHelper.checkLocationAccess(identity)) {
@@ -224,9 +225,9 @@ public class GnssManagerService {
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
@Nullable String featureId) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission(PERMISSION_FINE);
synchronized (mGnssBatchingLock) {
Binder.DeathRecipient deathRecipient = () -> {
@@ -255,7 +256,6 @@ public class GnssManagerService {
*/
public void flushGnssBatch(String packageName) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
synchronized (mGnssBatchingLock) {
mGnssBatchingProvider.flush();
@@ -297,9 +297,9 @@ public class GnssManagerService {
*/
public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
@Nullable String featureId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission(PERMISSION_FINE);
+
mGnssStatusProvider.addListener(identity, listener);
}
@@ -315,12 +315,13 @@ public class GnssManagerService {
*/
public void addGnssMeasurementsListener(GnssRequest request, IGnssMeasurementsListener listener,
String packageName, @Nullable String featureId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission(PERMISSION_FINE);
+
if (request.isFullTracking()) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
}
- CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
mGnssMeasurementsProvider.addListener(request, identity, listener);
}
@@ -351,9 +352,9 @@ public class GnssManagerService {
*/
public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName,
@Nullable String featureId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission(PERMISSION_FINE);
+
mGnssAntennaInfoProvider.addListener(identity, listener);
}
@@ -371,9 +372,9 @@ public class GnssManagerService {
*/
public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
String packageName, @Nullable String featureId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission(PERMISSION_FINE);
+
mGnssNavigationMessageProvider.addListener(identity, listener);
}
diff --git a/services/core/java/com/android/server/location/util/listeners/IdentifiedRegistration.java b/services/core/java/com/android/server/location/util/listeners/IdentifiedRegistration.java
index 79577c93595b..132be232470f 100644
--- a/services/core/java/com/android/server/location/util/listeners/IdentifiedRegistration.java
+++ b/services/core/java/com/android/server/location/util/listeners/IdentifiedRegistration.java
@@ -19,11 +19,11 @@ package com.android.server.location.util.listeners;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.annotation.Nullable;
+import android.location.util.identity.CallerIdentity;
import android.location.util.listeners.AbstractListenerManager;
import android.os.Process;
import com.android.server.FgThread;
-import com.android.server.location.CallerIdentity;
import java.util.Objects;
import java.util.concurrent.Executor;
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
index 7fc10b14209b..3bbcf2135a94 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
@@ -22,9 +22,8 @@ import static android.app.AppOpsManager.OP_FINE_LOCATION;
import static android.app.AppOpsManager.OP_MOCK_LOCATION;
import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
-
-import static com.android.server.location.CallerIdentity.PERMISSION_COARSE;
-import static com.android.server.location.CallerIdentity.PERMISSION_FINE;
+import static android.location.util.identity.CallerIdentity.PERMISSION_COARSE;
+import static android.location.util.identity.CallerIdentity.PERMISSION_FINE;
import static com.google.common.truth.Truth.assertThat;
@@ -41,6 +40,7 @@ import static org.mockito.MockitoAnnotations.initMocks;
import android.app.AppOpsManager;
import android.content.Context;
+import android.location.util.identity.CallerIdentity;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -105,7 +105,7 @@ public class AppOpsHelperTest {
@Test
public void testCheckLocationAccess() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
doReturn(MODE_ALLOWED).when(
@@ -116,7 +116,7 @@ public class AppOpsHelperTest {
mAppOps).checkOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"));
assertThat(mHelper.checkLocationAccess(identity)).isFalse();
- identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_COARSE);
doReturn(MODE_ALLOWED).when(
@@ -130,7 +130,7 @@ public class AppOpsHelperTest {
@Test
public void testNoteLocationAccess() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
doReturn(MODE_ALLOWED).when(
@@ -144,7 +144,7 @@ public class AppOpsHelperTest {
assertThat(mHelper.noteLocationAccess(identity)).isFalse();
- identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_COARSE);
doReturn(MODE_ALLOWED).when(
@@ -160,7 +160,7 @@ public class AppOpsHelperTest {
@Test
public void testStartLocationMonitoring() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
doReturn(MODE_ALLOWED).when(
@@ -176,7 +176,7 @@ public class AppOpsHelperTest {
@Test
public void testStartHighPowerLocationMonitoring() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
doReturn(MODE_ALLOWED).when(
@@ -194,7 +194,7 @@ public class AppOpsHelperTest {
@Test
public void testStopLocationMonitoring() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
mHelper.stopLocationMonitoring(identity);
@@ -203,7 +203,7 @@ public class AppOpsHelperTest {
@Test
public void testStopHighPowerLocationMonitoring() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
mHelper.stopHighPowerLocationMonitoring(identity);
@@ -212,7 +212,7 @@ public class AppOpsHelperTest {
@Test
public void testNoteMockLocationAccess() {
- CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ CallerIdentity identity = CallerIdentity.forTest(1000, 1000, "mypackage", "myfeature",
PERMISSION_FINE);
doReturn(MODE_ALLOWED).when(
diff --git a/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/MockableLocationProviderTest.java
index 9b076e8edb52..6bfe566197af 100644
--- a/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/MockableLocationProviderTest.java
@@ -35,21 +35,18 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.server.location.test.FakeProvider;
+import com.android.server.location.test.ProviderListenerCapture;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.LinkedList;
-import java.util.List;
-
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class MockableLocationProviderTest {
- private Object mLock;
- private ListenerCapture mListener;
+ private ProviderListenerCapture mListener;
private AbstractLocationProvider mRealProvider;
private MockProvider mMockProvider;
@@ -58,8 +55,8 @@ public class MockableLocationProviderTest {
@Before
public void setUp() {
- mLock = new Object();
- mListener = new ListenerCapture();
+ Object lock = new Object();
+ mListener = new ProviderListenerCapture(lock);
mRealProvider = spy(new FakeProvider());
mMockProvider = spy(new MockProvider(new ProviderProperties(
@@ -71,9 +68,10 @@ public class MockableLocationProviderTest {
true,
true,
Criteria.POWER_LOW,
- Criteria.ACCURACY_FINE)));
+ Criteria.ACCURACY_FINE)
+ ));
- mProvider = new MockableLocationProvider(mLock, mListener);
+ mProvider = new MockableLocationProvider(lock, mListener);
mProvider.setRealProvider(mRealProvider);
}
@@ -170,34 +168,4 @@ public class MockableLocationProviderTest {
mMockProvider.reportLocation(mockLocation);
assertThat(mListener.getNextLocation()).isEqualTo(mockLocation);
}
-
- private class ListenerCapture implements AbstractLocationProvider.Listener {
-
- private final LinkedList<AbstractLocationProvider.State> mNewStates = new LinkedList<>();
- private final LinkedList<Location> mLocations = new LinkedList<>();
-
- @Override
- public void onStateChanged(AbstractLocationProvider.State oldState,
- AbstractLocationProvider.State newState) {
- assertThat(Thread.holdsLock(mLock)).isTrue();
- mNewStates.add(newState);
- }
-
- private AbstractLocationProvider.State getNextNewState() {
- return mNewStates.poll();
- }
-
- @Override
- public void onReportLocation(Location location) {
- assertThat(Thread.holdsLock(mLock)).isTrue();
- mLocations.add(location);
- }
-
- private Location getNextLocation() {
- return mLocations.poll();
- }
-
- @Override
- public void onReportLocation(List<Location> locations) {}
- }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index dd196312f763..a8635d85f62c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -55,6 +55,7 @@ import android.location.IGnssStatusListener;
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManagerInternal;
+import android.location.util.identity.CallerIdentity;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
@@ -64,7 +65,6 @@ import android.os.RemoteException;
import com.android.server.LocalServices;
import com.android.server.location.AppForegroundHelper;
import com.android.server.location.AppOpsHelper;
-import com.android.server.location.CallerIdentity;
import com.android.server.location.GnssAntennaInfoProvider;
import com.android.server.location.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
import com.android.server.location.GnssBatchingProvider;
@@ -148,6 +148,7 @@ public class GnssManagerServiceTest {
MockitoAnnotations.initMocks(this);
GnssLocationProvider.setIsSupportedForTest(true);
+ when(mMockContext.createFeatureContext(anyString())).thenReturn(mMockContext);
when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn(
Context.APP_OPS_SERVICE);
when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(
@@ -158,6 +159,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
when(mUserInfoHelper.isCurrentUserId(anyInt())).thenReturn(true);
+ when(mSettingsHelper.isLocationEnabled(anyInt())).thenReturn(true);
when(mAppOpsHelper.checkLocationAccess(any(CallerIdentity.class))).thenReturn(true);
when(mAppOpsHelper.noteLocationAccess(any(CallerIdentity.class))).thenReturn(true);
when(mAppForegroundHelper.isAppForeground(anyInt())).thenReturn(true);
@@ -297,7 +299,7 @@ public class GnssManagerServiceTest {
private void enableLocationPermissions() {
Mockito.doThrow(new SecurityException()).when(
- mMockContext).enforceCallingPermission(
+ mMockContext).enforceCallingOrSelfPermission(
AdditionalMatchers.and(
AdditionalMatchers.not(eq(Manifest.permission.LOCATION_HARDWARE)),
AdditionalMatchers.not(eq(Manifest.permission.ACCESS_FINE_LOCATION))),
@@ -305,6 +307,12 @@ public class GnssManagerServiceTest {
when(mMockContext.checkPermission(
eq(android.Manifest.permission.LOCATION_HARDWARE), anyInt(), anyInt())).thenReturn(
PackageManager.PERMISSION_GRANTED);
+ when(mMockContext.checkPermission(
+ eq(Manifest.permission.ACCESS_FINE_LOCATION), anyInt(), anyInt())).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+ when(mMockContext.checkPermission(
+ eq(Manifest.permission.ACCESS_COARSE_LOCATION), anyInt(), anyInt())).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
// AppOpsManager will return true if OP_FINE_LOCATION is checked
when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString())).thenAnswer(
@@ -324,6 +332,10 @@ public class GnssManagerServiceTest {
Mockito.doThrow(new SecurityException()).when(
mMockContext).enforceCallingOrSelfPermission(anyString(), nullable(String.class));
+ when(mMockContext.checkPermission(
+ anyString(), anyInt(), anyInt())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(),
anyString())).thenReturn(AppOpsManager.MODE_ERRORED);
diff --git a/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
index 5943f67494f8..2f1a20b2cbb1 100644
--- a/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
@@ -23,12 +23,11 @@ import com.android.server.location.AbstractLocationProvider;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
public class FakeProvider extends AbstractLocationProvider {
public FakeProvider() {
- super(Runnable::run, Collections.emptySet());
+ super(Runnable::run);
}
@Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/test/ProviderListenerCapture.java b/services/tests/mockingservicestests/src/com/android/server/location/test/ProviderListenerCapture.java
new file mode 100644
index 000000000000..5e5ed11bd0e7
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/test/ProviderListenerCapture.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.android.server.location.test;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.location.Location;
+
+import com.android.server.location.AbstractLocationProvider;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class ProviderListenerCapture implements AbstractLocationProvider.Listener {
+
+ private final Object mLock;
+ private final LinkedList<AbstractLocationProvider.State> mNewStates = new LinkedList<>();
+ private final LinkedList<Location> mLocations = new LinkedList<>();
+
+ public ProviderListenerCapture(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onStateChanged(AbstractLocationProvider.State oldState,
+ AbstractLocationProvider.State newState) {
+ assertThat(Thread.holdsLock(mLock)).isTrue();
+ mNewStates.add(newState);
+ }
+
+ public AbstractLocationProvider.State getNextNewState() {
+ return mNewStates.poll();
+ }
+
+ @Override
+ public void onReportLocation(Location location) {
+ assertThat(Thread.holdsLock(mLock)).isTrue();
+ mLocations.add(location);
+ }
+
+ public Location getNextLocation() {
+ return mLocations.poll();
+ }
+
+ @Override
+ public void onReportLocation(List<Location> locations) {}
+}