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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2424,6 +2424,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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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() {
|
||||
@@ -159,6 +163,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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2975,28 +2987,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) {
|
||||
@@ -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:");
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,12 +55,19 @@ 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) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user