diff options
author | Soonil Nagarkar <sooniln@google.com> | 2019-01-31 14:36:56 -0800 |
---|---|---|
committer | Soonil Nagarkar <sooniln@google.com> | 2019-02-04 10:58:24 -0800 |
commit | 0d77ea68937f382c36c3c122ebe504d4db2ca83f (patch) | |
tree | 8acb9d4b893bc3c3f47c99338a557427e6f02c81 | |
parent | affa55b49baebce7ae1b8bb893e015379df83a49 (diff) |
Change provider packages API to test all providers
This will replace the LocationManager.getNetworkProviderPackage() API
with LocationManager.isProviderPackage(). The network provider should
not be considered special.
In addition, providers now have the ability to specify additional
packages that may make location requests on their behalf, so that those
packages can be considered location providers as well.
Bug: 117177078
Test: manually
Change-Id: I204b56e7bb40874ac3347988474fb8afa787feb8
12 files changed, 162 insertions, 60 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index f9403ffc3c79..0d8b729354b9 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3322,6 +3322,7 @@ package android.location { method public boolean isLocationControllerExtraPackageEnabled(); method public boolean isLocationEnabledForUser(android.os.UserHandle); method public boolean isProviderEnabledForUser(String, android.os.UserHandle); + method public boolean isProviderPackage(String); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler); method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index e795b8119760..e91012fe0afe 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -85,12 +85,13 @@ interface ILocationManager boolean stopGnssBatch(); boolean injectLocation(in Location location); - // --- deprecated --- List<String> getAllProviders(); List<String> getProviders(in Criteria criteria, boolean enabledOnly); String getBestProvider(in Criteria criteria, boolean enabledOnly); ProviderProperties getProviderProperties(String provider); String getNetworkProviderPackage(); + boolean isProviderPackage(String packageName); + void setLocationControllerExtraPackage(String packageName); String getLocationControllerExtraPackage(); void setLocationControllerExtraPackageEnabled(boolean enabled); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 63b57d166f1f..5aba22f4c6b1 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2425,6 +2425,22 @@ public class LocationManager { } /** + * Returns true if the given package name matches a location provider package, and false + * otherwise. + * + * @hide + */ + @SystemApi + public boolean isProviderPackage(String packageName) { + try { + return mService.isProviderPackage(packageName); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return false; + } + } + + /** * Set the extra location controller package for location services on the device. * * @hide diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl index b1b8f0c7c3f7..79166ae3a9b0 100644 --- a/location/java/com/android/internal/location/ILocationProviderManager.aidl +++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl @@ -26,6 +26,8 @@ import com.android.internal.location.ProviderProperties; */ interface ILocationProviderManager { + void onSetAdditionalProviderPackages(in List<String> packageNames); + void onSetEnabled(boolean enabled); void onSetProperties(in ProviderProperties properties); diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt index c7212183a37e..67d64965ac96 100644 --- a/location/lib/api/current.txt +++ b/location/lib/api/current.txt @@ -19,6 +19,7 @@ package com.android.location.provider { method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle); method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource); method public void reportLocation(android.location.Location); + method public void setAdditionalProviderPackages(java.util.List<java.lang.String>); method public void setEnabled(boolean); method public void setProperties(com.android.location.provider.ProviderPropertiesUnbundled); field public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation"; diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java index 5bcec92c4fba..7cd7207c26a0 100644 --- a/location/lib/java/com/android/location/provider/LocationProviderBase.java +++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java @@ -36,6 +36,8 @@ import com.android.internal.location.ProviderRequest; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; /** * Base class for location providers implemented as unbundled services. @@ -88,6 +90,7 @@ public abstract class LocationProviderBase { @Nullable private volatile ILocationProviderManager mManager; private volatile ProviderProperties mProperties; private volatile boolean mEnabled; + private final ArrayList<String> mAdditionalProviderPackages; public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) { mTag = tag; @@ -99,6 +102,7 @@ public abstract class LocationProviderBase { mManager = null; mProperties = properties.getProviderProperties(); mEnabled = true; + mAdditionalProviderPackages = new ArrayList<>(0); } public IBinder getBinder() { @@ -160,6 +164,29 @@ public abstract class LocationProviderBase { } /** + * Sets a list of additional packages that should be considered as part of this location + * provider for the purposes of generating locations. This should generally only be used when + * another package may issue location requests on behalf of this package in the course of + * providing location. This will inform location services to treat the other packages as + * location providers as well. + */ + public void setAdditionalProviderPackages(List<String> packageNames) { + synchronized (mBinder) { + mAdditionalProviderPackages.clear(); + mAdditionalProviderPackages.addAll(packageNames); + } + + ILocationProviderManager manager = mManager; + if (manager != null) { + try { + manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages); + } catch (RemoteException | RuntimeException e) { + Log.w(mTag, e); + } + } + } + + /** * Returns true if this provider has been set as enabled. This will be true unless explicitly * set otherwise. */ @@ -275,6 +302,9 @@ public abstract class LocationProviderBase { public void setLocationProviderManager(ILocationProviderManager manager) { synchronized (mBinder) { try { + if (!mAdditionalProviderPackages.isEmpty()) { + manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages); + } manager.onSetProperties(mProperties); manager.onSetEnabled(mEnabled); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index a36c7c0e89b0..1165b094f319 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -114,6 +114,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -669,7 +670,7 @@ public class LocationManagerService extends ILocationManager.Stub { // create a passive location provider, which is always enabled LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER); addProviderLocked(passiveProviderManager); - mPassiveProvider = new PassiveProvider(passiveProviderManager); + mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager); passiveProviderManager.attachLocked(mPassiveProvider); if (GnssLocationProvider.isSupported()) { @@ -805,7 +806,7 @@ public class LocationManagerService extends ILocationManager.Stub { Integer.parseInt(fragments[9]) /* accuracy */); LocationProvider testProviderManager = new LocationProvider(name); addProviderLocked(testProviderManager); - new MockProvider(testProviderManager, properties); + new MockProvider(mContext, testProviderManager, properties); } } @@ -895,15 +896,12 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - @Nullable - public String getPackageLocked() { + public List<String> getPackagesLocked() { if (mProvider == null) { - return null; - } else if (mProvider instanceof LocationProviderProxy) { - // safe to not clear binder context since this doesn't call into the actual provider - return ((LocationProviderProxy) mProvider).getConnectedPackageName(); + return Collections.emptyList(); } else { - return mContext.getPackageName(); + // safe to not clear binder context since this doesn't call into the real provider + return mProvider.getProviderPackages(); } } @@ -2172,10 +2170,8 @@ public class LocationManagerService extends ILocationManager.Stub { return true; } - for (LocationProvider provider : mProviders) { - if (callerIdentity.mPackageName.equals(provider.getPackageLocked())) { - return true; - } + if (isProviderPackage(callerIdentity.mPackageName)) { + return true; } return false; @@ -2192,10 +2188,8 @@ public class LocationManagerService extends ILocationManager.Stub { return true; } - for (LocationProvider provider : mProviders) { - if (record.mReceiver.mCallerIdentity.mPackageName.equals(provider.getPackageLocked())) { - return true; - } + if (isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName)) { + return true; } return false; @@ -2571,8 +2565,8 @@ public class LocationManagerService extends ILocationManager.Stub { if (provider == null) return null; // only the current user or location providers may get location this way - if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isLocationProviderLocked( - uid)) { + if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isProviderPackage( + packageName)) { return null; } @@ -2894,7 +2888,25 @@ public class LocationManagerService extends ILocationManager.Stub { if (provider == null) { return null; } - return provider.getPackageLocked(); + List<String> packages = provider.getPackagesLocked(); + if (packages.isEmpty()) { + return null; + } else { + return packages.get(0); + } + } + } + + @Override + public boolean isProviderPackage(String packageName) { + synchronized (mLock) { + for (LocationProvider provider : mProviders) { + if (provider.getPackagesLocked().contains(packageName)) { + return true; + } + } + + return false; } } @@ -2976,28 +2988,6 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private boolean isLocationProviderLocked(int uid) { - if (uid == Process.SYSTEM_UID) { - return true; - } - - String[] packageNames = mPackageManager.getPackagesForUid(uid); - if (packageNames == null) { - return false; - } - for (LocationProvider provider : mProviders) { - String packageName = provider.getPackageLocked(); - if (packageName == null) { - continue; - } - if (ArrayUtils.contains(packageNames, packageName)) { - return true; - } - } - return false; - } - - @GuardedBy("mLock") private static boolean shouldBroadcastSafeLocked( Location loc, Location lastLoc, UpdateRecord record, long now) { // Always broadcast the first update @@ -3099,7 +3089,7 @@ public class LocationManagerService extends ILocationManager.Stub { int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid); if (!isCurrentProfileLocked(receiverUserId) - && !isLocationProviderLocked(receiver.mCallerIdentity.mUid)) { + && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for background user " + receiverUserId + " (current user: " + mCurrentUserId + ", app: " + @@ -3288,7 +3278,8 @@ public class LocationManagerService extends ILocationManager.Stub { MockLocationProvider mockProviderManager = new MockLocationProvider(name); addProviderLocked(mockProviderManager); - mockProviderManager.attachLocked(new MockProvider(mockProviderManager, properties)); + mockProviderManager.attachLocked( + new MockProvider(mContext, mockProviderManager, properties)); } finally { Binder.restoreCallingIdentity(identity); } @@ -3428,7 +3419,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (provider.mProvider instanceof LocationProviderProxy) { pw.println(" " + provider.getName() + ": " + ((LocationProviderProxy) provider.mProvider) - .getConnectedPackageName()); + .getProviderPackages()); } } pw.println(" Historical Records by Provider:"); diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java index b3f101848692..0edd17b1f777 100644 --- a/services/core/java/com/android/server/location/AbstractLocationProvider.java +++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.content.Context; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -26,6 +27,7 @@ import com.android.internal.location.ProviderRequest; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Collections; import java.util.List; /** @@ -65,9 +67,12 @@ public abstract class AbstractLocationProvider { void onReportLocation(List<Location> locations); } + protected final Context mContext; private final LocationProviderManager mLocationProviderManager; - protected AbstractLocationProvider(LocationProviderManager locationProviderManager) { + protected AbstractLocationProvider( + Context context, LocationProviderManager locationProviderManager) { + mContext = context; mLocationProviderManager = locationProviderManager; } @@ -101,6 +106,11 @@ public abstract class AbstractLocationProvider { mLocationProviderManager.onSetProperties(properties); } + /** Returns list of packages currently associated with this provider. */ + public List<String> getProviderPackages() { + return Collections.singletonList(mContext.getPackageName()); + } + /** * Called when the location service delivers a new request for fulfillment to the provider. * Replaces any previous requests completely. diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index ab9f711b4238..b18110e80c2d 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -368,7 +368,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private int mC2KServerPort; private boolean mSuplEsEnabled = false; - private final Context mContext; private final Looper mLooper; private final LocationExtras mLocationExtras = new LocationExtras(); private final GnssStatusListenerHelper mGnssStatusListenerHelper; @@ -562,9 +561,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements public GnssLocationProvider(Context context, LocationProviderManager locationProviderManager, Looper looper) { - super(locationProviderManager); + super(context, locationProviderManager); - mContext = context; mLooper = looper; // Create a wake lock diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 776beb50be62..34c8786b00b3 100644 --- a/services/core/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java @@ -16,8 +16,11 @@ package com.android.server.location; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + import android.annotation.Nullable; import android.content.Context; +import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -39,6 +42,10 @@ import com.android.server.ServiceWatcher; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * Proxy for ILocationProvider implementations. @@ -48,14 +55,21 @@ public class LocationProviderProxy extends AbstractLocationProvider { private static final String TAG = "LocationProviderProxy"; private static final boolean D = LocationManagerService.D; + // used to ensure that updates to mProviderPackages are atomic + private final Object mProviderPackagesLock = new Object(); + // used to ensure that updates to mRequest and mWorkSource are atomic private final Object mRequestLock = new Object(); - private final ServiceWatcher mServiceWatcher; - private final ILocationProviderManager.Stub mManager = new ILocationProviderManager.Stub() { // executed on binder thread @Override + public void onSetAdditionalProviderPackages(List<String> packageNames) { + LocationProviderProxy.this.onSetAdditionalProviderPackages(packageNames); + } + + // executed on binder thread + @Override public void onSetEnabled(boolean enabled) { LocationProviderProxy.this.setEnabled(enabled); } @@ -73,6 +87,11 @@ public class LocationProviderProxy extends AbstractLocationProvider { } }; + private final ServiceWatcher mServiceWatcher; + + @GuardedBy("mProviderPackagesLock") + private final CopyOnWriteArrayList<String> mProviderPackages = new CopyOnWriteArrayList<>(); + @GuardedBy("mRequestLock") @Nullable private ProviderRequest mRequest; @@ -101,7 +120,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { private LocationProviderProxy(Context context, LocationProviderManager locationProviderManager, String action, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId) { - super(locationProviderManager); + super(context, locationProviderManager); mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, @@ -114,6 +133,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { @Override protected void onUnbind() { + resetProviderPackages(Collections.emptyList()); setEnabled(false); setProperties(null); } @@ -131,6 +151,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); if (D) Log.d(TAG, "applying state to connected service " + mServiceWatcher); + resetProviderPackages(Collections.emptyList()); + service.setLocationProviderManager(mManager); synchronized (mRequestLock) { @@ -140,9 +162,11 @@ public class LocationProviderProxy extends AbstractLocationProvider { } } - @Nullable - public String getConnectedPackageName() { - return mServiceWatcher.getCurrentPackageName(); + @Override + public List<String> getProviderPackages() { + synchronized (mProviderPackagesLock) { + return mProviderPackages; + } } @Override @@ -193,4 +217,30 @@ public class LocationProviderProxy extends AbstractLocationProvider { service.sendExtraCommand(command, extras); }); } + + private void onSetAdditionalProviderPackages(List<String> packageNames) { + resetProviderPackages(packageNames); + } + + private void resetProviderPackages(List<String> additionalPackageNames) { + ArrayList<String> permittedPackages = new ArrayList<>(additionalPackageNames.size()); + for (String packageName : additionalPackageNames) { + try { + mContext.getPackageManager().getPackageInfo(packageName, MATCH_SYSTEM_ONLY); + permittedPackages.add(packageName); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, mServiceWatcher + " specified unknown additional provider package: " + + packageName); + } + } + + synchronized (mProviderPackagesLock) { + mProviderPackages.clear(); + String myPackage = mServiceWatcher.getCurrentPackageName(); + if (myPackage != null) { + mProviderPackages.add(myPackage); + mProviderPackages.addAll(permittedPackages); + } + } + } } diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java index fe91c63e712b..6accad8a93a0 100644 --- a/services/core/java/com/android/server/location/MockProvider.java +++ b/services/core/java/com/android/server/location/MockProvider.java @@ -17,6 +17,7 @@ package com.android.server.location; import android.annotation.Nullable; +import android.content.Context; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -41,9 +42,9 @@ public class MockProvider extends AbstractLocationProvider { private long mStatusUpdateTime; private Bundle mExtras; - public MockProvider( + public MockProvider(Context context, LocationProviderManager locationProviderManager, ProviderProperties properties) { - super(locationProviderManager); + super(context, locationProviderManager); mEnabled = true; mLocation = null; diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java index 30260b2fe14c..3a841c91399e 100644 --- a/services/core/java/com/android/server/location/PassiveProvider.java +++ b/services/core/java/com/android/server/location/PassiveProvider.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.content.Context; import android.location.Criteria; import android.location.Location; import android.os.Bundle; @@ -42,8 +43,8 @@ public class PassiveProvider extends AbstractLocationProvider { private boolean mReportLocation; - public PassiveProvider(LocationProviderManager locationProviderManager) { - super(locationProviderManager); + public PassiveProvider(Context context, LocationProviderManager locationProviderManager) { + super(context, locationProviderManager); mReportLocation = false; |