summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2021-02-08 21:01:41 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-02-08 21:01:41 +0000
commit15c8bf6793f3ca582cbb5b285f3fbdaf86e2cc76 (patch)
tree45060823652c20a224ee9d7d8023a954e9f42e5e
parentb610667bfd88681a2c089150315f8e4eedd3691e (diff)
parent72a25122677dda9145ce6b42108933d1e72ebcf6 (diff)
Merge "Add LocationManager#registerProviderRequestListener" into sc-dev
-rw-r--r--core/api/system-current.txt6
-rw-r--r--location/java/android/location/ILocationManager.aidl4
-rw-r--r--location/java/android/location/LocationManager.java83
-rw-r--r--location/java/android/location/provider/IProviderRequestListener.aidl26
-rw-r--r--location/java/android/location/provider/ProviderRequest.java11
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java15
-rw-r--r--services/core/java/com/android/server/location/provider/LocationProviderManager.java41
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java18
8 files changed, 198 insertions, 6 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6fec3095ed16..1192d1fa59af 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4666,6 +4666,7 @@ package android.location {
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerProviderRequestListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.Listener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -4674,6 +4675,7 @@ package android.location {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void unregisterProviderRequestListener(@NonNull android.location.provider.ProviderRequest.Listener);
}
public final class LocationRequest implements android.os.Parcelable {
@@ -4823,6 +4825,10 @@ package android.location.provider {
method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
}
+ public static interface ProviderRequest.Listener {
+ method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
+ }
+
}
package android.media {
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 65721cc33aed..adf58da6a072 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -36,6 +36,7 @@ import android.location.LastLocationRequest;
import android.location.Location;
import android.location.LocationRequest;
import android.location.LocationTime;
+import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.os.Bundle;
import android.os.ICancellationSignal;
@@ -91,6 +92,9 @@ interface ILocationManager
void addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener, String packageName, @nullable String attributionTag);
void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
+ void addProviderRequestListener(in IProviderRequestListener listener);
+ void removeProviderRequestListener(in IProviderRequestListener listener);
+
int getGnssBatchSize();
void startGnssBatch(long periodNanos, in ILocationListener listener, String packageName, @nullable String attributionTag, @nullable String listenerId);
void flushGnssBatch();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d56948222797..088b789ea690 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -49,7 +49,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
+import android.location.provider.ProviderRequest;
+import android.location.provider.ProviderRequest.Listener;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -436,6 +439,9 @@ public class LocationManager {
new GnssNavigationTransportManager();
}
+ private static final ProviderRequestTransportManager sProviderRequestListeners =
+ new ProviderRequestTransportManager();
+
private final Context mContext;
private final ILocationManager mService;
@@ -2772,6 +2778,37 @@ public class LocationManager {
}
/**
+ * Registers a {@link ProviderRequest.Listener} to all providers.
+ *
+ * @param executor the executor that the callback runs on
+ * @param listener the listener to register
+ * @return {@code true} always
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
+ public boolean registerProviderRequestListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Listener listener) {
+ sProviderRequestListeners.addListener(listener,
+ new ProviderRequestTransport(executor, listener));
+ return true;
+ }
+
+ /**
+ * Unregisters a {@link ProviderRequest.Listener}.
+ *
+ * @param listener the listener to remove.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
+ public void unregisterProviderRequestListener(
+ @NonNull Listener listener) {
+ sProviderRequestListeners.removeListener(listener);
+ }
+
+ /**
* Returns the batch size (in number of Location objects) that are supported by the batching
* interface.
*
@@ -2960,6 +2997,22 @@ public class LocationManager {
}
}
+ private static class ProviderRequestTransportManager extends
+ ListenerTransportManager<ProviderRequestTransport> {
+
+ @Override
+ protected void registerTransport(ProviderRequestTransport transport)
+ throws RemoteException {
+ getService().addProviderRequestListener(transport);
+ }
+
+ @Override
+ protected void unregisterTransport(ProviderRequestTransport transport)
+ throws RemoteException {
+ getService().removeProviderRequestListener(transport);
+ }
+ }
+
private static class GetCurrentLocationTransport extends ILocationCallback.Stub implements
ListenerExecutor, CancellationSignal.OnCancelListener {
@@ -3359,6 +3412,36 @@ public class LocationManager {
}
}
+ private static class ProviderRequestTransport extends IProviderRequestListener.Stub
+ implements ListenerTransport<ProviderRequest.Listener> {
+
+ private final Executor mExecutor;
+
+ private volatile @Nullable ProviderRequest.Listener mListener;
+
+ ProviderRequestTransport(Executor executor, ProviderRequest.Listener listener) {
+ Preconditions.checkArgument(executor != null, "invalid null executor");
+ Preconditions.checkArgument(listener != null, "invalid null callback");
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void unregister() {
+ mListener = null;
+ }
+
+ @Override
+ public @Nullable ProviderRequest.Listener getListener() {
+ return mListener;
+ }
+
+ @Override
+ public void onProviderRequestChanged(String provider, ProviderRequest request) {
+ execute(mExecutor, listener -> listener.onProviderRequestChanged(provider, request));
+ }
+ }
+
private static class BatchedLocationCallbackWrapper implements LocationListener {
private final BatchedLocationCallback mCallback;
diff --git a/location/java/android/location/provider/IProviderRequestListener.aidl b/location/java/android/location/provider/IProviderRequestListener.aidl
new file mode 100644
index 000000000000..89d454aafe2c
--- /dev/null
+++ b/location/java/android/location/provider/IProviderRequestListener.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021, 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 android.location.provider;
+
+import android.location.provider.ProviderRequest;
+
+/**
+ * {@hide}
+ */
+oneway interface IProviderRequestListener {
+ void onProviderRequestChanged(String provider, in ProviderRequest request);
+}
diff --git a/location/java/android/location/provider/ProviderRequest.java b/location/java/android/location/provider/ProviderRequest.java
index e543b040a2d4..b6ec32309b08 100644
--- a/location/java/android/location/provider/ProviderRequest.java
+++ b/location/java/android/location/provider/ProviderRequest.java
@@ -53,6 +53,17 @@ public final class ProviderRequest implements Parcelable {
private final boolean mLocationSettingsIgnored;
private final WorkSource mWorkSource;
+ /**
+ * Listener to be invoked when a new request is set to the provider.
+ */
+ public interface Listener {
+
+ /**
+ * Invoked when a new request is set.
+ */
+ void onProviderRequestChanged(@NonNull String provider, @NonNull ProviderRequest request);
+ }
+
private ProviderRequest(
long intervalMillis,
@Quality int quality,
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 142f64f0a510..ea759bf500dd 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -66,6 +66,7 @@ import android.location.LocationManagerInternal;
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.LocationTime;
+import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.util.identity.CallerIdentity;
import android.os.Binder;
@@ -882,6 +883,20 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
+ public void addProviderRequestListener(IProviderRequestListener listener) {
+ for (LocationProviderManager manager : mProviderManagers) {
+ manager.addProviderRequestListener(listener);
+ }
+ }
+
+ @Override
+ public void removeProviderRequestListener(IProviderRequestListener listener) {
+ for (LocationProviderManager manager : mProviderManagers) {
+ manager.removeProviderRequestListener(listener);
+ }
+ }
+
+ @Override
public void injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections) {
if (mGnssManagerService != null) {
mGnssManagerService.injectGnssMeasurementCorrections(corrections);
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 221d4fb40ef9..48a012e57a02 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -55,6 +55,7 @@ import android.location.LocationManagerInternal;
import android.location.LocationManagerInternal.ProviderEnabledListener;
import android.location.LocationRequest;
import android.location.LocationResult;
+import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
import android.location.util.identity.CallerIdentity;
@@ -117,6 +118,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
/**
@@ -1219,6 +1221,8 @@ public class LocationProviderManager extends
@GuardedBy("mLock")
private final ArrayList<ProviderEnabledListener> mEnabledListeners;
+ private final CopyOnWriteArrayList<IProviderRequestListener> mProviderRequestListeners;
+
protected final LocationManagerInternal mLocationManagerInternal;
protected final SettingsHelper mSettingsHelper;
protected final UserInfoHelper mUserHelper;
@@ -1279,6 +1283,7 @@ public class LocationProviderManager extends
mLastLocations = new SparseArray<>(2);
mEnabledListeners = new ArrayList<>();
+ mProviderRequestListeners = new CopyOnWriteArrayList<>();
mLocationManagerInternal = Objects.requireNonNull(
LocalServices.getService(LocationManagerInternal.class));
@@ -1344,6 +1349,7 @@ public class LocationProviderManager extends
// if external entities are registering listeners it's their responsibility to
// unregister them before stopManager() is called
Preconditions.checkState(mEnabledListeners.isEmpty());
+ mProviderRequestListeners.clear();
mEnabled.clear();
mLastLocations.clear();
@@ -1404,6 +1410,16 @@ public class LocationProviderManager extends
}
}
+ /** Add a {@link IProviderRequestListener}. */
+ public void addProviderRequestListener(IProviderRequestListener listener) {
+ mProviderRequestListeners.add(listener);
+ }
+
+ /** Remove a {@link IProviderRequestListener}. */
+ public void removeProviderRequestListener(IProviderRequestListener listener) {
+ mProviderRequestListeners.remove(listener);
+ }
+
public void setRealProvider(@Nullable AbstractLocationProvider provider) {
synchronized (mLock) {
Preconditions.checkState(mState != STATE_STOPPED);
@@ -1873,8 +1889,7 @@ public class LocationProviderManager extends
Preconditions.checkState(delayMs >= 0 && delayMs <= newRequest.getIntervalMillis());
if (delayMs < MIN_REQUEST_DELAY_MS) {
- mLocationEventLog.logProviderUpdateRequest(mName, newRequest);
- mProvider.getController().setRequest(newRequest);
+ setProviderRequest(newRequest);
} else {
if (D) {
Log.d(TAG, mName + " provider delaying request update " + newRequest + " by "
@@ -1886,8 +1901,7 @@ public class LocationProviderManager extends
public void onAlarm() {
synchronized (mLock) {
if (mDelayedRegister == this) {
- mLocationEventLog.logProviderUpdateRequest(mName, newRequest);
- mProvider.getController().setRequest(newRequest);
+ setProviderRequest(newRequest);
mDelayedRegister = null;
}
}
@@ -1906,8 +1920,23 @@ public class LocationProviderManager extends
Preconditions.checkState(Thread.holdsLock(mLock));
}
- mLocationEventLog.logProviderUpdateRequest(mName, ProviderRequest.EMPTY_REQUEST);
- mProvider.getController().setRequest(ProviderRequest.EMPTY_REQUEST);
+ setProviderRequest(ProviderRequest.EMPTY_REQUEST);
+ }
+
+ @GuardedBy("mLock")
+ private void setProviderRequest(ProviderRequest request) {
+ mLocationEventLog.logProviderUpdateRequest(mName, request);
+ mProvider.getController().setRequest(request);
+
+ FgThread.getHandler().post(() -> {
+ for (IProviderRequestListener listener : mProviderRequestListeners) {
+ try {
+ listener.onProviderRequestChanged(mName, request);
+ } catch (RemoteException e) {
+ mProviderRequestListeners.remove(listener);
+ }
+ }
+ });
}
@GuardedBy("mLock")
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 3b5cc887c798..54fa89a1e24b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -64,6 +64,7 @@ import android.location.LocationManagerInternal;
import android.location.LocationManagerInternal.ProviderEnabledListener;
import android.location.LocationRequest;
import android.location.LocationResult;
+import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
import android.location.util.identity.CallerIdentity;
@@ -662,6 +663,23 @@ public class LocationProviderManagerTest {
}
@Test
+ public void testProviderRequestListener() throws Exception {
+ IProviderRequestListener requestListener = mock(IProviderRequestListener.class);
+ mManager.addProviderRequestListener(requestListener);
+
+ ILocationListener locationListener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(1).setWorkSource(
+ WORK_SOURCE).build();
+ mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, locationListener);
+
+ verify(requestListener, timeout(TIMEOUT_MS).times(1)).onProviderRequestChanged(anyString(),
+ any(ProviderRequest.class));
+
+ mManager.unregisterLocationRequest(locationListener);
+ mManager.removeProviderRequestListener(requestListener);
+ }
+
+ @Test
public void testGetCurrentLocation() throws Exception {
ILocationCallback listener = createMockGetCurrentLocationListener();
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();