Merge "Add LocationManager#registerProviderRequestListener" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-02-08 21:01:41 +00:00
committed by Android (Google) Code Review
8 changed files with 198 additions and 6 deletions

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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;
@@ -2771,6 +2777,37 @@ public class LocationManager {
GnssLazyLoader.sGnssNavigationListeners.removeListener(callback);
}
/**
* 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;

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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;
@@ -881,6 +882,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) {

View File

@@ -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")

View File

@@ -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;
@@ -661,6 +662,23 @@ public class LocationProviderManagerTest {
.onLocationChanged(any(List.class), nullable(IRemoteCallback.class));
}
@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();