summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt1
-rw-r--r--location/java/android/location/ILocationManager.aidl3
-rw-r--r--location/java/android/location/LocationManager.java16
-rw-r--r--location/java/com/android/internal/location/ILocationProviderManager.aidl2
-rw-r--r--location/lib/api/current.txt1
-rw-r--r--location/lib/java/com/android/location/provider/LocationProviderBase.java30
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java81
-rw-r--r--services/core/java/com/android/server/location/AbstractLocationProvider.java12
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java4
-rw-r--r--services/core/java/com/android/server/location/LocationProviderProxy.java62
-rw-r--r--services/core/java/com/android/server/location/MockProvider.java5
-rw-r--r--services/core/java/com/android/server/location/PassiveProvider.java5
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;