summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--location/java/android/location/ILocationManager.aidl35
-rw-r--r--location/java/android/location/Location.java10
-rw-r--r--location/java/android/location/LocationManager.java57
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java873
-rw-r--r--services/core/java/com/android/server/LocationManagerServiceUtils.java25
-rw-r--r--services/core/java/com/android/server/location/AppOpsHelper.java253
-rw-r--r--services/core/java/com/android/server/location/CallerIdentity.java216
-rw-r--r--services/core/java/com/android/server/location/GeofenceManager.java51
-rw-r--r--services/core/java/com/android/server/location/GeofenceState.java17
-rw-r--r--services/core/java/com/android/server/location/LocationPermissionUtil.java4
-rw-r--r--services/core/java/com/android/server/location/RemoteListenerHelper.java9
-rw-r--r--services/core/java/com/android/server/location/SettingsHelper.java17
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssManagerService.java105
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java228
-rw-r--r--services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java84
20 files changed, 1153 insertions, 848 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index fbe381b2ec15..78bc079c692e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9649,14 +9649,6 @@ public final class Settings {
"location_ignore_settings_package_whitelist";
/**
- * Maximum staleness allowed for last location when returned to clients with only foreground
- * location permissions.
- * @hide
- */
- public static final String LOCATION_LAST_LOCATION_MAX_AGE_MILLIS =
- "location_last_location_max_age_millis";
-
- /**
* Whether TV will switch to MHL port when a mobile device is plugged in.
* (0 = false, 1 = true)
* @hide
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 8600dc48c6a4..415092623531 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -47,16 +47,14 @@ interface ILocationManager
Location getLastLocation(in LocationRequest request, String packageName, String featureId);
boolean getCurrentLocation(in LocationRequest request,
in ICancellationSignal cancellationSignal, in ILocationListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
- in PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier);
- void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName);
+ in PendingIntent intent, String packageName, String featureId);
+ void removeUpdates(in ILocationListener listener, in PendingIntent intent);
void requestGeofence(in LocationRequest request, in Geofence geofence,
- in PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier);
+ in PendingIntent intent, String packageName, String featureId);
void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName,
@@ -73,34 +71,31 @@ interface ILocationManager
boolean addGnssMeasurementsListener(in GnssRequest request,
in IGnssMeasurementsListener listener,
- String packageName, String featureId,
- String listenerIdentifier);
+ String packageName, String featureId);
void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
in String packageName);
- long getGnssCapabilities(in String packageName);
+ long getGnssCapabilities();
void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
boolean addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);
boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
int getGnssYearOfHardware();
String getGnssHardwareModelName();
int getGnssBatchSize(String packageName);
- boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName,
- String featureId, String listenerIdentifier);
+ boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName, String featureId);
void removeGnssBatchingCallback();
- boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
+ boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId);
void flushGnssBatch(String packageName);
boolean stopGnssBatch();
void injectLocation(in Location location);
- @UnsupportedAppUsage
List<String> getAllProviders();
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
String getBestProvider(in Criteria criteria, boolean enabledOnly);
@@ -116,11 +111,11 @@ interface ILocationManager
boolean isProviderEnabledForUser(String provider, int userId);
boolean isLocationEnabledForUser(int userId);
void setLocationEnabledForUser(boolean enabled, int userId);
- void addTestProvider(String name, in ProviderProperties properties, String opPackageName);
- void removeTestProvider(String provider, String opPackageName);
- void setTestProviderLocation(String provider, in Location loc, String opPackageName);
- void setTestProviderEnabled(String provider, boolean enabled, String opPackageName);
- List<LocationRequest> getTestProviderCurrentRequests(String provider, String opPackageName);
+ void addTestProvider(String name, in ProviderProperties properties, String packageName, String featureId);
+ void removeTestProvider(String provider, String packageName, String featureId);
+ void setTestProviderLocation(String provider, in Location location, String packageName, String featureId);
+ void setTestProviderEnabled(String provider, boolean enabled, String packageName, String featureId);
+ List<LocationRequest> getTestProviderCurrentRequests(String provider);
LocationTime getGnssTimeMillis();
boolean sendExtraCommand(String provider, String command, inout Bundle extras);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 6724324bfcb9..9aa0c870e512 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -585,6 +585,16 @@ public class Location implements Parcelable {
return mElapsedRealtimeNanos;
}
+ /** @hide */
+ public long getElapsedRealtimeAgeNanos(long referenceRealtimeNs) {
+ return referenceRealtimeNs - mElapsedRealtimeNanos;
+ }
+
+ /** @hide */
+ public long getElapsedRealtimeAgeNanos() {
+ return getElapsedRealtimeAgeNanos(SystemClock.elapsedRealtimeNanos());
+ }
+
/**
* Set the time of this fix, in elapsed real-time since system boot.
*
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index ff7049ee565b..fcbd3e540291 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -652,19 +652,6 @@ public class LocationManager {
}
/**
- * Create a string that allows an app to identify a listener
- *
- * @param listener The listener
- *
- * @return A identifying string
- */
- private static String getListenerIdentifier(@NonNull Object listener) {
- return listener.getClass().getName()
- + '@'
- + Integer.toHexString(System.identityHashCode(listener));
- }
-
- /**
* Asynchronously returns a single current location fix. This may activate sensors in order to
* compute a new location, unlike {@link #getLastKnownLocation(String)}, which will only return
* a cached fix if available. The given callback will be invoked once and only once, either with
@@ -742,8 +729,7 @@ public class LocationManager {
try {
if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
- listenerTransport, mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(consumer))) {
+ listenerTransport, mContext.getPackageName(), mContext.getAttributionTag())) {
listenerTransport.register(mContext.getSystemService(AlarmManager.class),
remoteCancellationSignal);
if (cancellationSignal != null) {
@@ -1189,8 +1175,7 @@ public class LocationManager {
boolean registered = false;
try {
mService.requestLocationUpdates(locationRequest, transport, null,
- mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(listener));
+ mContext.getPackageName(), mContext.getAttributionTag());
registered = true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1235,8 +1220,7 @@ public class LocationManager {
try {
mService.requestLocationUpdates(locationRequest, null, pendingIntent,
- mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(pendingIntent));
+ mContext.getPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1293,7 +1277,7 @@ public class LocationManager {
transport.unregister();
try {
- mService.removeUpdates(transport, null, mContext.getPackageName());
+ mService.removeUpdates(transport, null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1312,7 +1296,7 @@ public class LocationManager {
Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
try {
- mService.removeUpdates(null, pendingIntent, mContext.getPackageName());
+ mService.removeUpdates(null, pendingIntent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1515,7 +1499,8 @@ public class LocationManager {
requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
supportsBearing, powerRequirement, accuracy);
try {
- mService.addTestProvider(provider, properties, mContext.getOpPackageName());
+ mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1536,7 +1521,8 @@ public class LocationManager {
Preconditions.checkArgument(provider != null, "invalid null provider");
try {
- mService.removeTestProvider(provider, mContext.getOpPackageName());
+ mService.removeTestProvider(provider, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1570,7 +1556,8 @@ public class LocationManager {
}
try {
- mService.setTestProviderLocation(provider, location, mContext.getOpPackageName());
+ mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1599,7 +1586,8 @@ public class LocationManager {
Preconditions.checkArgument(provider != null, "invalid null provider");
try {
- mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
+ mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1643,8 +1631,7 @@ public class LocationManager {
public List<LocationRequest> getTestProviderCurrentRequests(String providerName) {
Preconditions.checkArgument(providerName != null, "invalid null provider");
try {
- return mService.getTestProviderCurrentRequests(providerName,
- mContext.getOpPackageName());
+ return mService.getTestProviderCurrentRequests(providerName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1711,7 +1698,7 @@ public class LocationManager {
LocationRequest request = new LocationRequest().setExpireIn(expiration);
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getAttributionTag(), getListenerIdentifier(intent));
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1798,7 +1785,7 @@ public class LocationManager {
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getAttributionTag(), getListenerIdentifier(intent));
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1867,7 +1854,7 @@ public class LocationManager {
*/
public @NonNull GnssCapabilities getGnssCapabilities() {
try {
- long gnssCapabilities = mService.getGnssCapabilities(mContext.getPackageName());
+ long gnssCapabilities = mService.getGnssCapabilities();
if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) {
gnssCapabilities = 0L;
}
@@ -2493,7 +2480,7 @@ public class LocationManager {
try {
if (mBatchedLocationCallbackManager.addListener(callback, handler)) {
return mService.startGnssBatch(periodNanos, wakeOnFifoFull,
- mContext.getPackageName());
+ mContext.getPackageName(), mContext.getAttributionTag());
}
return false;
} catch (RemoteException e) {
@@ -3012,7 +2999,7 @@ public class LocationManager {
GnssMeasurementsListener transport = new GnssMeasurementsListener();
if (mService.addGnssMeasurementsListener(request, transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss measurement callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3065,7 +3052,7 @@ public class LocationManager {
GnssNavigationMessageListener transport = new GnssNavigationMessageListener();
if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss navigation callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3106,7 +3093,7 @@ public class LocationManager {
GnssAntennaInfoListener transport = new GnssAntennaInfoListener();
if (mService.addGnssAntennaInfoListener(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss antenna info callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3143,7 +3130,7 @@ public class LocationManager {
BatchedLocationCallback transport = new BatchedLocationCallback();
if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "batched location callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index fe083812ffed..d5c04dc1f160 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -318,7 +318,6 @@ public class SettingsBackupTest {
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
Settings.Global.LOCK_SOUND,
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d814b9c9f1fa..8ccff7605811 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -16,7 +16,6 @@
package com.android.server;
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
@@ -27,6 +26,9 @@ import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
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;
@@ -34,17 +36,16 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
+import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
@@ -58,6 +59,7 @@ import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationManagerInternal;
+import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
@@ -86,14 +88,15 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
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;
@@ -176,10 +179,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private static final String WAKELOCK_KEY = "*location*";
- private static final int RESOLUTION_LEVEL_NONE = 0;
- private static final int RESOLUTION_LEVEL_COARSE = 1;
- private static final int RESOLUTION_LEVEL_FINE = 2;
-
private static final String NETWORK_LOCATION_SERVICE_ACTION =
"com.android.location.service.v3.NetworkLocationProvider";
private static final String FUSED_LOCATION_SERVICE_ACTION =
@@ -208,6 +207,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private final Context mContext;
private final Handler mHandler;
private final LocalService mLocalService;
+ private final AppOpsHelper mAppOpsHelper;
private final UserInfoHelper mUserInfoHelper;
private final SettingsHelper mSettingsHelper;
private final AppForegroundHelper mAppForegroundHelper;
@@ -217,8 +217,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private final PassiveLocationProviderManager mPassiveManager;
- private AppOpsManager mAppOps;
- private PackageManager mPackageManager;
private PowerManager mPowerManager;
private GeofenceManager mGeofenceManager;
@@ -252,6 +250,7 @@ public class LocationManagerService extends ILocationManager.Stub {
LocalServices.addService(LocationManagerInternal.class, mLocalService);
+ mAppOpsHelper = new AppOpsHelper(mContext);
mUserInfoHelper = new UserInfoHelper(mContext);
mSettingsHelper = new SettingsHelper(mContext, mHandler);
mAppForegroundHelper = new AppForegroundHelper(mContext);
@@ -280,32 +279,17 @@ public class LocationManagerService extends ILocationManager.Stub {
}
private void onSystemReady() {
+ mAppOpsHelper.onSystemReady();
mUserInfoHelper.onSystemReady();
mSettingsHelper.onSystemReady();
mAppForegroundHelper.onSystemReady();
synchronized (mLock) {
- mPackageManager = mContext.getPackageManager();
- mAppOps = mContext.getSystemService(AppOpsManager.class);
mPowerManager = mContext.getSystemService(PowerManager.class);
mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
-
// add listeners
- mAppOps.startWatchingMode(
- AppOpsManager.OP_COARSE_LOCATION,
- null,
- AppOpsManager.WATCH_FOREGROUND_CHANGES,
- new AppOpsManager.OnOpChangedInternalListener() {
- public void onOpChanged(int op, String packageName) {
- // onOpChanged invoked on ui thread, move to our thread to reduce risk
- // of blocking ui thread
- mHandler.post(() -> onAppOpChanged(packageName));
- }
- });
- mPackageManager.addOnPermissionsChangeListener(
+ mContext.getPackageManager().addOnPermissionsChangeListener(
uid -> {
// listener invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
@@ -316,7 +300,8 @@ public class LocationManagerService extends ILocationManager.Stub {
});
});
- localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
+ LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver(
+ ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
@@ -328,6 +313,8 @@ public class LocationManagerService extends ILocationManager.Stub {
});
mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+ mAppOpsHelper.addListener(this::onAppOpChanged);
+
mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged);
mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
this::onBackgroundThrottleIntervalChanged);
@@ -336,40 +323,32 @@ public class LocationManagerService extends ILocationManager.Stub {
mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
this::onIgnoreSettingsWhitelistChanged);
- new PackageMonitor() {
+ PackageMonitor packageMonitor = new PackageMonitor() {
@Override
public void onPackageDisappeared(String packageName, int reason) {
synchronized (mLock) {
- LocationManagerService.this.onPackageDisappearedLocked(packageName);
+ LocationManagerService.this.onPackageDisappeared(packageName);
}
}
- }.register(mContext, mHandler.getLooper(), true);
+ };
+ packageMonitor.register(mContext, null, true, mHandler);
mUserInfoHelper.addListener(this::onUserChanged);
mAppForegroundHelper.addListener(this::onAppForegroundChanged);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
-
+ IntentFilter screenIntentFilter = new IntentFilter();
+ screenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ screenIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action == null) {
- return;
- }
- synchronized (mLock) {
- switch (action) {
- case Intent.ACTION_SCREEN_ON:
- case Intent.ACTION_SCREEN_OFF:
- onScreenStateChangedLocked();
- break;
- }
+ if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())
+ || Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ onScreenStateChanged();
}
}
- }, UserHandle.ALL, intentFilter, null, mHandler);
+ }, UserHandle.ALL, screenIntentFilter, null, mHandler);
// initialize the current users. we would get the user started notifications for these
// users eventually anyways, but this takes care of it as early as possible.
@@ -389,7 +368,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private void onAppOpChanged(String packageName) {
synchronized (mLock) {
for (Receiver receiver : mReceivers.values()) {
- if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
+ if (receiver.mCallerIdentity.packageName.equals(packageName)) {
receiver.updateMonitoring(true);
}
}
@@ -398,7 +377,7 @@ public class LocationManagerService extends ILocationManager.Stub {
for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mCallerIdentity.mPackageName.equals(packageName)) {
+ if (record.mReceiver.mCallerIdentity.packageName.equals(packageName)) {
affectedProviders.add(provider);
}
}
@@ -436,11 +415,12 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- @GuardedBy("mLock")
- private void onScreenStateChangedLocked() {
- if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
- for (LocationProviderManager manager : mProviderManagers) {
- applyRequirementsLocked(manager);
+ private void onScreenStateChanged() {
+ synchronized (mLock) {
+ if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
+ for (LocationProviderManager manager : mProviderManagers) {
+ applyRequirementsLocked(manager);
+ }
}
}
}
@@ -466,23 +446,24 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- @GuardedBy("mLock")
- private void onPackageDisappearedLocked(String packageName) {
- ArrayList<Receiver> deadReceivers = null;
+ private void onPackageDisappeared(String packageName) {
+ synchronized (mLock) {
+ ArrayList<Receiver> deadReceivers = null;
- for (Receiver receiver : mReceivers.values()) {
- if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
- if (deadReceivers == null) {
- deadReceivers = new ArrayList<>();
+ for (Receiver receiver : mReceivers.values()) {
+ if (receiver.mCallerIdentity.packageName.equals(packageName)) {
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList<>();
+ }
+ deadReceivers.add(receiver);
}
- deadReceivers.add(receiver);
}
- }
- // perform removal outside of mReceivers loop
- if (deadReceivers != null) {
- for (Receiver receiver : deadReceivers) {
- removeUpdatesLocked(receiver);
+ // perform removal outside of mReceivers loop
+ if (deadReceivers != null) {
+ for (Receiver receiver : deadReceivers) {
+ removeUpdatesLocked(receiver);
+ }
}
}
}
@@ -493,7 +474,7 @@ public class LocationManagerService extends ILocationManager.Stub {
for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mCallerIdentity.mUid == uid
+ if (record.mReceiver.mCallerIdentity.uid == uid
&& record.mIsForegroundUid != foreground) {
record.updateForeground(foreground);
@@ -574,17 +555,6 @@ public class LocationManagerService extends ILocationManager.Stub {
Log.e(TAG, "no geocoder provider found");
}
- // bind to geofence proxy
- if (mGnssManagerService != null) {
- IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
- if (gpsGeofenceHardware != null) {
- GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
- if (provider == null) {
- Log.e(TAG, "unable to bind to GeofenceProxy");
- }
- }
- }
-
// bind to hardware activity recognition
HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
HardwareActivityRecognitionProxy.createAndRegister(mContext);
@@ -607,19 +577,33 @@ public class LocationManagerService extends ILocationManager.Stub {
Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
Integer.parseInt(fragments[8]) /* powerRequirement */,
Integer.parseInt(fragments[9]) /* accuracy */);
- addTestProvider(name, properties, mContext.getOpPackageName());
+ LocationProviderManager manager = getLocationProviderManager(name);
+ if (manager == null) {
+ manager = new LocationProviderManager(name);
+ mProviderManagers.add(manager);
+ }
+ manager.setMockProvider(new MockProvider(properties));
}
// initialize gnss last because it has no awareness of boot phases and blindly assumes that
// all other location providers are loaded at initialization
if (GnssManagerService.isGnssSupported()) {
- mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper,
+ mGnssManagerService = new GnssManagerService(mContext, mAppOpsHelper, mSettingsHelper,
mAppForegroundHelper, mLocationUsageLogger);
mGnssManagerService.onSystemReady();
LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
mProviderManagers.add(gnssManager);
gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
+
+ // bind to geofence proxy
+ IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
+ if (gpsGeofenceHardware != null) {
+ GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
+ if (provider == null) {
+ Log.e(TAG, "unable to bind to GeofenceProxy");
+ }
+ }
}
}
@@ -742,16 +726,16 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Nullable
- public Location getLastFineLocation(int userId) {
+ public Location getLastLocation(int userId, @PermissionLevel int permissionlevel) {
synchronized (mLock) {
- return mLastLocation.get(userId);
- }
- }
-
- @Nullable
- public Location getLastCoarseLocation(int userId) {
- synchronized (mLock) {
- return mLastCoarseLocation.get(userId);
+ switch (permissionlevel) {
+ case PERMISSION_COARSE:
+ return mLastCoarseLocation.get(userId);
+ case PERMISSION_FINE:
+ return mLastLocation.get(userId);
+ default:
+ throw new AssertionError();
+ }
}
}
@@ -1037,7 +1021,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
PendingIntent.OnFinished {
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
- private final int mAllowedResolutionLevel; // resolution level allowed to receiver
private final ILocationListener mListener;
final PendingIntent mPendingIntent;
@@ -1054,11 +1037,9 @@ public class LocationManagerService extends ILocationManager.Stub {
private int mPendingBroadcasts;
PowerManager.WakeLock mWakeLock;
- private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
- String packageName, @Nullable String featureId, WorkSource workSource,
- boolean hideFromAppOps, @NonNull String listenerIdentifier) {
- super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
- "LocationListener");
+ private Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
+ super(identity);
mListener = listener;
mPendingIntent = intent;
if (listener != null) {
@@ -1066,7 +1047,6 @@ public class LocationManagerService extends ILocationManager.Stub {
} else {
mKey = intent;
}
- mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
if (workSource != null && workSource.isEmpty()) {
workSource = null;
}
@@ -1078,7 +1058,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// construct/configure wakelock
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
if (workSource == null) {
- workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
+ workSource = new WorkSource(mCallerIdentity.uid, mCallerIdentity.packageName);
}
mWakeLock.setWorkSource(workSource);
@@ -1136,7 +1116,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (manager == null) {
continue;
}
- if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.mUid))
+ if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.uid))
&& !isSettingsExempt(updateRecord)) {
continue;
}
@@ -1156,42 +1136,43 @@ public class LocationManagerService extends ILocationManager.Stub {
mOpMonitoring = updateMonitoring(
requestingLocation,
mOpMonitoring,
- AppOpsManager.OP_MONITOR_LOCATION);
+ false);
// Now update monitoring of high power requests only.
boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
mOpHighPowerMonitoring = updateMonitoring(
requestingHighPowerLocation,
mOpHighPowerMonitoring,
- AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
+ true);
if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
- // Send an intent to notify that a high power request has been added/removed.
- Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // Send an intent to notify that a high power request has been added/removed.
+ Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
- /**
- * Update AppOps monitoring for a single location request and op type.
- *
- * @param allowMonitoring True if monitoring is allowed for this request/op.
- * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
- * @param op AppOps code for the op to update.
- * @return True if monitoring is on for this request/op after updating.
- */
private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
- int op) {
+ boolean highPower) {
if (!currentlyMonitoring) {
if (allowMonitoring) {
- return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
- mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
- == AppOpsManager.MODE_ALLOWED;
+ if (!highPower) {
+ return mAppOpsHelper.startLocationMonitoring(mCallerIdentity);
+ } else {
+ return mAppOpsHelper.startHighPowerLocationMonitoring(mCallerIdentity);
+ }
}
} else {
- if (!allowMonitoring
- || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
- mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
+ if (!allowMonitoring || !mAppOpsHelper.checkLocationAccess(mCallerIdentity)) {
+ if (!highPower) {
+ mAppOpsHelper.stopLocationMonitoring(mCallerIdentity);
+ } else {
+ mAppOpsHelper.stopHighPowerLocationMonitoring(mCallerIdentity);
+ }
return false;
}
}
@@ -1230,7 +1211,7 @@ public class LocationManagerService extends ILocationManager.Stub {
new Location(location));
try {
mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
- getResolutionPermission(mAllowedResolutionLevel),
+ CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exception.
@@ -1265,7 +1246,7 @@ public class LocationManagerService extends ILocationManager.Stub {
providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
try {
mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
- getResolutionPermission(mAllowedResolutionLevel),
+ CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exception.
@@ -1289,8 +1270,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void binderDied() {
- if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
-
synchronized (mLock) {
removeUpdatesLocked(this);
clearPendingBroadcastsLocked();
@@ -1380,11 +1359,9 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
- String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
- callback, packageName, featureId, listenerIdentifier);
+ callback, packageName, featureId);
}
@Override
@@ -1393,9 +1370,10 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
+ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
+ String featureId) {
return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
- wakeOnFifoFull, packageName);
+ wakeOnFifoFull, packageName, featureId);
}
@Override
@@ -1419,110 +1397,6 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- private String getResolutionPermission(int resolutionLevel) {
- switch (resolutionLevel) {
- case RESOLUTION_LEVEL_FINE:
- return ACCESS_FINE_LOCATION;
- case RESOLUTION_LEVEL_COARSE:
- return ACCESS_COARSE_LOCATION;
- default:
- return null;
- }
- }
-
- private int getAllowedResolutionLevel(int pid, int uid) {
- if (mContext.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
- return RESOLUTION_LEVEL_FINE;
- } else if (mContext.checkPermission(ACCESS_COARSE_LOCATION, pid, uid)
- == PERMISSION_GRANTED) {
- return RESOLUTION_LEVEL_COARSE;
- } else {
- return RESOLUTION_LEVEL_NONE;
- }
- }
-
- private int getCallerAllowedResolutionLevel() {
- return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
- }
-
- private boolean checkCallingOrSelfLocationPermission() {
- return mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED
- || mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
- == PERMISSION_GRANTED;
- }
-
- private void enforceCallingOrSelfLocationPermission() {
- if (checkCallingOrSelfLocationPermission()) {
- return;
- }
-
- throw new SecurityException("uid " + Binder.getCallingUid() + " does not have "
- + ACCESS_COARSE_LOCATION + " or " + ACCESS_FINE_LOCATION + ".");
- }
-
- private void enforceCallingOrSelfPackageName(String packageName) {
- int uid = Binder.getCallingUid();
- if (ArrayUtils.contains(mPackageManager.getPackagesForUid(uid), packageName)) {
- return;
- }
-
- throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
- }
-
- public static int resolutionLevelToOp(int allowedResolutionLevel) {
- if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
- if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
- return AppOpsManager.OP_COARSE_LOCATION;
- } else {
- return AppOpsManager.OP_FINE_LOCATION;
- }
- }
- return -1;
- }
-
- private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
- switch (allowedResolutionLevel) {
- case RESOLUTION_LEVEL_COARSE:
- return AppOpsManager.OPSTR_COARSE_LOCATION;
- case RESOLUTION_LEVEL_FINE:
- // fall through
- case RESOLUTION_LEVEL_NONE:
- // fall through
- default:
- // Use the most restrictive ops if not sure.
- return AppOpsManager.OPSTR_FINE_LOCATION;
- }
- }
-
- private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
- @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
- int op = resolutionLevelToOp(allowedResolutionLevel);
- if (op >= 0) {
- if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
- != AppOpsManager.MODE_ALLOWED) {
- return false;
- }
- }
-
- return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
- }
-
- private boolean checkLocationAccess(int pid, int uid, String packageName,
- int allowedResolutionLevel) {
- int op = resolutionLevelToOp(allowedResolutionLevel);
- if (op >= 0) {
- if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
- return false;
- }
- }
-
- return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
- }
-
- /**
- * Returns all providers by name, including passive and the ones that are not permitted to
- * be accessed by the calling activity or are currently disabled, but excluding fused.
- */
@Override
public List<String> getAllProviders() {
ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
@@ -1535,14 +1409,9 @@ public class LocationManagerService extends ILocationManager.Stub {
return providers;
}
- /**
- * Return all providers by name, that match criteria and are optionally
- * enabled.
- * Can return passive provider, but never returns fused provider.
- */
@Override
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
- if (!checkCallingOrSelfLocationPermission()) {
+ if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext)) {
return Collections.emptyList();
}
@@ -1556,9 +1425,8 @@ public class LocationManagerService extends ILocationManager.Stub {
if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
continue;
}
- if (criteria != null
- && !android.location.LocationProvider.propertiesMeetCriteria(
- name, manager.getProperties(), criteria)) {
+ if (criteria != null && !LocationProvider.propertiesMeetCriteria(name,
+ manager.getProperties(), criteria)) {
continue;
}
providers.add(name);
@@ -1567,18 +1435,14 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- /**
- * Return the name of the best provider given a Criteria object.
- * This method has been deprecated from the public API,
- * and the whole LocationProvider (including #meetsCriteria)
- * has been deprecated as well. So this method now uses
- * some simplified logic.
- */
@Override
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
- List<String> providers = getProviders(criteria, enabledOnly);
- if (providers.isEmpty()) {
- providers = getProviders(null, enabledOnly);
+ List<String> providers;
+ synchronized (mLock) {
+ providers = getProviders(criteria, enabledOnly);
+ if (providers.isEmpty()) {
+ providers = getProviders(null, enabledOnly);
+ }
}
if (!providers.isEmpty()) {
@@ -1601,7 +1465,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (records != null) {
for (UpdateRecord record : records) {
if (!mUserInfoHelper.isCurrentUserId(
- UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
continue;
}
@@ -1658,20 +1522,17 @@ public class LocationManagerService extends ILocationManager.Stub {
// initialize the low power mode to true and set to false if any of the records requires
providerRequest.setLowPowerMode(true);
for (UpdateRecord record : records) {
- int userId = UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid);
- if (!mUserInfoHelper.isCurrentUserId(userId)) {
+ CallerIdentity identity = record.mReceiver.mCallerIdentity;
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
continue;
}
- if (!checkLocationAccess(
- record.mReceiver.mCallerIdentity.mPid,
- record.mReceiver.mCallerIdentity.mUid,
- record.mReceiver.mCallerIdentity.mPackageName,
- record.mReceiver.mAllowedResolutionLevel)) {
+
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
continue;
}
final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
|| (isForegroundOnlyMode && !record.mIsForegroundUid);
- if (!manager.isEnabled(userId) || isBatterySaverDisablingLocation) {
+ if (!manager.isEnabled(identity.userId) || isBatterySaverDisablingLocation) {
if (isSettingsExempt(record)) {
providerRequest.setLocationSettingsIgnored(true);
providerRequest.setLowPowerMode(false);
@@ -1718,7 +1579,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
for (UpdateRecord record : records) {
if (mUserInfoHelper.isCurrentUserId(
- UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
LocationRequest locationRequest = record.mRequest;
// Don't assign battery blame for update records whose
@@ -1735,8 +1596,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// Assign blame to caller if there's no WorkSource associated with
// the request or if it's invalid.
providerRequest.getWorkSource().add(
- record.mReceiver.mCallerIdentity.mUid,
- record.mReceiver.mCallerIdentity.mPackageName);
+ record.mReceiver.mCallerIdentity.uid,
+ record.mReceiver.mCallerIdentity.packageName);
}
}
}
@@ -1775,16 +1636,16 @@ public class LocationManagerService extends ILocationManager.Stub {
}
private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
- if (callerIdentity.mUid == Process.SYSTEM_UID) {
+ if (callerIdentity.uid == Process.SYSTEM_UID) {
return true;
}
if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
- callerIdentity.mPackageName)) {
+ callerIdentity.packageName)) {
return true;
}
- return mLocalService.isProviderPackage(callerIdentity.mPackageName);
+ return mLocalService.isProviderPackage(callerIdentity.packageName);
}
@@ -1794,11 +1655,11 @@ public class LocationManagerService extends ILocationManager.Stub {
}
if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
- record.mReceiver.mCallerIdentity.mPackageName)) {
+ record.mReceiver.mCallerIdentity.packageName)) {
return true;
}
- return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
+ return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.packageName);
}
@@ -1821,9 +1682,9 @@ public class LocationManagerService extends ILocationManager.Stub {
mRealRequest = request;
mRequest = request;
mReceiver = receiver;
- mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid);
+ mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.uid);
- if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
+ if (D && receiver.mCallerIdentity.pid == Process.myPid()) {
mStackTrace = new Throwable();
}
@@ -1835,7 +1696,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// Update statistics for historical location requests by package/provider
mRequestStatistics.startRequesting(
- mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
+ mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
provider, request.getInterval(), mIsForegroundUid);
}
@@ -1845,7 +1706,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private void updateForeground(boolean isForeground) {
mIsForegroundUid = isForeground;
mRequestStatistics.updateForeground(
- mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
+ mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
mProvider, isForeground);
}
@@ -1853,19 +1714,18 @@ public class LocationManagerService extends ILocationManager.Stub {
* Method to be called when a record will no longer be used.
*/
private void disposeLocked(boolean removeReceiver) {
- String packageName = mReceiver.mCallerIdentity.mPackageName;
- mRequestStatistics.stopRequesting(packageName, mReceiver.mCallerIdentity.mFeatureId,
- mProvider);
+ CallerIdentity identity = mReceiver.mCallerIdentity;
+ mRequestStatistics.stopRequesting(identity.packageName, identity.featureId, mProvider);
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_ENDED,
LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
- packageName,
+ identity.packageName,
mRealRequest,
mReceiver.isListener(),
mReceiver.isPendingIntent(),
/* geofence= */ null,
- mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid));
+ mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.uid));
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -1889,18 +1749,10 @@ public class LocationManagerService extends ILocationManager.Stub {
public String toString() {
StringBuilder b = new StringBuilder("UpdateRecord[");
b.append(mProvider).append(" ");
- b.append(mReceiver.mCallerIdentity.mPackageName);
- String featureId = mReceiver.mCallerIdentity.mFeatureId;
- if (featureId != null) {
- b.append(" ").append(featureId).append(" ");
- }
- b.append("(").append(mReceiver.mCallerIdentity.mUid);
- if (mIsForegroundUid) {
- b.append(" foreground");
- } else {
- b.append(" background");
+ b.append(mReceiver.mCallerIdentity).append(" ");
+ if (!mIsForegroundUid) {
+ b.append("(background) ");
}
- b.append(") ");
b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
if (mStackTrace != null) {
@@ -1915,14 +1767,13 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
- String packageName, @Nullable String featureId, WorkSource workSource,
- boolean hideFromAppOps, @NonNull String listenerIdentifier) {
+ private Receiver getReceiverLocked(ILocationListener listener, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
IBinder binder = listener.asBinder();
Receiver receiver = mReceivers.get(binder);
- if (receiver == null) {
- receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
- hideFromAppOps, listenerIdentifier);
+ if (receiver == null && identity != null) {
+ receiver = new Receiver(listener, null, identity, workSource,
+ hideFromAppOps);
if (!receiver.linkToListenerDeathNotificationLocked(
receiver.getListener().asBinder())) {
return null;
@@ -1933,13 +1784,12 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
- @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
- @NonNull String listenerIdentifier) {
+ private Receiver getReceiverLocked(PendingIntent intent, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
Receiver receiver = mReceivers.get(intent);
- if (receiver == null) {
- receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
- hideFromAppOps, listenerIdentifier);
+ if (receiver == null && identity != null) {
+ receiver = new Receiver(null, intent, identity, workSource,
+ hideFromAppOps);
mReceivers.put(intent, receiver);
}
return receiver;
@@ -1953,14 +1803,14 @@ public class LocationManagerService extends ILocationManager.Stub {
* @return a version of request that meets the given resolution and consistency requirements
* @hide
*/
- private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
+ private LocationRequest createSanitizedRequest(LocationRequest request, CallerIdentity identity,
boolean callerHasLocationHardwarePermission) {
LocationRequest sanitizedRequest = new LocationRequest(request);
if (!callerHasLocationHardwarePermission) {
// allow setting low power mode only for callers with location hardware permission
sanitizedRequest.setLowPowerMode(false);
}
- if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
+ if (identity.permissionLevel < PERMISSION_FINE) {
switch (sanitizedRequest.getQuality()) {
case LocationRequest.ACCURACY_FINE:
sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
@@ -1986,72 +1836,58 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
- PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
- enforceCallingOrSelfLocationPermission();
- enforceCallingOrSelfPackageName(packageName);
-
- synchronized (mLock) {
- if (request == null) request = DEFAULT_LOCATION_REQUEST;
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- WorkSource workSource = request.getWorkSource();
- if (workSource != null && !workSource.isEmpty()) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.UPDATE_DEVICE_STATS, null);
- }
- boolean hideFromAppOps = request.getHideFromAppOps();
- if (hideFromAppOps) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.UPDATE_APP_OPS_STATS, null);
- }
- if (request.isLocationSettingsIgnored()) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.WRITE_SECURE_SETTINGS, null);
- }
- boolean callerHasLocationHardwarePermission =
- mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
- == PERMISSION_GRANTED;
- LocationRequest sanitizedRequest = createSanitizedRequest(request,
- allowedResolutionLevel,
- callerHasLocationHardwarePermission);
-
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
+ PendingIntent intent, String packageName, String featureId) {
+ if (request == null) {
+ request = DEFAULT_LOCATION_REQUEST;
+ }
- long identity = Binder.clearCallingIdentity();
- try {
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
- // We don't check for MODE_IGNORED here; we will do that when we go to deliver
- // a location.
- checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
+ WorkSource workSource = request.getWorkSource();
+ if (workSource != null && !workSource.isEmpty()) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.UPDATE_DEVICE_STATS, null);
+ }
+ boolean hideFromAppOps = request.getHideFromAppOps();
+ if (hideFromAppOps) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.UPDATE_APP_OPS_STATS, null);
+ }
+ if (request.isLocationSettingsIgnored()) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.WRITE_SECURE_SETTINGS, null);
+ }
+ boolean callerHasLocationHardwarePermission =
+ mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
+ == PERMISSION_GRANTED;
+ LocationRequest sanitizedRequest = createSanitizedRequest(request,
+ identity,
+ callerHasLocationHardwarePermission);
- if (intent == null && listener == null) {
- throw new IllegalArgumentException("need either listener or intent");
- } else if (intent != null && listener != null) {
- throw new IllegalArgumentException(
- "cannot register both listener and intent");
- }
+ if (intent == null && listener == null) {
+ throw new IllegalArgumentException("need either listener or intent");
+ } else if (intent != null && listener != null) {
+ throw new IllegalArgumentException(
+ "cannot register both listener and intent");
+ }
- mLocationUsageLogger.logLocationApiUsage(
- LocationStatsEnums.USAGE_STARTED,
- LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
- packageName, request, listener != null, intent != null,
- /* geofence= */ null,
- mAppForegroundHelper.getImportance(uid));
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
+ packageName, request, listener != null, intent != null,
+ /* geofence= */ null,
+ mAppForegroundHelper.getImportance(identity.uid));
- Receiver receiver;
- if (intent != null) {
- receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
- workSource, hideFromAppOps, listenerIdentifier);
- } else {
- receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
- workSource, hideFromAppOps, listenerIdentifier);
- }
+ synchronized (mLock) {
+ Receiver receiver;
+ if (intent != null) {
+ receiver = getReceiverLocked(intent, identity, workSource, hideFromAppOps);
+ } else {
+ receiver = getReceiverLocked(listener, identity, workSource, hideFromAppOps);
+ }
+ if (receiver != null) {
requestLocationUpdatesLocked(sanitizedRequest, receiver);
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
}
@@ -2078,28 +1914,27 @@ public class LocationManagerService extends ILocationManager.Stub {
oldRecord.disposeLocked(false);
}
- int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
- if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
- // Notify the listener that updates are currently disabled - but only if the request
- // does not ignore location settings
- receiver.callProviderEnabledLocked(name, false);
- }
+ long identity = Binder.clearCallingIdentity();
+ try {
+ int userId = UserHandle.getUserId(receiver.mCallerIdentity.uid);
+ if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
+ // Notify the listener that updates are currently disabled - but only if the request
+ // does not ignore location settings
+ receiver.callProviderEnabledLocked(name, false);
+ }
- applyRequirementsLocked(name);
+ applyRequirementsLocked(name);
- // Update the monitoring here just in case multiple location requests were added to the
- // same receiver (this request may be high power and the initial might not have been).
- receiver.updateMonitoring(true);
+ // Update the monitoring here just in case multiple location requests were added to the
+ // same receiver (this request may be high power and the initial might not have been).
+ receiver.updateMonitoring(true);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
- public void removeUpdates(ILocationListener listener, PendingIntent intent,
- String packageName) {
- enforceCallingOrSelfPackageName(packageName);
-
- int pid = Binder.getCallingPid();
- int uid = Binder.getCallingUid();
-
+ public void removeUpdates(ILocationListener listener, PendingIntent intent) {
if (intent == null && listener == null) {
throw new IllegalArgumentException("need either listener or intent");
} else if (intent != null && listener != null) {
@@ -2109,17 +1944,13 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
Receiver receiver;
if (intent != null) {
- receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
+ receiver = getReceiverLocked(intent, null, null, false);
} else {
- receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
- "");
+ receiver = getReceiverLocked(listener, null, null, false);
}
- long identity = Binder.clearCallingIdentity();
- try {
+ if (receiver != null) {
removeUpdatesLocked(receiver);
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
}
@@ -2161,25 +1992,14 @@ public class LocationManagerService extends ILocationManager.Stub {
request = DEFAULT_LOCATION_REQUEST;
}
- enforceCallingOrSelfLocationPermission();
- enforceCallingOrSelfPackageName(packageName);
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- if (!reportLocationAccessNoThrow(Binder.getCallingPid(), Binder.getCallingUid(),
- packageName, featureId, allowedResolutionLevel, null)) {
- if (D) {
- Log.d(TAG, "not returning last loc for no op app: " + packageName);
- }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, identity.packageName)) {
return null;
}
-
- int userId = UserHandle.getCallingUserId();
-
- if (mSettingsHelper.isLocationPackageBlacklisted(userId, packageName)) {
- return null;
- }
-
- if (!mUserInfoHelper.isCurrentUserId(userId)) {
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
return null;
}
@@ -2188,40 +2008,26 @@ public class LocationManagerService extends ILocationManager.Stub {
if (manager == null) {
return null;
}
-
- if (!manager.isEnabled(userId) && !request.isLocationSettingsIgnored()) {
+ if (!manager.isEnabled(identity.userId) && !request.isLocationSettingsIgnored()) {
return null;
}
- Location location;
- if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
- location = manager.getLastCoarseLocation(userId);
- } else {
- location = manager.getLastFineLocation(userId);
- }
- if (location == null) {
+ // appops check should always be right before delivery
+ if (!mAppOpsHelper.noteLocationAccess(identity)) {
return null;
}
- // Don't return stale location to apps with foreground-only location permission.
- String op = resolutionLevelToOpStr(allowedResolutionLevel);
- long locationAgeMs = NANOSECONDS.toMillis(
- SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs()
- && (mAppOps.unsafeCheckOp(op, Binder.getCallingUid(), packageName)
- == AppOpsManager.MODE_FOREGROUND)) {
- return null;
- }
+ Location location = manager.getLastLocation(identity.userId, identity.permissionLevel);
// make a defensive copy - the client could be in the same process as us
- return new Location(location);
+ return location != null ? new Location(location) : null;
}
}
@Override
public boolean getCurrentLocation(LocationRequest locationRequest,
ICancellationSignal remoteCancellationSignal, ILocationListener listener,
- String packageName, String featureId, String listenerIdentifier) {
+ String packageName, String featureId) {
// side effect of validating locationRequest and packageName
Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
if (lastLocation != null) {
@@ -2246,13 +2052,12 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
- listenerIdentifier);
+ requestLocationUpdates(locationRequest, listener, null, packageName, featureId);
CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
remoteCancellationSignal);
if (cancellationSignal != null) {
cancellationSignal.setOnCancelListener(
- () -> removeUpdates(listener, null, packageName));
+ () -> removeUpdates(listener, null));
}
return true;
}
@@ -2265,14 +2070,14 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- Location location = gpsManager.getLastFineLocation(UserHandle.getCallingUserId());
+ Location location = gpsManager.getLastLocation(UserHandle.getCallingUserId(),
+ PERMISSION_FINE);
if (location == null) {
return null;
}
long currentNanos = SystemClock.elapsedRealtimeNanos();
- long deltaMs = NANOSECONDS.toMillis(
- currentNanos - location.getElapsedRealtimeNanos());
+ long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos));
return new LocationTime(location.getTime() + deltaMs, currentNanos);
}
}
@@ -2295,32 +2100,27 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
+ String packageName, String featureId) {
+ if (request == null) {
+ request = DEFAULT_LOCATION_REQUEST;
+ }
- mContext.enforceCallingOrSelfPermission(ACCESS_FINE_LOCATION, null);
- enforceCallingOrSelfPackageName(packageName);
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
+
+ Objects.requireNonNull(intent);
- if (request == null) request = DEFAULT_LOCATION_REQUEST;
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- if (intent == null) {
- throw new IllegalArgumentException("invalid pending intent: " + null);
- }
- // Require that caller can manage given document
boolean callerHasLocationHardwarePermission =
mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
== PERMISSION_GRANTED;
- LocationRequest sanitizedRequest = createSanitizedRequest(request,
- allowedResolutionLevel,
+ LocationRequest sanitizedRequest = createSanitizedRequest(request, identity,
callerHasLocationHardwarePermission);
if (D) {
Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
}
- // geo-fence manager uses the public location API, need to clear identity
- int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
+ if (identity.userId != UserHandle.USER_SYSTEM) {
// temporary measure until geofences work for secondary users
Log.w(TAG, "proximity alerts are currently available only to the primary user");
return;
@@ -2334,15 +2134,9 @@ public class LocationManagerService extends ILocationManager.Stub {
/* hasListener= */ false,
true,
geofence,
- mAppForegroundHelper.getImportance(uid));
+ mAppForegroundHelper.getImportance(identity.uid));
- long identity = Binder.clearCallingIdentity();
- try {
- mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
- uid, packageName, featureId, listenerIdentifier);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ mGeofenceManager.addFence(sanitizedRequest, geofence, intent, identity);
}
@Override
@@ -2350,7 +2144,6 @@ public class LocationManagerService extends ILocationManager.Stub {
if (intent == null) {
throw new IllegalArgumentException("invalid pending intent: " + null);
}
- enforceCallingOrSelfPackageName(packageName);
if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
@@ -2387,13 +2180,9 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
- IGnssMeasurementsListener listener,
- String packageName, String featureId,
- String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ IGnssMeasurementsListener listener, String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
- request, listener, packageName, featureId, listenerIdentifier);
+ request, listener, packageName, featureId);
}
@Override
@@ -2414,18 +2203,17 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public long getGnssCapabilities(String packageName) {
- return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
- packageName);
+ public long getGnssCapabilities() {
+ return mGnssManagerService == null ? GnssCapabilities.INVALID_CAPABILITIES
+ : mGnssManagerService.getGnssCapabilities();
}
@Override
public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
+ String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener(
- listener, packageName, featureId, listenerIdentifier);
+ listener, packageName, featureId);
}
@Override
@@ -2437,11 +2225,9 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
- listener, packageName, featureId, listenerIdentifier);
+ listener, packageName, featureId);
}
@Override
@@ -2453,29 +2239,27 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
- Objects.requireNonNull(providerName);
- Objects.requireNonNull(command);
-
+ public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+ CallerIdentity.enforceCallingOrSelfLocationPermission(mContext);
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
- enforceCallingOrSelfLocationPermission();
+
+ LocationProviderManager manager = getLocationProviderManager(
+ Objects.requireNonNull(provider));
+ if (manager != null) {
+ manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(),
+ Objects.requireNonNull(command), extras);
+ }
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_STARTED,
LocationStatsEnums.API_SEND_EXTRA_COMMAND,
- providerName);
-
- LocationProviderManager manager = getLocationProviderManager(providerName);
- if (manager != null) {
- manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
- extras);
- }
+ provider);
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_ENDED,
LocationStatsEnums.API_SEND_EXTRA_COMMAND,
- providerName);
+ provider);
return true;
}
@@ -2537,12 +2321,10 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void setLocationEnabledForUser(boolean enabled, int userId) {
- if (UserHandle.getCallingUserId() != userId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
- null);
- }
- mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
- "Requires WRITE_SECURE_SETTINGS permission");
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, false, "setLocationEnabledForUser", null);
+
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null);
LocationManager.invalidateLocalLocationEnabledCaches();
mSettingsHelper.setLocationEnabled(enabled, userId);
@@ -2601,7 +2383,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private void handleLocationChangedLocked(LocationProviderManager manager, Location location,
+ private void handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation,
Location coarseLocation) {
if (!mProviderManagers.contains(manager)) {
Log.w(TAG, "received location from unknown provider: " + manager.getName());
@@ -2610,7 +2392,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// notify passive provider
if (manager != mPassiveManager) {
- mPassiveManager.updateLocation(location);
+ mPassiveManager.updateLocation(fineLocation);
}
long now = SystemClock.elapsedRealtime();
@@ -2624,59 +2406,45 @@ public class LocationManagerService extends ILocationManager.Stub {
// Broadcast location to all listeners
for (UpdateRecord r : records) {
Receiver receiver = r.mReceiver;
+ CallerIdentity identity = receiver.mCallerIdentity;
boolean receiverDead = false;
- int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
- if (!manager.isEnabled(userId) && !isSettingsExempt(r)) {
+ if (!manager.isEnabled(identity.userId) && !isSettingsExempt(r)) {
continue;
}
- if (!mUserInfoHelper.isCurrentUserId(userId)
- && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
- if (D) {
- Log.d(TAG, "skipping loc update for background user " + userId
- + " (app: " + receiver.mCallerIdentity.mPackageName + ")");
- }
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)
+ && !isProviderPackage(identity.packageName)) {
continue;
}
- if (mSettingsHelper.isLocationPackageBlacklisted(userId,
- receiver.mCallerIdentity.mPackageName)) {
- if (D) {
- Log.d(TAG, "skipping loc update for blacklisted app: " +
- receiver.mCallerIdentity.mPackageName);
- }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId,
+ identity.packageName)) {
continue;
}
- Location notifyLocation;
- if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
- notifyLocation = coarseLocation; // use coarse location
- } else {
- notifyLocation = location; // use fine location
- }
- if (shouldBroadcastSafeLocked(notifyLocation, r.mLastFixBroadcast, r, now)) {
- r.mLastFixBroadcast = notifyLocation;
- // Report location access before delivering location to the client. This will
- // note location delivery to appOps, so it should be called only when a
- // location is really being delivered to the client.
- if (!reportLocationAccessNoThrow(
- receiver.mCallerIdentity.mPid,
- receiver.mCallerIdentity.mUid,
- receiver.mCallerIdentity.mPackageName,
- receiver.mCallerIdentity.mFeatureId,
- receiver.mAllowedResolutionLevel,
- "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
- if (D) {
- Log.d(TAG, "skipping loc update for no op app: "
- + receiver.mCallerIdentity.mPackageName);
- }
+ Location location;
+ switch (identity.permissionLevel) {
+ case PERMISSION_COARSE:
+ location = coarseLocation;
+ break;
+ case PERMISSION_FINE:
+ location = fineLocation;
+ break;
+ default:
+ throw new AssertionError();
+ }
+
+ if (shouldBroadcastSafeLocked(location, r.mLastFixBroadcast, r, now)) {
+ r.mLastFixBroadcast = location;
+
+ // appops check should always be right before delivery
+ if (!mAppOpsHelper.noteLocationAccess(receiver.mCallerIdentity)) {
continue;
}
- if (!receiver.callLocationChangedLocked(notifyLocation)) {
- Log.w(TAG, "RemoteException calling onLocationChanged on "
- + receiver);
+
+ if (!receiver.callLocationChangedLocked(location)) {
receiverDead = true;
}
r.mRealRequest.decrementNumUpdates();
@@ -2733,7 +2501,6 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
-
@Override
public String getFromLocationName(String locationName,
double lowerLeftLatitude, double lowerLeftLongitude,
@@ -2752,9 +2519,10 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void addTestProvider(String provider, ProviderProperties properties,
- String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ String packageName, String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2770,9 +2538,10 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public void removeTestProvider(String provider, String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void removeTestProvider(String provider, String packageName, String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2790,15 +2559,17 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public void setTestProviderLocation(String provider, Location location, String packageName) {
- Preconditions.checkArgument(location.isComplete(),
- "incomplete location object, missing timestamp or accuracy?");
-
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void setTestProviderLocation(String provider, Location location, String packageName,
+ String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
+ Preconditions.checkArgument(location.isComplete(),
+ "incomplete location object, missing timestamp or accuracy?");
+
LocationProviderManager manager = getLocationProviderManager(provider);
if (manager == null) {
throw new IllegalArgumentException("provider doesn't exist: " + provider);
@@ -2808,9 +2579,11 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
- public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void setTestProviderEnabled(String provider, boolean enabled, String packageName,
+ String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2824,12 +2597,8 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
@NonNull
- public List<LocationRequest> getTestProviderCurrentRequests(String provider,
- String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
- return Collections.emptyList();
- }
+ public List<LocationRequest> getTestProviderCurrentRequests(String provider) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
LocationProviderManager manager = getLocationProviderManager(provider);
if (manager == null) {
diff --git a/services/core/java/com/android/server/LocationManagerServiceUtils.java b/services/core/java/com/android/server/LocationManagerServiceUtils.java
index ba1c81cdd975..9d0fe5e936bb 100644
--- a/services/core/java/com/android/server/LocationManagerServiceUtils.java
+++ b/services/core/java/com/android/server/LocationManagerServiceUtils.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.Log;
import com.android.server.location.CallerIdentity;
@@ -32,9 +31,6 @@ import java.util.function.Consumer;
*/
public class LocationManagerServiceUtils {
- private static final String TAG = "LocManagerServiceUtils";
- private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
-
/**
* Listener that can be linked to a binder.
* @param <TListener> listener type
@@ -49,10 +45,9 @@ public class LocationManagerServiceUtils {
public LinkedListener(
@Nullable TRequest request,
@NonNull TListener listener,
- String listenerName,
@NonNull CallerIdentity callerIdentity,
@NonNull Consumer<TListener> binderDeathCallback) {
- super(callerIdentity, listenerName);
+ super(callerIdentity);
mListener = listener;
mRequest = request;
mBinderDeathCallback = binderDeathCallback;
@@ -65,7 +60,6 @@ public class LocationManagerServiceUtils {
@Override
public void binderDied() {
- if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
mBinderDeathCallback.accept(mListener);
}
}
@@ -75,28 +69,20 @@ public class LocationManagerServiceUtils {
*/
public abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
protected final CallerIdentity mCallerIdentity;
- protected final String mListenerName;
- LinkedListenerBase(
- @NonNull CallerIdentity callerIdentity, @NonNull String listenerName) {
+ LinkedListenerBase(@NonNull CallerIdentity callerIdentity) {
mCallerIdentity = callerIdentity;
- mListenerName = listenerName;
}
@Override
public String toString() {
- return mListenerName + "[" + mCallerIdentity.mPackageName + "(" + mCallerIdentity.mPid
- + ")]";
+ return mCallerIdentity.toString();
}
public CallerIdentity getCallerIdentity() {
return mCallerIdentity;
}
- public String getListenerName() {
- return mListenerName;
- }
-
/**
* Link listener (i.e. callback) to a binder, so that it will be called upon binder's death.
*/
@@ -105,9 +91,6 @@ public class LocationManagerServiceUtils {
binder.linkToDeath(this, 0 /* flags */);
return true;
} catch (RemoteException e) {
- // if the remote process registering the listener is already dead, just swallow the
- // exception and return
- Log.w(TAG, "Could not link " + mListenerName + " death callback.", e);
return false;
}
}
@@ -119,7 +102,7 @@ public class LocationManagerServiceUtils {
try {
binder.unlinkToDeath(this, 0 /* flags */);
} catch (NoSuchElementException e) {
- Log.w(TAG, "Could not unlink " + mListenerName + " death callback.", e);
+ // ignore
}
}
}
diff --git a/services/core/java/com/android/server/location/AppOpsHelper.java b/services/core/java/com/android/server/location/AppOpsHelper.java
new file mode 100644
index 000000000000..9c279166ac8a
--- /dev/null
+++ b/services/core/java/com/android/server/location/AppOpsHelper.java
@@ -0,0 +1,253 @@
+/*
+ * 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;
+
+import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
+import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
+
+import static com.android.server.LocationManagerService.D;
+import static com.android.server.LocationManagerService.TAG;
+
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.FgThread;
+
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides helpers and listeners for appops.
+ */
+public class AppOpsHelper {
+
+ /**
+ * Listener for current user changes.
+ */
+ public interface LocationAppOpListener {
+
+ /**
+ * Called when something has changed about a location appop for the given package.
+ */
+ void onAppOpsChanged(String packageName);
+ }
+
+ private final Context mContext;
+ private final CopyOnWriteArrayList<LocationAppOpListener> mListeners;
+
+ @GuardedBy("this")
+ @Nullable
+ private AppOpsManager mAppOps;
+
+ public AppOpsHelper(Context context) {
+ mContext = context;
+ mListeners = new CopyOnWriteArrayList<>();
+ }
+
+ /** Called when system is ready. */
+ public synchronized void onSystemReady() {
+ if (mAppOps != null) {
+ return;
+ }
+
+ mAppOps = Objects.requireNonNull(mContext.getSystemService(AppOpsManager.class));
+ mAppOps.startWatchingMode(
+ AppOpsManager.OP_COARSE_LOCATION,
+ null,
+ AppOpsManager.WATCH_FOREGROUND_CHANGES,
+ new AppOpsManager.OnOpChangedInternalListener() {
+ public void onOpChanged(int op, String packageName) {
+ // invoked on ui thread, move to fg thread so ui thread isn't blocked
+ FgThread.getHandler().sendMessage(
+ PooledLambda.obtainMessage(AppOpsHelper::onAppOpChanged,
+ AppOpsHelper.this, packageName));
+ }
+ });
+ }
+
+ private void onAppOpChanged(String packageName) {
+ if (D) {
+ Log.v(TAG, "location appop changed for " + packageName);
+ }
+
+ for (LocationAppOpListener listener : mListeners) {
+ listener.onAppOpsChanged(packageName);
+ }
+ }
+
+ /**
+ * Adds a listener for app ops events. Callbacks occur on an unspecified thread.
+ */
+ public void addListener(LocationAppOpListener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes a listener for app ops events.
+ */
+ public void removeListener(LocationAppOpListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Checks if the given identity may have locations delivered without noting that a location is
+ * being delivered. This is a looser guarantee than {@link #noteLocationAccess(CallerIdentity)},
+ * and this function does not validate package arguments and so should not be used with
+ * unvalidated arguments or before actually delivering locations.
+ *
+ * @see AppOpsManager#checkOpNoThrow(int, int, String)
+ */
+ public boolean checkLocationAccess(CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.checkOpNoThrow(
+ CallerIdentity.asAppOp(callerIdentity.permissionLevel),
+ callerIdentity.uid,
+ callerIdentity.packageName) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Notes location access to the given identity, ie, location delivery. This method should be
+ * called right before a location is delivered, and if it returns false, the location should not
+ * be delivered.
+ */
+ public boolean noteLocationAccess(CallerIdentity identity) {
+ return noteOpNoThrow(CallerIdentity.asAppOp(identity.permissionLevel), identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is using location at normal/low power levels. If
+ * this function returns false, do not later call
+ * {@link #stopLocationMonitoring(CallerIdentity)}.
+ */
+ public boolean startLocationMonitoring(CallerIdentity identity) {
+ return startLocationMonitoring(OP_MONITOR_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is no longer using location at normal/low power
+ * levels.
+ */
+ public void stopLocationMonitoring(CallerIdentity identity) {
+ stopLocationMonitoring(OP_MONITOR_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is using location at high levels. If this function
+ * returns false, do not later call {@link #stopLocationMonitoring(CallerIdentity)}.
+ */
+ public boolean startHighPowerLocationMonitoring(CallerIdentity identity) {
+ return startLocationMonitoring(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is no longer using location at high power levels.
+ */
+ public void stopHighPowerLocationMonitoring(CallerIdentity identity) {
+ stopLocationMonitoring(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+ }
+
+ /**
+ * Notes access to any mock location APIs. If this call returns false, access to the APIs should
+ * silently fail.
+ */
+ public boolean noteMockLocationAccess(CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // note that this is not the no throw version of noteOp, this call may throw exceptions
+ return mAppOps.noteOp(
+ AppOpsManager.OP_MOCK_LOCATION,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean startLocationMonitoring(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.startOpNoThrow(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ false,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private void stopLocationMonitoring(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mAppOps.finishOp(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean noteOpNoThrow(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.noteOpNoThrow(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
index 75ba5b8c212e..b84fd13415fc 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -16,25 +16,211 @@
package com.android.server.location;
-import android.annotation.NonNull;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Represents the calling process's uid, pid, and package name.
*/
-public class CallerIdentity {
- public final int mUid;
- public final int mPid;
- public final String mPackageName;
- public final @Nullable String mFeatureId;
- public final @NonNull String mListenerIdentifier;
-
- public CallerIdentity(int uid, int pid, String packageName, @Nullable String featureId,
- @NonNull String listenerIdentifier) {
- mUid = uid;
- mPid = pid;
- mPackageName = packageName;
- mFeatureId = featureId;
- mListenerIdentifier = listenerIdentifier;
+public final class CallerIdentity {
+
+ public static final int PERMISSION_NONE = 0;
+ public static final int PERMISSION_COARSE = 1;
+ public static final int PERMISSION_FINE = 2;
+
+ @IntDef({PERMISSION_NONE, PERMISSION_COARSE, PERMISSION_FINE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionLevel {}
+
+ /**
+ * Converts the given permission level to the corresponding permission.
+ */
+ public static String asPermission(@PermissionLevel int permissionLevel) {
+ switch (permissionLevel) {
+ case PERMISSION_COARSE:
+ return ACCESS_COARSE_LOCATION;
+ case PERMISSION_FINE:
+ return ACCESS_FINE_LOCATION;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Converts the given permission level to the corresponding appop.
+ */
+ public static int asAppOp(@PermissionLevel int permissionLevel) {
+ switch (permissionLevel) {
+ case PERMISSION_COARSE:
+ return AppOpsManager.OP_COARSE_LOCATION;
+ case PERMISSION_FINE:
+ return AppOpsManager.OP_FINE_LOCATION;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public static CallerIdentity fromBinder(Context context, String packageName,
+ @Nullable String featureId) {
+ int uid = Binder.getCallingUid();
+ if (!ArrayUtils.contains(context.getPackageManager().getPackagesForUid(uid), packageName)) {
+ throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
+ }
+
+ return fromBinderUnsafe(context, packageName, featureId);
+ }
+
+ /**
+ * Creates a CallerIdentity from the current binder identity, using the given package and
+ * feature id. The package will not be checked to enforce that it belongs to the calling uid -
+ * this method should only be used if the package will be validated by some other means, such as
+ * an appops call.
+ */
+ public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
+ @Nullable String featureId) {
+ return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(),
+ UserHandle.getCallingUserId(), packageName, featureId,
+ getBinderPermissionLevel(context));
+ }
+
+ /**
+ * Throws a security exception if the caller does not hold a location permission.
+ */
+ public static void enforceCallingOrSelfLocationPermission(Context context) {
+ enforceLocationPermission(Binder.getCallingUid(), getBinderPermissionLevel(context));
+ }
+
+ /**
+ * Returns false if the caller does not hold a location permission, true otherwise.
+ */
+ public static boolean checkCallingOrSelfLocationPermission(Context context) {
+ return checkLocationPermission(getBinderPermissionLevel(context));
+ }
+
+ private static void enforceLocationPermission(int uid, @PermissionLevel int permissionLevel) {
+ if (checkLocationPermission(permissionLevel)) {
+ return;
+ }
+
+ throw new SecurityException("uid " + uid + " does not have " + ACCESS_COARSE_LOCATION
+ + " or " + ACCESS_FINE_LOCATION + ".");
+ }
+
+ private static boolean checkLocationPermission(@PermissionLevel int permissionLevel) {
+ return permissionLevel >= PERMISSION_COARSE;
+ }
+
+ private static @PermissionLevel int getBinderPermissionLevel(Context context) {
+ if (context.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) {
+ return PERMISSION_FINE;
+ }
+ if (context.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) {
+ return PERMISSION_COARSE;
+ }
+
+ return PERMISSION_NONE;
+ }
+
+ /** The calling UID. */
+ public final int uid;
+
+ /** The calling PID. */
+ public final int pid;
+
+ /** The calling user. */
+ public final int userId;
+
+ /** The calling package name. */
+ public final String packageName;
+
+ /** The calling feature id. */
+ public final @Nullable String featureId;
+
+ /**
+ * The calling location permission level. This field should only be used for validating
+ * permissions for API access. It should not be used for validating permissions for location
+ * access - that must be done through appops.
+ */
+ public final @PermissionLevel int permissionLevel;
+
+ @VisibleForTesting
+ public CallerIdentity(int uid, int pid, int userId, String packageName,
+ @Nullable String featureId, @PermissionLevel int permissionLevel) {
+ this.uid = uid;
+ this.pid = pid;
+ this.userId = userId;
+ this.packageName = Objects.requireNonNull(packageName);
+ this.featureId = featureId;
+ this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE,
+ PERMISSION_FINE, "permissionLevel");
+ }
+
+ /**
+ * Throws a security exception if the CallerIdentity does not hold a location permission.
+ */
+ public void enforceLocationPermission() {
+ enforceLocationPermission(uid, permissionLevel);
+ }
+
+ @Override
+ public String toString() {
+ int length = 10 + packageName.length();
+ if (featureId != null) {
+ length += featureId.length();
+ }
+
+ StringBuilder builder = new StringBuilder(length);
+ builder.append(pid).append("/").append(packageName);
+ if (featureId != null) {
+ builder.append("[");
+ if (featureId.startsWith(packageName)) {
+ builder.append(featureId.substring(packageName.length()));
+ } else {
+ builder.append(featureId);
+ }
+ builder.append("]");
+ }
+ return builder.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof CallerIdentity)) {
+ return false;
+ }
+ CallerIdentity that = (CallerIdentity) o;
+ return uid == that.uid
+ && pid == that.pid
+ && packageName.equals(that.packageName)
+ && Objects.equals(featureId, that.featureId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uid, pid, packageName, featureId);
}
}
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 4e9c06761e54..195b059b7374 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -16,9 +16,6 @@
package com.android.server.location;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -38,7 +35,6 @@ import android.util.Log;
import android.util.Slog;
import com.android.server.FgThread;
-import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
import java.io.PrintWriter;
@@ -125,16 +121,10 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
- int allowedResolutionLevel, int uid, String packageName, @Nullable String featureId,
- @NonNull String listenerIdentifier) {
- if (D) {
- Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
- + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
- }
-
+ CallerIdentity identity) {
GeofenceState state = new GeofenceState(geofence,
request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()),
- allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier, intent);
+ identity, intent);
synchronized (mLock) {
// first make sure it doesn't already exist
for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -182,26 +172,14 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
synchronized (mLock) {
- Iterator<GeofenceState> iter = mFences.iterator();
- while (iter.hasNext()) {
- GeofenceState state = iter.next();
- if (state.mPackageName.equals(packageName)) {
- iter.remove();
- }
- }
+ mFences.removeIf(state -> state.mIdentity.packageName.equals(packageName));
scheduleUpdateFencesLocked();
}
}
private void removeExpiredFencesLocked() {
long time = SystemClock.elapsedRealtime();
- Iterator<GeofenceState> iter = mFences.iterator();
- while (iter.hasNext()) {
- GeofenceState state = iter.next();
- if (state.mExpireAt < time) {
- iter.remove();
- }
- }
+ mFences.removeIf(state -> state.mExpireAt < time);
}
private void scheduleUpdateFencesLocked() {
@@ -266,24 +244,17 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
- state.mPackageName)) {
- if (D) {
- Slog.d(TAG, "skipping geofence processing for blacklisted app: "
- + state.mPackageName);
- }
+ CallerIdentity identity = state.mIdentity;
+ if (mSettingsStore.isLocationPackageBlacklisted(identity.userId,
+ identity.packageName)) {
continue;
}
- int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
+ int op = CallerIdentity.asAppOp(identity.permissionLevel);
if (op >= 0) {
- if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
- state.mPackageName, state.mFeatureId, state.mListenerIdentifier)
+ if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, identity.uid,
+ identity.packageName, identity.featureId, null)
!= AppOpsManager.MODE_ALLOWED) {
- if (D) {
- Slog.d(TAG, "skipping geofence processing for no op app: "
- + state.mPackageName);
- }
continue;
}
}
@@ -429,7 +400,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
public void dump(PrintWriter pw) {
for (GeofenceState state : mFences) {
- pw.println(state.mPackageName + " " + state.mFence);
+ pw.println(state.mIdentity + " " + state.mFence);
}
}
diff --git a/services/core/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
index a91a1dcb78e7..13318bfa6492 100644
--- a/services/core/java/com/android/server/location/GeofenceState.java
+++ b/services/core/java/com/android/server/location/GeofenceState.java
@@ -17,8 +17,6 @@
package com.android.server.location;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.location.Geofence;
import android.location.Location;
@@ -37,29 +35,20 @@ public class GeofenceState {
public final Geofence mFence;
private final Location mLocation;
public final long mExpireAt;
- public final int mAllowedResolutionLevel;
- public final int mUid;
- public final String mPackageName;
- public final @Nullable String mFeatureId;
- public final @NonNull String mListenerIdentifier;
+ public final CallerIdentity mIdentity;
public final PendingIntent mIntent;
int mState; // current state
double mDistanceToCenter; // current distance to center of fence
- public GeofenceState(Geofence fence, long expireAt, int allowedResolutionLevel, int uid,
- String packageName, @Nullable String featureId, @NonNull String listenerIdentifier,
+ public GeofenceState(Geofence fence, long expireAt, CallerIdentity identity,
PendingIntent intent) {
mState = STATE_UNKNOWN;
mDistanceToCenter = Double.MAX_VALUE;
mFence = fence;
mExpireAt = expireAt;
- mAllowedResolutionLevel = allowedResolutionLevel;
- mUid = uid;
- mPackageName = packageName;
- mFeatureId = featureId;
- mListenerIdentifier = listenerIdentifier;
+ mIdentity = identity;
mIntent = intent;
mLocation = new Location("");
diff --git a/services/core/java/com/android/server/location/LocationPermissionUtil.java b/services/core/java/com/android/server/location/LocationPermissionUtil.java
index 4465f31cb45b..80b93b5e8ef6 100644
--- a/services/core/java/com/android/server/location/LocationPermissionUtil.java
+++ b/services/core/java/com/android/server/location/LocationPermissionUtil.java
@@ -49,13 +49,13 @@ public final class LocationPermissionUtil {
private static boolean hasPermissionLocationHardware(Context context,
CallerIdentity callerIdentity) {
return context.checkPermission(android.Manifest.permission.LOCATION_HARDWARE,
- callerIdentity.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED;
+ 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.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED;
+ callerIdentity.pid, callerIdentity.uid) == PackageManager.PERMISSION_GRANTED;
}
private LocationPermissionUtil() {}
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index f6652892c3de..9c908dfb4276 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -179,13 +179,12 @@ public abstract class RemoteListenerHelper<TRequest, TListener extends IInterfac
if (LocationPermissionUtil.doesCallerReportToAppOps(context, callerIdentity)) {
// The caller is identified as a location provider that will report location
// access to AppOps. Skip noteOp but do checkOp to check for location permission.
- return mAppOps.checkOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
- callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
+ return mAppOps.checkOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.uid,
+ callerIdentity.packageName) == AppOpsManager.MODE_ALLOWED;
}
- return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
- callerIdentity.mPackageName, callerIdentity.mFeatureId,
- "Location sent to " + callerIdentity.mListenerIdentifier)
+ return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.uid,
+ callerIdentity.packageName, callerIdentity.featureId, null)
== AppOpsManager.MODE_ALLOWED;
}
diff --git a/services/core/java/com/android/server/location/SettingsHelper.java b/services/core/java/com/android/server/location/SettingsHelper.java
index 5fe21bdf8950..7ab258c29b46 100644
--- a/services/core/java/com/android/server/location/SettingsHelper.java
+++ b/services/core/java/com/android/server/location/SettingsHelper.java
@@ -22,7 +22,6 @@ import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTE
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
-import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
import static android.provider.Settings.Secure.LOCATION_COARSE_ACCURACY_M;
import static android.provider.Settings.Secure.LOCATION_MODE;
import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
@@ -92,7 +91,6 @@ public class SettingsHelper {
private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
30 * 60 * 1000;
- private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
private static final float DEFAULT_COARSE_LOCATION_ACCURACY_M = 2000.0f;
private final Context mContext;
@@ -285,21 +283,6 @@ public class SettingsHelper {
}
/**
- * Retrieve maximum age of the last location.
- */
- public long getMaxLastLocationAgeMs() {
- long identity = Binder.clearCallingIdentity();
- try {
- return Settings.Global.getLong(
- mContext.getContentResolver(),
- LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_MAX_LAST_LOCATION_AGE_MS);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
* Retrieve the accuracy for coarsening location, ie, the grid size used for snap-to-grid
* coarsening.
*/
diff --git a/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
index d839095542c7..4ee1100b5297 100644
--- a/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
@@ -112,7 +112,7 @@ public abstract class GnssAntennaInfoProvider
foreach((IGnssAntennaInfoListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
logPermissionDisabledEventNotReported(
- TAG, callerIdentity.mPackageName, "GNSS antenna info");
+ TAG, callerIdentity.packageName, "GNSS antenna info");
return;
}
listener.onGnssAntennaInfoReceived(gnssAntennaInfos);
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 9e64e3aeae59..711f45cb7d28 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -16,15 +16,11 @@
package com.android.server.location.gnss;
-import static android.app.AppOpsManager.OP_FINE_LOCATION;
import static android.location.LocationManager.GPS_PROVIDER;
import android.Manifest;
-import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.Context;
-import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
@@ -41,7 +37,6 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Process;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.stats.location.LocationStatsEnums;
import android.util.ArrayMap;
import android.util.Log;
@@ -54,6 +49,7 @@ import com.android.server.LocalServices;
import com.android.server.LocationManagerServiceUtils.LinkedListener;
import com.android.server.LocationManagerServiceUtils.LinkedListenerBase;
import com.android.server.location.AppForegroundHelper;
+import com.android.server.location.AppOpsHelper;
import com.android.server.location.CallerIdentity;
import com.android.server.location.LocationUsageLogger;
import com.android.server.location.RemoteListenerHelper;
@@ -76,6 +72,7 @@ public class GnssManagerService {
}
private final Context mContext;
+ private final AppOpsHelper mAppOpsHelper;
private final SettingsHelper mSettingsHelper;
private final AppForegroundHelper mAppForegroundHelper;
private final LocationUsageLogger mLocationUsageLogger;
@@ -112,8 +109,6 @@ public class GnssManagerService {
@GuardedBy("this")
@Nullable private LocationManagerInternal mLocationManagerInternal;
- @GuardedBy("this")
- @Nullable private AppOpsManager mAppOpsManager;
private final Object mGnssBatchingLock = new Object();
@@ -127,19 +122,21 @@ public class GnssManagerService {
@GuardedBy("mGnssBatchingLock")
private boolean mGnssBatchingInProgress = false;
- public GnssManagerService(Context context, SettingsHelper settingsHelper,
- AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger) {
- this(context, settingsHelper, appForegroundHelper, locationUsageLogger, null);
+ public GnssManagerService(Context context, AppOpsHelper appOpsHelper,
+ SettingsHelper settingsHelper, AppForegroundHelper appForegroundHelper,
+ LocationUsageLogger locationUsageLogger) {
+ this(context, appOpsHelper, settingsHelper, appForegroundHelper, locationUsageLogger, null);
}
// Can use this constructor to inject GnssLocationProvider for testing
@VisibleForTesting
- GnssManagerService(Context context, SettingsHelper settingsHelper,
+ GnssManagerService(Context context, AppOpsHelper appOpsHelper, SettingsHelper settingsHelper,
AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger,
GnssLocationProvider gnssLocationProvider) {
Preconditions.checkState(isGnssSupported());
mContext = context;
+ mAppOpsHelper = appOpsHelper;
mSettingsHelper = settingsHelper;
mAppForegroundHelper = appForegroundHelper;
mLocationUsageLogger = locationUsageLogger;
@@ -169,11 +166,11 @@ public class GnssManagerService {
return;
}
+ mAppOpsHelper.onSystemReady();
mSettingsHelper.onSystemReady();
mAppForegroundHelper.onSystemReady();
mLocationManagerInternal = LocalServices.getService(LocationManagerInternal.class);
- mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mAppForegroundHelper.addListener(this::onAppForegroundChanged);
}
@@ -207,11 +204,7 @@ public class GnssManagerService {
* Get GNSS hardware capabilities. The capabilities returned are a bitfield as described in
* {@link android.location.GnssCapabilities}.
*/
- public long getGnssCapabilities(String packageName) {
- if (!checkLocationAppOp(packageName)) {
- return GnssCapabilities.INVALID_CAPABILITIES;
- }
-
+ public long getGnssCapabilities() {
return mGnssCapabilitiesProvider.getGnssCapabilities();
}
@@ -222,10 +215,6 @@ public class GnssManagerService {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return 0;
- }
-
synchronized (mGnssBatchingLock) {
return mGnssBatchingProvider.getBatchSize();
}
@@ -235,11 +224,13 @@ public class GnssManagerService {
* Starts GNSS batch collection. GNSS positions are collected in a batch before being delivered
* as a collection.
*/
- public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
+ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
+ String featureId) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
return false;
}
@@ -259,25 +250,19 @@ public class GnssManagerService {
* Adds a GNSS batching callback for delivering GNSS location batch results.
*/
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentity) {
+ @Nullable String featureId) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return false;
- }
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
- CallerIdentity callerIdentity =
- new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
- featureId, listenerIdentity);
synchronized (mGnssBatchingLock) {
mGnssBatchingCallback = callback;
mGnssBatchingDeathCallback =
new LinkedListener<>(
/* request= */ null,
callback,
- "BatchedLocationCallback",
- callerIdentity,
+ identity,
(IBatchedLocationCallback listener) -> {
stopGnssBatch();
removeGnssBatchingCallback();
@@ -297,10 +282,6 @@ public class GnssManagerService {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return;
- }
-
synchronized (mGnssBatchingLock) {
mGnssBatchingProvider.flush();
}
@@ -378,7 +359,7 @@ public class GnssManagerService {
LinkedListener<TRequest, TListener> linkedListener = entry.getValue();
CallerIdentity callerIdentity = linkedListener.getCallerIdentity();
TRequest request = linkedListener.getRequest();
- if (callerIdentity.mUid != uid) {
+ if (callerIdentity.uid != uid) {
continue;
}
@@ -396,21 +377,19 @@ public class GnssManagerService {
TListener listener,
String packageName,
@Nullable String featureId,
- @NonNull String listenerIdentifier,
RemoteListenerHelper<TRequest, TListener> gnssDataProvider,
ArrayMap<IBinder,
LinkedListener<TRequest, TListener>> gnssDataListeners,
Consumer<TListener> binderDeathCallback) {
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
return false;
}
- CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
- Binder.getCallingPid(), packageName, featureId, listenerIdentifier);
LinkedListener<TRequest, TListener> linkedListener = new LinkedListener<>(request, listener,
- listenerIdentifier, callerIdentity, binderDeathCallback);
+ identity, binderDeathCallback);
IBinder binder = listener.asBinder();
if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) {
return false;
@@ -429,11 +408,11 @@ public class GnssManagerService {
/* hasListener= */ true,
/* hasIntent= */ false,
/* geofence= */ null,
- mAppForegroundHelper.getImportance(callerIdentity.mUid));
+ mAppForegroundHelper.getImportance(identity.uid));
}
- if (mAppForegroundHelper.isAppForeground(callerIdentity.mUid)
- || isThrottlingExempt(callerIdentity)) {
- gnssDataProvider.addListener(request, listener, callerIdentity);
+ if (mAppForegroundHelper.isAppForeground(identity.uid)
+ || isThrottlingExempt(identity)) {
+ gnssDataProvider.addListener(request, listener, identity);
}
return true;
}
@@ -463,7 +442,7 @@ public class GnssManagerService {
gnssDataProvider == mGnssMeasurementsProvider
? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
: LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
- linkedListener.getCallerIdentity().mPackageName,
+ linkedListener.getCallerIdentity().packageName,
/* LocationRequest= */ null,
/* hasListener= */ true,
/* hasIntent= */ false,
@@ -485,7 +464,6 @@ public class GnssManagerService {
listener,
packageName,
featureId,
- "Gnss status",
mGnssStatusProvider,
mGnssStatusListeners,
this::unregisterGnssStatusCallback);
@@ -506,8 +484,7 @@ public class GnssManagerService {
*/
public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
IGnssMeasurementsListener listener, String packageName,
- @Nullable String featureId,
- @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
if (request != null && request.isFullTracking()) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE,
null);
@@ -518,7 +495,6 @@ public class GnssManagerService {
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssMeasurementsProvider,
mGnssMeasurementsListeners,
this::removeGnssMeasurementsListener);
@@ -533,10 +509,6 @@ public class GnssManagerService {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return;
- }
-
mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections(
measurementCorrections);
}
@@ -556,18 +528,16 @@ public class GnssManagerService {
*
* @param listener called when GNSS antenna info is received
* @param packageName name of requesting package
- * @return true if listener is successfully added, false otherwise
*/
public boolean addGnssAntennaInfoListener(
IGnssAntennaInfoListener listener, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
synchronized (mGnssAntennaInfoListeners) {
return addGnssDataListenerLocked(
/* request= */ null,
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssAntennaInfoProvider,
mGnssAntennaInfoListeners,
this::removeGnssAntennaInfoListener);
@@ -591,14 +561,13 @@ public class GnssManagerService {
*/
public boolean addGnssNavigationMessageListener(
IGnssNavigationMessageListener listener, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
synchronized (mGnssNavigationMessageListeners) {
return addGnssDataListenerLocked(
/* request= */ null,
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssNavigationMessageProvider,
mGnssNavigationMessageListeners,
this::removeGnssNavigationMessageListener);
@@ -641,7 +610,7 @@ public class GnssManagerService {
return;
}
- int userId = UserHandle.getUserId(gnssBatchingDeathCallback.getCallerIdentity().mUid);
+ int userId = gnssBatchingDeathCallback.getCallerIdentity().userId;
if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER, userId)) {
Log.w(TAG, "reportLocationBatch() called without user permission");
return;
@@ -655,27 +624,19 @@ public class GnssManagerService {
}
private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
- if (callerIdentity.mUid == Process.SYSTEM_UID) {
+ if (callerIdentity.uid == Process.SYSTEM_UID) {
return true;
}
if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
- callerIdentity.mPackageName)) {
+ callerIdentity.packageName)) {
return true;
}
synchronized (this) {
Preconditions.checkState(mLocationManagerInternal != null);
}
- return mLocationManagerInternal.isProviderPackage(callerIdentity.mPackageName);
- }
-
- private boolean checkLocationAppOp(String packageName) {
- synchronized (this) {
- Preconditions.checkState(mAppOpsManager != null);
- }
- return mAppOpsManager.checkOp(OP_FINE_LOCATION, Binder.getCallingUid(), packageName)
- == AppOpsManager.MODE_ALLOWED;
+ return mLocationManagerInternal.isProviderPackage(callerIdentity.packageName);
}
/**
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 76c3ad02e7e9..b42670149ab4 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -117,7 +117,7 @@ public abstract class GnssMeasurementsProvider
foreach((IGnssMeasurementsListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
logPermissionDisabledEventNotReported(
- TAG, callerIdentity.mPackageName, "GNSS measurements");
+ TAG, callerIdentity.packageName, "GNSS measurements");
return;
}
listener.onGnssMeasurementsReceived(event);
diff --git a/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
index d2ecdeebd9d0..3417e6e7805d 100644
--- a/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
@@ -79,7 +79,7 @@ public abstract class GnssStatusListenerHelper extends
final float[] basebandCn0s) {
foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
- logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName,
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.packageName,
"GNSS status");
return;
}
@@ -91,7 +91,7 @@ public abstract class GnssStatusListenerHelper extends
public void onNmeaReceived(final long timestamp, final String nmea) {
foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
- logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName, "NMEA");
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.packageName, "NMEA");
return;
}
listener.onNmeaReceived(timestamp, nmea);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
new file mode 100644
index 000000000000..7fc10b14209b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_COARSE_LOCATION;
+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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AppOpsHelperTest {
+
+ private static final long TIMEOUT_MS = 5000;
+
+ @Mock private Context mContext;
+ @Mock private AppOpsManager mAppOps;
+
+ private List<AppOpsManager.OnOpChangedInternalListener> mListeners = new ArrayList<>();
+
+ private AppOpsHelper mHelper;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+
+ doReturn(mAppOps).when(mContext).getSystemService(AppOpsManager.class);
+ doAnswer(invocation -> mListeners.add(invocation.getArgument(3))).when(mAppOps)
+ .startWatchingMode(
+ eq(AppOpsManager.OP_COARSE_LOCATION),
+ isNull(),
+ eq(AppOpsManager.WATCH_FOREGROUND_CHANGES),
+ any(AppOpsManager.OnOpChangedInternalListener.class));
+
+ mHelper = new AppOpsHelper(mContext);
+ mHelper.onSystemReady();
+ }
+
+ private void sendAppOp(String packageName) {
+ for (AppOpsManager.OnOpChangedInternalListener listener : mListeners) {
+ listener.onOpChanged(AppOpsManager.OP_COARSE_LOCATION, packageName);
+ }
+ }
+
+ @Test
+ public void testListener() {
+ AppOpsHelper.LocationAppOpListener listener = mock(
+ AppOpsHelper.LocationAppOpListener.class);
+ mHelper.addListener(listener);
+
+ sendAppOp("mypackage1");
+ verify(listener, timeout(TIMEOUT_MS)).onAppOpsChanged("mypackage1");
+
+ sendAppOp("mypackage2");
+ verify(listener, timeout(TIMEOUT_MS)).onAppOpsChanged("mypackage2");
+ }
+
+ @Test
+ public void testCheckLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).checkOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).checkOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isFalse();
+
+ identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_COARSE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).checkOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).checkOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isFalse();
+ }
+
+ @Test
+ public void testNoteLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isFalse();
+
+
+ identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_COARSE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isFalse();
+ }
+
+ @Test
+ public void testStartLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_LOCATION), eq(1000), eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startLocationMonitoring(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_LOCATION), eq(1000), eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startLocationMonitoring(identity)).isFalse();
+ }
+
+ @Test
+ public void testStartHighPowerLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_HIGH_POWER_LOCATION), eq(1000),
+ eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startHighPowerLocationMonitoring(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_HIGH_POWER_LOCATION), eq(1000),
+ eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startHighPowerLocationMonitoring(identity)).isFalse();
+ }
+
+ @Test
+ public void testStopLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ mHelper.stopLocationMonitoring(identity);
+ verify(mAppOps).finishOp(OP_MONITOR_LOCATION, 1000, "mypackage", "myfeature");
+ }
+
+ @Test
+ public void testStopHighPowerLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ mHelper.stopHighPowerLocationMonitoring(identity);
+ verify(mAppOps).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, 1000, "mypackage", "myfeature");
+ }
+
+ @Test
+ public void testNoteMockLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOp(eq(OP_MOCK_LOCATION), eq(1000), eq("mypackage"), eq("myfeature"),
+ nullable(String.class));
+ assertThat(mHelper.noteMockLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOp(eq(OP_MOCK_LOCATION), eq(1000), eq("mypackage"), eq("myfeature"),
+ nullable(String.class));
+ assertThat(mHelper.noteMockLocationAccess(identity)).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index be2a5c529181..36ab1b3ef1ac 100644
--- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -61,11 +61,12 @@ 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.LocationUsageLogger;
+import com.android.server.location.SettingsHelper;
import com.android.server.location.gnss.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
import com.android.server.location.gnss.GnssMeasurementsProvider.GnssMeasurementProviderNative;
import com.android.server.location.gnss.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative;
-import com.android.server.location.LocationUsageLogger;
-import com.android.server.location.SettingsHelper;
import org.junit.After;
import org.junit.Before;
@@ -77,7 +78,7 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -103,7 +104,8 @@ public class GnssManagerServiceTest {
private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider;
private GnssAntennaInfoProvider mTestGnssAntennaInfoProvider;
- // Managers and services
+ @Mock
+ private PackageManager mPackageManager;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
@@ -131,6 +133,9 @@ public class GnssManagerServiceTest {
Context.APP_OPS_SERVICE);
when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(
mAppOpsManager);
+ when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
+ new String[]{"com.android.server"});
enableLocationPermissions();
when(mAppForegroundHelper.isAppForeground(anyInt())).thenReturn(true);
@@ -179,8 +184,11 @@ public class GnssManagerServiceTest {
when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true);
when(mMockGnssBatchingProvider.stop()).thenReturn(true);
+ // Managers and services
+ AppOpsHelper appOpsHelper = new AppOpsHelper(mMockContext);
+
// Create GnssManagerService
- mGnssManagerService = new GnssManagerService(mMockContext, mSettingsHelper,
+ mGnssManagerService = new GnssManagerService(mMockContext, appOpsHelper, mSettingsHelper,
mAppForegroundHelper, new LocationUsageLogger(),
mMockGnssLocationProvider);
mGnssManagerService.onSystemReady();
@@ -232,7 +240,7 @@ public class GnssManagerServiceTest {
new GnssSingleSatCorrection.Builder().build();
return
new GnssMeasurementCorrections.Builder().setSingleSatelliteCorrectionList(
- Arrays.asList(gnssSingleSatCorrection)).build();
+ Collections.singletonList(gnssSingleSatCorrection)).build();
}
private static List<GnssAntennaInfo> createDummyGnssAntennaInfos() {
@@ -262,7 +270,7 @@ public class GnssManagerServiceTest {
signalGainCorrectionsDbi,
signalGainCorrectionsUncertaintyDbi);
- List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList();
+ List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList<>();
gnssAntennaInfos.add(new GnssAntennaInfo.Builder()
.setCarrierFrequencyMHz(carrierFrequencyMHz)
.setPhaseCenterOffset(phaseCenterOffset)
@@ -284,7 +292,7 @@ public class GnssManagerServiceTest {
PackageManager.PERMISSION_GRANTED);
// AppOpsManager will return true if OP_FINE_LOCATION is checked
- when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer(
+ when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString())).thenAnswer(
(InvocationOnMock invocation) -> {
int code = (int) (invocation.getArguments()[0]);
if (code == AppOpsManager.OP_FINE_LOCATION) {
@@ -303,7 +311,7 @@ public class GnssManagerServiceTest {
Mockito.doThrow(new SecurityException()).when(
mMockContext).checkPermission(anyString(), anyInt(), anyInt());
- when(mAppOpsManager.checkOp(anyInt(), anyInt(),
+ when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(),
anyString())).thenReturn(AppOpsManager.MODE_ERRORED);
when(mLocationManagerInternal.isProviderEnabledForUser(eq(GPS_PROVIDER), anyInt()))
@@ -390,8 +398,7 @@ public class GnssManagerServiceTest {
when(mMockGnssCapabilitiesProvider.getGnssCapabilities()).thenReturn(mGnssCapabilities);
enableLocationPermissions();
- assertThat(mGnssManagerService.getGnssCapabilities("com.android.server")).isEqualTo(
- mGnssCapabilities);
+ assertThat(mGnssManagerService.getGnssCapabilities()).isEqualTo(mGnssCapabilities);
}
@Test
@@ -421,7 +428,7 @@ public class GnssManagerServiceTest {
assertThrows(SecurityException.class,
() -> mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull,
- "com.android.server"));
+ "com.android.server", null));
verify(mMockGnssBatchingProvider, times(0)).start(periodNanos, wakeOnFifoFull);
}
@@ -433,7 +440,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
assertThat(mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull,
- "com.android.server"))
+ "com.android.server", null))
.isEqualTo(
true);
verify(mMockGnssBatchingProvider, times(1)).start(100L, true);
@@ -447,8 +454,7 @@ public class GnssManagerServiceTest {
disableLocationPermissions();
assertThrows(SecurityException.class, () -> mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback, "com.android.server", "abcd123",
- "TestBatchedLocationCallback"));
+ mockBatchedLocationCallback, "com.android.server", null));
mGnssManagerService.onReportLocation(mockLocationList);
@@ -463,8 +469,8 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback, "com.android.server", null))
+ .isEqualTo(true);
mGnssManagerService.onReportLocation(mockLocationList);
@@ -480,11 +486,11 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback1, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback1, "com.android.server", null))
+ .isEqualTo(true);
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback2, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback2, "com.android.server", null))
+ .isEqualTo(true);
mGnssManagerService.onReportLocation(mockLocationList);
@@ -517,7 +523,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback,
- "com.android.server", "abcd123", "TestBatchedLocationCallback");
+ "com.android.server", null);
disableLocationPermissions();
@@ -538,7 +544,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback,
- "com.android.server", "abcd123", "TestBatchedLocationCallback");
+ "com.android.server", null);
mGnssManagerService.removeGnssBatchingCallback();
@@ -623,7 +629,7 @@ public class GnssManagerServiceTest {
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssMeasurementsListener(
new GnssRequest.Builder().build(), mockGnssMeasurementsListener,
- "com.android.server", "abcd123", "TestGnssMeasurementsListener"));
+ "com.android.server", null));
mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
verify(mockGnssMeasurementsListener, times(0)).onGnssMeasurementsReceived(
@@ -642,8 +648,7 @@ public class GnssManagerServiceTest {
assertThat(mGnssManagerService.addGnssMeasurementsListener(
new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener")).isEqualTo(true);
+ "com.android.server", null)).isEqualTo(true);
mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
verify(mockGnssMeasurementsListener, times(1)).onGnssMeasurementsReceived(
@@ -690,8 +695,7 @@ public class GnssManagerServiceTest {
mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -714,8 +718,7 @@ public class GnssManagerServiceTest {
mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -738,7 +741,7 @@ public class GnssManagerServiceTest {
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener"));
+ "com.android.server", null));
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
verify(mockGnssAntennaInfoListener, times(0))
@@ -754,7 +757,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssAntennaInfoListener(mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener")).isEqualTo(true);
+ "com.android.server", null)).isEqualTo(true);
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
verify(mockGnssAntennaInfoListener, times(1))
@@ -771,7 +774,7 @@ public class GnssManagerServiceTest {
mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -793,7 +796,7 @@ public class GnssManagerServiceTest {
mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener");
+ "com.android.server", null);
mGnssManagerService.removeGnssAntennaInfoListener(
mockGnssAntennaInfoListener);
@@ -813,8 +816,7 @@ public class GnssManagerServiceTest {
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener"));
+ mockGnssNavigationMessageListener, "com.android.server", null));
mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage);
@@ -831,8 +833,8 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener")).isEqualTo(true);
+ mockGnssNavigationMessageListener, "com.android.server", null))
+ .isEqualTo(true);
mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage);
@@ -849,8 +851,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener");
+ mockGnssNavigationMessageListener, "com.android.server", null);
disableLocationPermissions();
@@ -872,8 +873,7 @@ public class GnssManagerServiceTest {
enableLocationPermissions();
mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener");
+ mockGnssNavigationMessageListener, "com.android.server", null);
mGnssManagerService.removeGnssNavigationMessageListener(
mockGnssNavigationMessageListener);