Show location icon for GNSS measurements
Mark active GNSS measurement registrations as using high power, which will usually cause the location icon to be shown. Bug: 162605910 Test: manual + presubmits Change-Id: I07e94532badae648dc377a5b74619fce0a864eae
This commit is contained in:
@@ -67,7 +67,7 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
/**
|
||||
* Registration object for GNSS listeners.
|
||||
*/
|
||||
protected final class GnssListenerRegistration extends
|
||||
protected class GnssListenerRegistration extends
|
||||
BinderListenerRegistration<TRequest, TListener> {
|
||||
|
||||
// we store these values because we don't trust the listeners not to give us dupes, not to
|
||||
@@ -232,12 +232,20 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
addRegistration(listener.asBinder(),
|
||||
new GnssListenerRegistration(request, callerIdentity, listener));
|
||||
createRegistration(request, callerIdentity, listener));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* May be overridden by subclasses to change the registration type.
|
||||
*/
|
||||
protected GnssListenerRegistration createRegistration(TRequest request,
|
||||
CallerIdentity callerIdentity, TListener listener) {
|
||||
return new GnssListenerRegistration(request, callerIdentity, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given listener.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.location.gnss;
|
||||
import static com.android.server.location.gnss.GnssManagerService.D;
|
||||
import static com.android.server.location.gnss.GnssManagerService.TAG;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.location.GnssMeasurementsEvent;
|
||||
import android.location.GnssRequest;
|
||||
@@ -32,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.location.util.AppOpsHelper;
|
||||
import com.android.server.location.util.Injector;
|
||||
import com.android.server.location.util.LocationAttributionHelper;
|
||||
import com.android.server.location.util.LocationUsageLogger;
|
||||
import com.android.server.location.util.SettingsHelper;
|
||||
|
||||
@@ -44,11 +46,40 @@ import java.util.Objects;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class GnssMeasurementsProvider extends
|
||||
public final class GnssMeasurementsProvider extends
|
||||
GnssListenerMultiplexer<GnssRequest, IGnssMeasurementsListener, Boolean> implements
|
||||
SettingsHelper.GlobalSettingChangedListener {
|
||||
|
||||
private class GnssMeasurementListenerRegistration extends GnssListenerRegistration {
|
||||
|
||||
private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement";
|
||||
|
||||
protected GnssMeasurementListenerRegistration(
|
||||
@Nullable GnssRequest gnssRequest,
|
||||
CallerIdentity callerIdentity,
|
||||
IGnssMeasurementsListener iGnssMeasurementsListener) {
|
||||
super(gnssRequest, callerIdentity, iGnssMeasurementsListener);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ListenerOperation<IGnssMeasurementsListener> onActive() {
|
||||
mLocationAttributionHelper.reportHighPowerLocationStart(
|
||||
getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ListenerOperation<IGnssMeasurementsListener> onInactive() {
|
||||
mLocationAttributionHelper.reportHighPowerLocationStop(
|
||||
getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final AppOpsHelper mAppOpsHelper;
|
||||
private final LocationAttributionHelper mLocationAttributionHelper;
|
||||
private final LocationUsageLogger mLogger;
|
||||
private final GnssMeasurementProviderNative mNative;
|
||||
|
||||
@@ -60,6 +91,7 @@ public class GnssMeasurementsProvider extends
|
||||
public GnssMeasurementsProvider(Injector injector, GnssMeasurementProviderNative aNative) {
|
||||
super(injector);
|
||||
mAppOpsHelper = injector.getAppOpsHelper();
|
||||
mLocationAttributionHelper = injector.getLocationAttributionHelper();
|
||||
mLogger = injector.getLocationUsageLogger();
|
||||
mNative = aNative;
|
||||
}
|
||||
@@ -75,6 +107,12 @@ public class GnssMeasurementsProvider extends
|
||||
super.addListener(request, identity, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GnssListenerRegistration createRegistration(GnssRequest request,
|
||||
CallerIdentity callerIdentity, IGnssMeasurementsListener listener) {
|
||||
return new GnssMeasurementListenerRegistration(request, callerIdentity, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean registerWithService(Boolean fullTrackingRequest,
|
||||
Collection<GnssListenerRegistration> registrations) {
|
||||
|
||||
@@ -38,12 +38,12 @@ import java.util.Set;
|
||||
*/
|
||||
public class LocationAttributionHelper {
|
||||
|
||||
private static class ProviderListener {
|
||||
private final String mProvider;
|
||||
private static class BucketKey {
|
||||
private final String mBucket;
|
||||
private final Object mKey;
|
||||
|
||||
private ProviderListener(String provider, Object key) {
|
||||
mProvider = Objects.requireNonNull(provider);
|
||||
private BucketKey(String bucket, Object key) {
|
||||
mBucket = Objects.requireNonNull(bucket);
|
||||
mKey = Objects.requireNonNull(key);
|
||||
}
|
||||
|
||||
@@ -56,23 +56,23 @@ public class LocationAttributionHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProviderListener that = (ProviderListener) o;
|
||||
return mProvider.equals(that.mProvider)
|
||||
BucketKey that = (BucketKey) o;
|
||||
return mBucket.equals(that.mBucket)
|
||||
&& mKey.equals(that.mKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mProvider, mKey);
|
||||
return Objects.hash(mBucket, mKey);
|
||||
}
|
||||
}
|
||||
|
||||
private final AppOpsHelper mAppOpsHelper;
|
||||
|
||||
@GuardedBy("this")
|
||||
private final Map<CallerIdentity, Set<ProviderListener>> mAttributions;
|
||||
private final Map<CallerIdentity, Set<BucketKey>> mAttributions;
|
||||
@GuardedBy("this")
|
||||
private final Map<CallerIdentity, Set<ProviderListener>> mHighPowerAttributions;
|
||||
private final Map<CallerIdentity, Set<BucketKey>> mHighPowerAttributions;
|
||||
|
||||
public LocationAttributionHelper(AppOpsHelper appOpsHelper) {
|
||||
mAppOpsHelper = appOpsHelper;
|
||||
@@ -82,14 +82,14 @@ public class LocationAttributionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report normal location usage for the given caller on the given provider, with a unique key.
|
||||
* Report normal location usage for the given caller in the given bucket, with a unique key.
|
||||
*/
|
||||
public synchronized void reportLocationStart(CallerIdentity identity, String provider,
|
||||
public synchronized void reportLocationStart(CallerIdentity identity, String bucket,
|
||||
Object key) {
|
||||
Set<ProviderListener> keySet = mAttributions.computeIfAbsent(identity,
|
||||
Set<BucketKey> keySet = mAttributions.computeIfAbsent(identity,
|
||||
i -> new ArraySet<>());
|
||||
boolean empty = keySet.isEmpty();
|
||||
if (keySet.add(new ProviderListener(provider, key)) && empty) {
|
||||
if (keySet.add(new BucketKey(bucket, key)) && empty) {
|
||||
if (!mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) {
|
||||
mAttributions.remove(identity);
|
||||
}
|
||||
@@ -97,13 +97,13 @@ public class LocationAttributionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report normal location usage has stopped for the given caller on the given provider, with a
|
||||
* Report normal location usage has stopped for the given caller in the given bucket, with a
|
||||
* unique key.
|
||||
*/
|
||||
public synchronized void reportLocationStop(CallerIdentity identity, String provider,
|
||||
public synchronized void reportLocationStop(CallerIdentity identity, String bucket,
|
||||
Object key) {
|
||||
Set<ProviderListener> keySet = mAttributions.get(identity);
|
||||
if (keySet != null && keySet.remove(new ProviderListener(provider, key))
|
||||
Set<BucketKey> keySet = mAttributions.get(identity);
|
||||
if (keySet != null && keySet.remove(new BucketKey(bucket, key))
|
||||
&& keySet.isEmpty()) {
|
||||
mAttributions.remove(identity);
|
||||
mAppOpsHelper.finishOp(OP_MONITOR_LOCATION, identity);
|
||||
@@ -111,15 +111,15 @@ public class LocationAttributionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report high power location usage for the given caller on the given provider, with a unique
|
||||
* Report high power location usage for the given caller in the given bucket, with a unique
|
||||
* key.
|
||||
*/
|
||||
public synchronized void reportHighPowerLocationStart(CallerIdentity identity, String provider,
|
||||
public synchronized void reportHighPowerLocationStart(CallerIdentity identity, String bucket,
|
||||
Object key) {
|
||||
Set<ProviderListener> keySet = mHighPowerAttributions.computeIfAbsent(identity,
|
||||
Set<BucketKey> keySet = mHighPowerAttributions.computeIfAbsent(identity,
|
||||
i -> new ArraySet<>());
|
||||
boolean empty = keySet.isEmpty();
|
||||
if (keySet.add(new ProviderListener(provider, key)) && empty) {
|
||||
if (keySet.add(new BucketKey(bucket, key)) && empty) {
|
||||
if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) {
|
||||
if (D) {
|
||||
Log.v(TAG, "starting high power location attribution for " + identity);
|
||||
@@ -131,13 +131,13 @@ public class LocationAttributionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report high power location usage has stopped for the given caller on the given provider,
|
||||
* Report high power location usage has stopped for the given caller in the given bucket,
|
||||
* with a unique key.
|
||||
*/
|
||||
public synchronized void reportHighPowerLocationStop(CallerIdentity identity, String provider,
|
||||
public synchronized void reportHighPowerLocationStop(CallerIdentity identity, String bucket,
|
||||
Object key) {
|
||||
Set<ProviderListener> keySet = mHighPowerAttributions.get(identity);
|
||||
if (keySet != null && keySet.remove(new ProviderListener(provider, key))
|
||||
Set<BucketKey> keySet = mHighPowerAttributions.get(identity);
|
||||
if (keySet != null && keySet.remove(new BucketKey(bucket, key))
|
||||
&& keySet.isEmpty()) {
|
||||
if (D) {
|
||||
Log.v(TAG, "stopping high power location attribution for " + identity);
|
||||
|
||||
Reference in New Issue
Block a user