Merge "Updates and fixes to GnssMeasurementsProvider"

This commit is contained in:
Soonil Nagarkar
2020-02-28 16:57:17 +00:00
committed by Android (Google) Code Review
5 changed files with 168 additions and 61 deletions

View File

@@ -78,13 +78,6 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
return mRequest;
}
/**
* Returns the listener, or null if this registration is no longer registered.
*/
protected @Nullable TListener getListener() {
return mListener;
}
boolean register() {
Preconditions.checkState(mListener != null);
return onRegister();
@@ -145,6 +138,9 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
@GuardedBy("mRegistrations")
private final ReentrancyGuard mReentrancyGuard = new ReentrancyGuard();
@GuardedBy("mRegistrations")
private boolean mActiveRegistrations = false;
@GuardedBy("mRegistrations")
private boolean mServiceRegistered = false;
@@ -216,36 +212,47 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
updateService();
}
@GuardedBy("mRegistrations")
private void updateService() {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mRegistrations));
}
ArrayList<TRegistration> actives = new ArrayList<>(mRegistrations.size());
for (int i = 0; i < mRegistrations.size(); i++) {
TRegistration registration = mRegistrations.valueAt(i);
if (isActive(registration)) {
actives.add(registration);
/**
* Forces a re-evalution of the active state of all registrations, the merged request for all
* active registrations, and service registration state.
*/
protected void updateService() {
synchronized (mRegistrations) {
ArrayList<TRegistration> actives = new ArrayList<>(mRegistrations.size());
for (int i = 0; i < mRegistrations.size(); i++) {
TRegistration registration = mRegistrations.valueAt(i);
if (isActive(registration)) {
actives.add(registration);
}
}
}
if (actives.isEmpty()) {
if (mServiceRegistered) {
unregisterService();
mServiceRegistered = false;
}
mCurrentRequest = null;
return;
}
if (actives.isEmpty()) {
if (mServiceRegistered) {
unregisterService();
mServiceRegistered = false;
}
mCurrentRequest = null;
TMergedRequest merged = mergeRequests(actives);
if (!mServiceRegistered || !Objects.equals(merged, mCurrentRequest)) {
if (mServiceRegistered) {
unregisterService();
if (mActiveRegistrations) {
mActiveRegistrations = false;
onInactive();
}
return;
} else {
if (!mActiveRegistrations) {
mActiveRegistrations = true;
onActive();
}
}
TMergedRequest merged = mergeRequests(actives);
if (!mServiceRegistered || !Objects.equals(merged, mCurrentRequest)) {
if (mServiceRegistered) {
unregisterService();
}
mCurrentRequest = merged;
mServiceRegistered = registerService(mCurrentRequest);
}
mCurrentRequest = merged;
mServiceRegistered = registerService(mCurrentRequest);
}
}
@@ -264,7 +271,8 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
/**
* Performs some function on all (not just active) registrations. The function should return
* true if the active state of the registration has changed, or if the change to the
* registration may have changed the result of {@link #mergeRequests(List)}.
* registration may have changed the result of {@link #mergeRequests(List)}. If the function
* returns true for any registration, {@link #updateService()} will be invoked.
*/
protected final void updateRegistrations(@NonNull Function<TRegistration, Boolean> function) {
synchronized (mRegistrations) {
@@ -307,6 +315,22 @@ public abstract class AbstractListenerManager<TKey, TRequest, TListener,
*/
protected abstract void unregisterService();
/**
* Invoked when the listener goes from having no active registrations to having some active
* registrations. This is a convenient entry point for registering listeners, etc, which only
* need to be present while there are active registrations. This method will always be invoked
* before a corrosponding call to {@link #registerService(Object)}.
*/
protected void onActive() {}
/**
* Invoked when the listener goes from having some active registrations to having no active
* registrations. This is a convenient entry point for unregistering listeners, etc, which only
* need to be present while there are active registrations. This method will always be invoked
* after a corrosponding call to {@link #unregisterService()}.
*/
protected void onInactive() {}
/**
* Invoked when a registration is added.
*/

View File

@@ -29,6 +29,7 @@ import com.android.server.location.gnss.GnssManagerService;
import com.android.server.location.util.listeners.GnssListenerManager;
import java.util.List;
import java.util.Objects;
/**
* An base implementation for GNSS measurements provider. It abstracts out the responsibility of
@@ -37,7 +38,8 @@ import java.util.List;
* @hide
*/
public class GnssMeasurementsProvider extends
GnssListenerManager<GnssRequest, IGnssMeasurementsListener, Boolean> {
GnssListenerManager<GnssRequest, IGnssMeasurementsListener, Boolean> implements
SettingsHelper.GlobalSettingChangedListener {
private final LocationUsageLogger mLogger;
private final GnssMeasurementProviderNative mNative;
@@ -94,6 +96,22 @@ public class GnssMeasurementsProvider extends
}
}
@Override
protected void onActive() {
mSettingsHelper.addOnGnssMeasurementsFullTrackingEnabledChangedListener(this);
}
@Override
protected void onInactive() {
mSettingsHelper.removeOnGnssMeasurementsFullTrackingEnabledChangedListener(this);
}
@Override
public void onSettingChanged() {
// GNSS Measurements Full Tracking dev setting changed
updateService();
}
@Override
protected Boolean mergeRequests(List<GnssRegistration> registrations) {
if (mSettingsHelper.isGnssMeasurementsFullTrackingEnabled()) {
@@ -101,7 +119,7 @@ public class GnssMeasurementsProvider extends
}
for (GnssRegistration registration : registrations) {
if (registration.getRequest().isFullTracking()) {
if (Objects.requireNonNull(registration.getRequest()).isFullTracking()) {
return true;
}
}

View File

@@ -98,6 +98,7 @@ public class SettingsHelper {
private final IntegerSecureSetting mLocationMode;
private final LongGlobalSetting mBackgroundThrottleIntervalMs;
private final BooleanGlobalSetting mGnssMeasurementFullTracking;
private final StringListCachedSecureSetting mLocationPackageBlacklist;
private final StringListCachedSecureSetting mLocationPackageWhitelist;
private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
@@ -110,6 +111,8 @@ public class SettingsHelper {
mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
mGnssMeasurementFullTracking = new BooleanGlobalSetting(context,
ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, handler);
mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
LOCATION_PACKAGE_BLACKLIST, handler);
mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
@@ -245,6 +248,30 @@ public class SettingsHelper {
mBackgroundThrottlePackageWhitelist.removeListener(listener);
}
/**
* Retrieve the gnss measurements full tracking enabled setting.
*/
public boolean isGnssMeasurementsFullTrackingEnabled() {
return mGnssMeasurementFullTracking.getValue(false);
}
/**
* Add a listener for changes to the background throttle package whitelist. Callbacks occur on
* an unspecified thread.
*/
public void addOnGnssMeasurementsFullTrackingEnabledChangedListener(
GlobalSettingChangedListener listener) {
mGnssMeasurementFullTracking.addListener(listener);
}
/**
* Remove a listener for changes to the background throttle package whitelist.
*/
public void removeOnGnssMeasurementsFullTrackingEnabledChangedListener(
GlobalSettingChangedListener listener) {
mGnssMeasurementFullTracking.removeListener(listener);
}
/**
* Retrieve the ignore settings package whitelist.
*/
@@ -283,19 +310,6 @@ public class SettingsHelper {
}
}
/**
* Retrieve the gnss measurements full tracking enabled setting.
*/
public boolean isGnssMeasurementsFullTrackingEnabled() {
long identity = Binder.clearCallingIdentity();
try {
return Settings.Global.getInt(mContext.getContentResolver(),
ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0) == 1;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
* Retrieve the accuracy for coarsening location, ie, the grid size used for snap-to-grid
* coarsening.
@@ -395,7 +409,7 @@ public class SettingsHelper {
@GuardedBy("this")
private boolean mRegistered;
private ObservingSetting(Handler handler) {
ObservingSetting(Handler handler) {
super(handler);
mListeners = new CopyOnWriteArrayList<>();
}
@@ -439,13 +453,13 @@ public class SettingsHelper {
private final Context mContext;
private final String mSettingName;
private IntegerSecureSetting(Context context, String settingName, Handler handler) {
IntegerSecureSetting(Context context, String settingName, Handler handler) {
super(handler);
mContext = context;
mSettingName = settingName;
}
private void register() {
void register() {
register(mContext, Settings.Secure.getUriFor(mSettingName));
}
@@ -470,7 +484,7 @@ public class SettingsHelper {
@GuardedBy("this")
private List<String> mCachedValue;
private StringListCachedSecureSetting(Context context, String settingName,
StringListCachedSecureSetting(Context context, String settingName,
Handler handler) {
super(handler);
mContext = context;
@@ -524,12 +538,38 @@ public class SettingsHelper {
}
}
private static class BooleanGlobalSetting extends ObservingSetting {
private final Context mContext;
private final String mSettingName;
BooleanGlobalSetting(Context context, String settingName, Handler handler) {
super(handler);
mContext = context;
mSettingName = settingName;
}
public void register() {
register(mContext, Settings.Global.getUriFor(mSettingName));
}
public boolean getValue(boolean defaultValue) {
long identity = Binder.clearCallingIdentity();
try {
return Settings.Global.getInt(mContext.getContentResolver(), mSettingName,
defaultValue ? 1 : 0) != 0;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
private static class LongGlobalSetting extends ObservingSetting {
private final Context mContext;
private final String mSettingName;
private LongGlobalSetting(Context context, String settingName, Handler handler) {
LongGlobalSetting(Context context, String settingName, Handler handler) {
super(handler);
mContext = context;
mSettingName = settingName;
@@ -561,7 +601,7 @@ public class SettingsHelper {
@GuardedBy("this")
private ArraySet<String> mCachedValue;
private StringSetCachedGlobalSetting(Context context, String settingName,
StringSetCachedGlobalSetting(Context context, String settingName,
Supplier<ArraySet<String>> baseValuesSupplier, Handler handler) {
super(handler);
mContext = context;

View File

@@ -313,9 +313,8 @@ public class GnssManagerService {
/**
* Adds a GNSS measurements listener.
*/
public void addGnssMeasurementsListener(@Nullable GnssRequest request,
IGnssMeasurementsListener listener, String packageName,
@Nullable String featureId) {
public void addGnssMeasurementsListener(GnssRequest request, IGnssMeasurementsListener listener,
String packageName, @Nullable String featureId) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
if (request.isFullTracking()) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);

View File

@@ -56,6 +56,7 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(0, listener);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(0);
mListenerManager.notifyListeners();
@@ -69,6 +70,7 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(0, listener);
mListenerManager.removeListener(listener);
assertThat(mListenerManager.mRegistered).isFalse();
assertThat(mListenerManager.mActive).isFalse();
mListenerManager.notifyListeners();
verify(listener, never()).run();
@@ -83,6 +85,7 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(0, listener1);
mListenerManager.addListener(1, listener2);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(1);
mListenerManager.notifyListeners();
@@ -92,6 +95,7 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(0, listener3);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(1);
mListenerManager.notifyListeners();
@@ -101,6 +105,7 @@ public class AbstractListenerManagerTest {
mListenerManager.removeListener(listener2);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(0);
mListenerManager.notifyListeners();
@@ -111,6 +116,7 @@ public class AbstractListenerManagerTest {
mListenerManager.removeListener(listener1);
mListenerManager.removeListener(listener3);
assertThat(mListenerManager.mRegistered).isFalse();
assertThat(mListenerManager.mActive).isFalse();
}
@Test
@@ -133,12 +139,14 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(0, listener);
mListenerManager.setActive(0, false);
assertThat(mListenerManager.mRegistered).isFalse();
assertThat(mListenerManager.mActive).isFalse();
mListenerManager.notifyListeners();
verify(listener, never()).run();
mListenerManager.setActive(0, true);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(0);
mListenerManager.notifyListeners();
@@ -155,6 +163,7 @@ public class AbstractListenerManagerTest {
mListenerManager.addListener(2, listener2);
mListenerManager.addListener(1, listener3);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(2);
mListenerManager.notifyListeners();
@@ -164,6 +173,7 @@ public class AbstractListenerManagerTest {
mListenerManager.setActive(2, false);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(1);
mListenerManager.notifyListeners();
@@ -173,6 +183,7 @@ public class AbstractListenerManagerTest {
mListenerManager.setActive(2, true);
assertThat(mListenerManager.mRegistered).isTrue();
assertThat(mListenerManager.mActive).isTrue();
assertThat(mListenerManager.mMergedRequest).isEqualTo(2);
mListenerManager.notifyListeners();
@@ -184,12 +195,13 @@ public class AbstractListenerManagerTest {
mListenerManager.setActive(1, false);
mListenerManager.setActive(2, false);
assertThat(mListenerManager.mRegistered).isFalse();
assertThat(mListenerManager.mActive).isFalse();
}
private static class TestRegistration extends
AbstractListenerManager.Registration<Integer, Runnable> {
private boolean mActive = true;
boolean mActive = true;
protected TestRegistration(Integer integer, Runnable runnable) {
super(integer, DIRECT_EXECUTOR, runnable);
@@ -199,8 +211,12 @@ public class AbstractListenerManagerTest {
private static class TestListenerManager extends
AbstractListenerManager<Runnable, Integer, Runnable, TestRegistration, Integer> {
private boolean mRegistered;
private int mMergedRequest;
boolean mActive;
boolean mRegistered;
int mMergedRequest;
TestListenerManager() {
}
public void addListener(Integer request, Runnable listener) {
addRegistration(listener, new TestRegistration(request, listener));
@@ -245,6 +261,16 @@ public class AbstractListenerManagerTest {
return registration.mActive;
}
@Override
protected void onActive() {
mActive = true;
}
@Override
protected void onInactive() {
mActive = false;
}
@Override
protected Integer mergeRequests(List<TestRegistration> testRegistrations) {
int max = Integer.MIN_VALUE;