summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anil Admal <aadmal@google.com> 2019-01-30 16:55:05 -0800
committer Anil Admal <aadmal@google.com> 2019-01-31 18:57:02 -0800
commit08b96123048b18fcf421fdae07c1184fa4434c6f (patch)
tree9e61100dc38b38709c87df19a092cb6ec9fe6320
parente2841c523b46419c83b95804880814db2fd43124 (diff)
Do not report GNSS requests from location providers to AppOps
Bug: 123529857 Test: Verified with a real device that GNSS status requests from GmsCore (location providers) is not reported to AppOps. Change-Id: I67bd99c3bc7f3e8e725e6c35f64d9e9fb99f6e5c
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java146
-rw-r--r--services/core/java/com/android/server/location/CallerIdentity.java32
-rw-r--r--services/core/java/com/android/server/location/GnssMeasurementsProvider.java33
-rw-r--r--services/core/java/com/android/server/location/GnssNavigationMessageProvider.java4
-rw-r--r--services/core/java/com/android/server/location/GnssStatusListenerHelper.java19
-rw-r--r--services/core/java/com/android/server/location/LocationPermissionUtil.java62
-rw-r--r--services/core/java/com/android/server/location/RemoteListenerHelper.java30
7 files changed, 205 insertions, 121 deletions
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 7eb8e938628e..5a0d528557b2 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -92,6 +92,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.ActivityRecognitionProxy;
+import com.android.server.location.CallerIdentity;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
@@ -223,10 +224,10 @@ public class LocationManagerService extends ILocationManager.Stub {
private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
@GuardedBy("mLock")
- private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
+ private final ArrayMap<IBinder, CallerIdentity> mGnssMeasurementsListeners = new ArrayMap<>();
@GuardedBy("mLock")
- private final ArrayMap<IBinder, Identity>
+ private final ArrayMap<IBinder, CallerIdentity>
mGnssNavigationMessageListeners = new ArrayMap<>();
// current active user on the device - other users are denied location data
@@ -455,7 +456,7 @@ public class LocationManagerService extends ILocationManager.Stub {
ArrayList<Receiver> deadReceivers = null;
for (Receiver receiver : mReceivers.values()) {
- if (receiver.mIdentity.mPackageName.equals(packageName)) {
+ if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<>();
}
@@ -478,7 +479,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.mIdentity.mUid == uid
+ if (record.mReceiver.mCallerIdentity.mUid == uid
&& record.mIsForegroundUid != foreground) {
if (D) {
Log.d(TAG, "request from uid " + uid + " is now "
@@ -486,7 +487,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
record.updateForeground(foreground);
- if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
affectedProviders.add(provider);
}
}
@@ -496,8 +497,8 @@ public class LocationManagerService extends ILocationManager.Stub {
applyRequirementsLocked(provider);
}
- for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
- Identity callerIdentity = entry.getValue();
+ for (Entry<IBinder, CallerIdentity> entry : mGnssMeasurementsListeners.entrySet()) {
+ CallerIdentity callerIdentity = entry.getValue();
if (callerIdentity.mUid == uid) {
if (D) {
Log.d(TAG, "gnss measurements listener from uid " + uid
@@ -506,7 +507,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (foreground || isThrottlingExemptLocked(entry.getValue())) {
mGnssMeasurementsProvider.addListener(
IGnssMeasurementsListener.Stub.asInterface(entry.getKey()),
- callerIdentity.mUid, callerIdentity.mPackageName);
+ callerIdentity);
} else {
mGnssMeasurementsProvider.removeListener(
IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
@@ -514,8 +515,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
- Identity callerIdentity = entry.getValue();
+ for (Entry<IBinder, CallerIdentity> entry : mGnssNavigationMessageListeners.entrySet()) {
+ CallerIdentity callerIdentity = entry.getValue();
if (callerIdentity.mUid == uid) {
if (D) {
Log.d(TAG, "gnss navigation message listener from uid "
@@ -525,7 +526,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (foreground || isThrottlingExemptLocked(entry.getValue())) {
mGnssNavigationMessageProvider.addListener(
IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()),
- callerIdentity.mUid, callerIdentity.mPackageName);
+ callerIdentity);
} else {
mGnssNavigationMessageProvider.removeListener(
IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
@@ -836,18 +837,6 @@ public class LocationManagerService extends ILocationManager.Stub {
onProviderAllowedChangedLocked(false);
}
- private static final class Identity {
- final int mUid;
- final int mPid;
- final String mPackageName;
-
- Identity(int uid, int pid, String packageName) {
- mUid = uid;
- mPid = pid;
- mPackageName = packageName;
- }
- }
-
private class LocationProvider implements AbstractLocationProvider.LocationProviderManager {
private final String mName;
@@ -1235,7 +1224,7 @@ public class LocationManagerService extends ILocationManager.Stub {
*/
private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
- final Identity mIdentity;
+ final CallerIdentity mCallerIdentity;
private final int mAllowedResolutionLevel; // resolution level allowed to receiver
private final ILocationListener mListener;
@@ -1263,7 +1252,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mKey = intent;
}
mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
- mIdentity = new Identity(uid, pid, packageName);
+ mCallerIdentity = new CallerIdentity(uid, pid, packageName);
if (workSource != null && workSource.isEmpty()) {
workSource = null;
}
@@ -1275,7 +1264,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(mIdentity.mUid, mIdentity.mPackageName);
+ workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
}
mWakeLock.setWorkSource(workSource);
@@ -1378,14 +1367,14 @@ public class LocationManagerService extends ILocationManager.Stub {
int op) {
if (!currentlyMonitoring) {
if (allowMonitoring) {
- return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
- == AppOpsManager.MODE_ALLOWED;
+ return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
+ mCallerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
}
} else {
if (!allowMonitoring
- || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
- != AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
+ || mAppOps.noteOpNoThrow(op, mCallerIdentity.mUid,
+ mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
+ mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
return false;
}
}
@@ -1723,7 +1712,6 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
-
@Override
public void flushGnssBatch(String packageName) {
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
@@ -2015,7 +2003,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (records != null) {
for (UpdateRecord record : records) {
if (!isCurrentProfileLocked(
- UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
continue;
}
@@ -2074,13 +2062,13 @@ public class LocationManagerService extends ILocationManager.Stub {
providerRequest.lowPowerMode = true;
for (UpdateRecord record : records) {
if (!isCurrentProfileLocked(
- UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
continue;
}
if (!checkLocationAccess(
- record.mReceiver.mIdentity.mPid,
- record.mReceiver.mIdentity.mUid,
- record.mReceiver.mIdentity.mPackageName,
+ record.mReceiver.mCallerIdentity.mPid,
+ record.mReceiver.mCallerIdentity.mUid,
+ record.mReceiver.mCallerIdentity.mPackageName,
record.mReceiver.mAllowedResolutionLevel)) {
continue;
}
@@ -2091,7 +2079,7 @@ public class LocationManagerService extends ILocationManager.Stub {
LocationRequest locationRequest = record.mRealRequest;
long interval = locationRequest.getInterval();
- if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
if (!record.mIsForegroundUid) {
interval = Math.max(interval, backgroundThrottleInterval);
}
@@ -2121,7 +2109,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
for (UpdateRecord record : records) {
if (isCurrentProfileLocked(
- UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
LocationRequest locationRequest = record.mRequest;
// Don't assign battery blame for update records whose
@@ -2138,8 +2126,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.
worksource.add(
- record.mReceiver.mIdentity.mUid,
- record.mReceiver.mIdentity.mPackageName);
+ record.mReceiver.mCallerIdentity.mUid,
+ record.mReceiver.mCallerIdentity.mPackageName);
}
}
}
@@ -2176,17 +2164,17 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private boolean isThrottlingExemptLocked(Identity identity) {
- if (identity.mUid == Process.SYSTEM_UID) {
+ private boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
+ if (callerIdentity.mUid == Process.SYSTEM_UID) {
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
+ if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
return true;
}
for (LocationProvider provider : mProviders) {
- if (identity.mPackageName.equals(provider.getPackageLocked())) {
+ if (callerIdentity.mPackageName.equals(provider.getPackageLocked())) {
return true;
}
}
@@ -2200,12 +2188,13 @@ public class LocationManagerService extends ILocationManager.Stub {
return false;
}
- if (mIgnoreSettingsPackageWhitelist.contains(record.mReceiver.mIdentity.mPackageName)) {
+ if (mIgnoreSettingsPackageWhitelist.contains(
+ record.mReceiver.mCallerIdentity.mPackageName)) {
return true;
}
for (LocationProvider provider : mProviders) {
- if (record.mReceiver.mIdentity.mPackageName.equals(provider.getPackageLocked())) {
+ if (record.mReceiver.mCallerIdentity.mPackageName.equals(provider.getPackageLocked())) {
return true;
}
}
@@ -2231,7 +2220,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mRequest = request;
mReceiver = receiver;
mIsForegroundUid = isImportanceForeground(
- mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
+ mActivityManager.getPackageImportance(mReceiver.mCallerIdentity.mPackageName));
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null) {
@@ -2244,7 +2233,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// Update statistics for historical location requests by package/provider
mRequestStatistics.startRequesting(
- mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
+ mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
mIsForegroundUid);
}
@@ -2254,14 +2243,14 @@ public class LocationManagerService extends ILocationManager.Stub {
private void updateForeground(boolean isForeground) {
mIsForegroundUid = isForeground;
mRequestStatistics.updateForeground(
- mReceiver.mIdentity.mPackageName, mProvider, isForeground);
+ mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
}
/**
* Method to be called when a record will no longer be used.
*/
private void disposeLocked(boolean removeReceiver) {
- mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
+ mRequestStatistics.stopRequesting(mReceiver.mCallerIdentity.mPackageName, mProvider);
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -2283,8 +2272,8 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public String toString() {
- return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
- + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
+ return "UpdateRecord[" + mProvider + " " + mReceiver.mCallerIdentity.mPackageName
+ + "(" + mReceiver.mCallerIdentity.mUid + (mIsForegroundUid ? " foreground"
: " background")
+ ")" + " " + mRealRequest + " "
+ mReceiver.mWorkSource + "]";
@@ -2459,7 +2448,7 @@ public class LocationManagerService extends ILocationManager.Stub {
Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+ " " + name + " " + request + " from " + packageName + "(" + uid + " "
+ (record.mIsForegroundUid ? "foreground" : "background")
- + (isThrottlingExemptLocked(receiver.mIdentity)
+ + (isThrottlingExemptLocked(receiver.mCallerIdentity)
? " [whitelisted]" : "") + ")");
}
@@ -2735,7 +2724,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// TODO(b/120449926): The GNSS status listeners should be handled similar to the GNSS
// measurements listeners.
- return mGnssStatusProvider.addListener(callback, Binder.getCallingUid(), packageName);
+ return mGnssStatusProvider.addListener(callback, new CallerIdentity(Binder.getCallingUid(),
+ Binder.getCallingPid(), packageName));
}
@Override
@@ -2751,8 +2741,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
synchronized (mLock) {
- Identity callerIdentity
- = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
+ Binder.getCallingPid(), packageName);
// TODO(b/120481270): Register for client death notification and update map.
mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
long identity = Binder.clearCallingIdentity();
@@ -2760,8 +2750,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (isThrottlingExemptLocked(callerIdentity)
|| isImportanceForeground(
mActivityManager.getPackageImportance(packageName))) {
- return mGnssMeasurementsProvider.addListener(listener,
- callerIdentity.mUid, callerIdentity.mPackageName);
+ return mGnssMeasurementsProvider.addListener(listener, callerIdentity);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -2816,8 +2805,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
synchronized (mLock) {
- Identity callerIdentity
- = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
+ Binder.getCallingPid(), packageName);
// TODO(b/120481270): Register for client death notification and update map.
mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
@@ -2826,8 +2815,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (isThrottlingExemptLocked(callerIdentity)
|| isImportanceForeground(
mActivityManager.getPackageImportance(packageName))) {
- return mGnssNavigationMessageProvider.addListener(listener,
- callerIdentity.mUid, callerIdentity.mPackageName);
+ return mGnssNavigationMessageProvider.addListener(listener, callerIdentity);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3110,33 +3098,33 @@ public class LocationManagerService extends ILocationManager.Stub {
continue;
}
- int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
+ int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
if (!isCurrentProfileLocked(receiverUserId)
- && !isLocationProviderLocked(receiver.mIdentity.mUid)) {
+ && !isLocationProviderLocked(receiver.mCallerIdentity.mUid)) {
if (D) {
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
" (current user: " + mCurrentUserId + ", app: " +
- receiver.mIdentity.mPackageName + ")");
+ receiver.mCallerIdentity.mPackageName + ")");
}
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
+ if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
if (D) {
Log.d(TAG, "skipping loc update for blacklisted app: " +
- receiver.mIdentity.mPackageName);
+ receiver.mCallerIdentity.mPackageName);
}
continue;
}
if (!reportLocationAccessNoThrow(
- receiver.mIdentity.mPid,
- receiver.mIdentity.mUid,
- receiver.mIdentity.mPackageName,
+ receiver.mCallerIdentity.mPid,
+ receiver.mCallerIdentity.mUid,
+ receiver.mCallerIdentity.mPackageName,
receiver.mAllowedResolutionLevel)) {
if (D) {
Log.d(TAG, "skipping loc update for no op app: " +
- receiver.mIdentity.mPackageName);
+ receiver.mCallerIdentity.mPackageName);
}
continue;
}
@@ -3425,14 +3413,16 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
pw.println(" Active GnssMeasurement Listeners:");
- for (Identity identity : mGnssMeasurementsListeners.values()) {
- pw.println(" " + identity.mPid + " " + identity.mUid + " "
- + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+ for (CallerIdentity callerIdentity : mGnssMeasurementsListeners.values()) {
+ pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
+ + callerIdentity.mPackageName + ": "
+ + isThrottlingExemptLocked(callerIdentity));
}
pw.println(" Active GnssNavigationMessage Listeners:");
- for (Identity identity : mGnssNavigationMessageListeners.values()) {
- pw.println(" " + identity.mPid + " " + identity.mUid + " "
- + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+ for (CallerIdentity callerIdentity : mGnssNavigationMessageListeners.values()) {
+ pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
+ + callerIdentity.mPackageName + ": "
+ + isThrottlingExemptLocked(callerIdentity));
}
pw.println(" Overlay Provider Packages:");
for (LocationProvider provider : mProviders) {
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
new file mode 100644
index 000000000000..da31d0b8e9a3
--- /dev/null
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+/**
+ * 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 CallerIdentity(int uid, int pid, String packageName) {
+ mUid = uid;
+ mPid = pid;
+ mPackageName = packageName;
+ }
+}
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 77dee8241bea..1fc7192916df 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -95,15 +95,11 @@ public abstract class GnssMeasurementsProvider
*/
public void injectGnssMeasurementCorrections(
GnssMeasurementCorrections measurementCorrections) {
- mHandler.post(
- new Runnable() {
- @Override
- public void run() {
- if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) {
- Log.e(TAG, "Failure in injecting GNSS corrections.");
- }
- }
- });
+ mHandler.post(() -> {
+ if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) {
+ Log.e(TAG, "Failure in injecting GNSS corrections.");
+ }
+ });
}
@Override
@@ -115,15 +111,14 @@ public abstract class GnssMeasurementsProvider
}
public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
- foreach(
- (IGnssMeasurementsListener listener, int uid, String packageName) -> {
- if (!hasPermission(uid, packageName)) {
- logPermissionDisabledEventNotReported(
- TAG, packageName, "GNSS measurements");
- return;
- }
- listener.onGnssMeasurementsReceived(event);
- });
+ foreach((IGnssMeasurementsListener listener, CallerIdentity callerIdentity) -> {
+ if (!hasPermission(mContext, callerIdentity)) {
+ logPermissionDisabledEventNotReported(
+ TAG, callerIdentity.mPackageName, "GNSS measurements");
+ return;
+ }
+ listener.onGnssMeasurementsReceived(event);
+ });
}
/** Updates the framework about the capabilities of the GNSS chipset */
@@ -182,7 +177,7 @@ public abstract class GnssMeasurementsProvider
@Override
public void execute(IGnssMeasurementsListener listener,
- int uid, String packageName) throws RemoteException {
+ CallerIdentity callerIdentity) throws RemoteException {
listener.onStatusChanged(mStatus);
}
}
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 679919f8fc67..80a3f9bd2aba 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -86,7 +86,7 @@ public abstract class GnssNavigationMessageProvider
}
public void onNavigationMessageAvailable(final GnssNavigationMessage event) {
- foreach((IGnssNavigationMessageListener listener, int uid, String packageName) -> {
+ foreach((IGnssNavigationMessageListener listener, CallerIdentity callerIdentity) -> {
listener.onGnssNavigationMessageReceived(event);
}
);
@@ -136,7 +136,7 @@ public abstract class GnssNavigationMessageProvider
@Override
public void execute(IGnssNavigationMessageListener listener,
- int uid, String packageName) throws RemoteException {
+ CallerIdentity callerIdentity) throws RemoteException {
listener.onStatusChanged(mStatus);
}
}
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 454dbddc406a..d67d0c5fe612 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -48,18 +48,18 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns
public void onStatusChanged(boolean isNavigating) {
if (isNavigating) {
- foreach((IGnssStatusListener listener, int uid, String packageName) -> {
+ foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
listener.onGnssStarted();
});
} else {
- foreach((IGnssStatusListener listener, int uid, String packageName) -> {
+ foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
listener.onGnssStopped();
});
}
}
public void onFirstFix(final int timeToFirstFix) {
- foreach((IGnssStatusListener listener, int uid, String packageName) -> {
+ foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
listener.onFirstFix(timeToFirstFix);
}
);
@@ -72,9 +72,10 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns
final float[] elevations,
final float[] azimuths,
final float[] carrierFreqs) {
- foreach((IGnssStatusListener listener, int uid, String packageName) -> {
- if (!hasPermission(uid, packageName)) {
- logPermissionDisabledEventNotReported(TAG, packageName, "GNSS status");
+ foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
+ if (!hasPermission(mContext, callerIdentity)) {
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName,
+ "GNSS status");
return;
}
listener.onSvStatusChanged(svCount, prnWithFlags, cn0s, elevations, azimuths,
@@ -83,9 +84,9 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns
}
public void onNmeaReceived(final long timestamp, final String nmea) {
- foreach((IGnssStatusListener listener, int uid, String packageName) -> {
- if (!hasPermission(uid, packageName)) {
- logPermissionDisabledEventNotReported(TAG, packageName, "NMEA");
+ foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
+ if (!hasPermission(mContext, callerIdentity)) {
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName, "NMEA");
return;
}
listener.onNmeaReceived(timestamp, nmea);
diff --git a/services/core/java/com/android/server/location/LocationPermissionUtil.java b/services/core/java/com/android/server/location/LocationPermissionUtil.java
new file mode 100644
index 000000000000..4465f31cb45b
--- /dev/null
+++ b/services/core/java/com/android/server/location/LocationPermissionUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Encapsulates utility functions and classes related to location permission checking.
+ */
+public final class LocationPermissionUtil {
+ /**
+ * Returns true if the calling process identified by {@code callerIdentity} is enabled to
+ * report location to AppOps service before providing device location identifiable information
+ * to its clients. Packages with these permissions must report any reporting of location
+ * information to apps, via AppOps.
+ *
+ * <p>The calling package represented by {@code callerIdentity} is considered a part of the
+ * extended Location Manager Service if it has all of the permissions below.
+ * <ul>
+ * <li>{@link android.Manifest.permission#LOCATION_HARDWARE}
+ * <li>{@link android.Manifest.permission#UPDATE_APP_OPS_STATS}
+ * </ul>
+ *
+ * <p>Any package with these permissions, that passes along location information from Android
+ * framework to apps, must report to AppOps, similarly to Location Manager Service - i.e.
+ * whenever it reports device location or location identifiable information such as
+ * GNSS status, GNSS measurements, etc. to its clients.
+ */
+ public static boolean doesCallerReportToAppOps(Context context, CallerIdentity callerIdentity) {
+ return hasPermissionLocationHardware(context, callerIdentity)
+ && hasPermissionUpdateAppOpsStats(context, callerIdentity);
+ }
+
+ private static boolean hasPermissionLocationHardware(Context context,
+ CallerIdentity callerIdentity) {
+ return context.checkPermission(android.Manifest.permission.LOCATION_HARDWARE,
+ callerIdentity.mPid, callerIdentity.mUid) == 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;
+ }
+
+ 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 e69b2ec28ebc..f03c99b0272e 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -71,10 +71,10 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
return mIsRegistered;
}
- public boolean addListener(@NonNull TListener listener, int uid, String packageName) {
+ public boolean addListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
IBinder binder = listener.asBinder();
- LinkedListener deathListener = new LinkedListener(listener, uid, packageName);
+ LinkedListener deathListener = new LinkedListener(listener, callerIdentity);
synchronized (mListenerMap) {
if (mListenerMap.containsKey(binder)) {
// listener already added
@@ -137,7 +137,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
protected abstract ListenerOperation<TListener> getHandlerOperation(int result);
protected interface ListenerOperation<TListener extends IInterface> {
- void execute(TListener listener, int uid, String packageName) throws RemoteException;
+ void execute(TListener listener, CallerIdentity callerIdentity) throws RemoteException;
}
protected void foreach(ListenerOperation<TListener> operation) {
@@ -177,9 +177,16 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
}
}
- protected boolean hasPermission(int uid, String packageName) {
- return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, uid, packageName)
- == AppOpsManager.MODE_ALLOWED;
+ protected boolean hasPermission(Context context, CallerIdentity callerIdentity) {
+ 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.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
+ callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
}
protected void logPermissionDisabledEventNotReported(String tag, String packageName,
@@ -254,13 +261,11 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
private class LinkedListener implements IBinder.DeathRecipient {
private final TListener mListener;
- private final int mUid;
- private final String mPackageName;
+ private final CallerIdentity mCallerIdentity;
- LinkedListener(@NonNull TListener listener, int uid, String packageName) {
+ LinkedListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
mListener = listener;
- mUid = uid;
- mPackageName = packageName;
+ mCallerIdentity = callerIdentity;
}
@Override
@@ -282,8 +287,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
@Override
public void run() {
try {
- mOperation.execute(mLinkedListener.mListener, mLinkedListener.mUid,
- mLinkedListener.mPackageName);
+ mOperation.execute(mLinkedListener.mListener, mLinkedListener.mCallerIdentity);
} catch (RemoteException e) {
Log.v(mTag, "Error in monitored listener.", e);
}