diff options
| author | 2019-01-30 16:55:05 -0800 | |
|---|---|---|
| committer | 2019-01-31 18:57:02 -0800 | |
| commit | 08b96123048b18fcf421fdae07c1184fa4434c6f (patch) | |
| tree | 9e61100dc38b38709c87df19a092cb6ec9fe6320 | |
| parent | e2841c523b46419c83b95804880814db2fd43124 (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
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); } |