Merge "Listen for PACKAGE_RESET queries and events"
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 5c84a62..ae65dcb 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -1,6 +1,9 @@
{
"presubmit": [
{
+ "name": "CtsLocationFineTestCases"
+ },
+ {
"name": "CtsLocationCoarseTestCases"
},
{
@@ -66,10 +69,5 @@
],
"file_patterns": ["ClipboardService\\.java"]
}
- ],
- "postsubmit": [
- {
- "name": "CtsLocationFineTestCases"
- }
]
}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 1d1057f..9bd48f2 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -115,6 +115,7 @@
import com.android.server.location.injector.LocationPermissionsHelper;
import com.android.server.location.injector.LocationPowerSaveModeHelper;
import com.android.server.location.injector.LocationUsageLogger;
+import com.android.server.location.injector.PackageResetHelper;
import com.android.server.location.injector.ScreenInteractiveHelper;
import com.android.server.location.injector.SettingsHelper;
import com.android.server.location.injector.SystemAlarmHelper;
@@ -125,6 +126,7 @@
import com.android.server.location.injector.SystemEmergencyHelper;
import com.android.server.location.injector.SystemLocationPermissionsHelper;
import com.android.server.location.injector.SystemLocationPowerSaveModeHelper;
+import com.android.server.location.injector.SystemPackageResetHelper;
import com.android.server.location.injector.SystemScreenInteractiveHelper;
import com.android.server.location.injector.SystemSettingsHelper;
import com.android.server.location.injector.SystemUserInfoHelper;
@@ -1696,11 +1698,13 @@
private final SystemDeviceStationaryHelper mDeviceStationaryHelper;
private final SystemDeviceIdleHelper mDeviceIdleHelper;
private final LocationUsageLogger mLocationUsageLogger;
+ private final PackageResetHelper mPackageResetHelper;
// lazily instantiated since they may not always be used
@GuardedBy("this")
- private @Nullable SystemEmergencyHelper mEmergencyCallHelper;
+ @Nullable
+ private SystemEmergencyHelper mEmergencyCallHelper;
@GuardedBy("this")
private boolean mSystemReady;
@@ -1721,6 +1725,7 @@
mDeviceStationaryHelper = new SystemDeviceStationaryHelper();
mDeviceIdleHelper = new SystemDeviceIdleHelper(context);
mLocationUsageLogger = new LocationUsageLogger();
+ mPackageResetHelper = new SystemPackageResetHelper(context);
}
synchronized void onSystemReady() {
@@ -1811,5 +1816,10 @@
public LocationUsageLogger getLocationUsageLogger() {
return mLocationUsageLogger;
}
+
+ @Override
+ public PackageResetHelper getPackageResetHelper() {
+ return mPackageResetHelper;
+ }
}
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
index 82bcca2..e7f6e67 100644
--- a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
@@ -39,6 +39,7 @@
import com.android.server.location.injector.AppForegroundHelper;
import com.android.server.location.injector.Injector;
import com.android.server.location.injector.LocationPermissionsHelper;
+import com.android.server.location.injector.PackageResetHelper;
import com.android.server.location.injector.SettingsHelper;
import com.android.server.location.injector.UserInfoHelper;
import com.android.server.location.injector.UserInfoHelper.UserListener;
@@ -193,6 +194,7 @@
protected final LocationPermissionsHelper mLocationPermissionsHelper;
protected final AppForegroundHelper mAppForegroundHelper;
protected final LocationManagerInternal mLocationManagerInternal;
+ private final PackageResetHelper mPackageResetHelper;
private final UserListener mUserChangedListener = this::onUserChanged;
private final ProviderEnabledListener mProviderEnabledChangedListener =
@@ -218,12 +220,25 @@
};
private final AppForegroundHelper.AppForegroundListener mAppForegroundChangedListener =
this::onAppForegroundChanged;
+ private final PackageResetHelper.Responder mPackageResetResponder =
+ new PackageResetHelper.Responder() {
+ @Override
+ public void onPackageReset(String packageName) {
+ GnssListenerMultiplexer.this.onPackageReset(packageName);
+ }
+
+ @Override
+ public boolean isResetableForPackage(String packageName) {
+ return GnssListenerMultiplexer.this.isResetableForPackage(packageName);
+ }
+ };
protected GnssListenerMultiplexer(Injector injector) {
mUserInfoHelper = injector.getUserInfoHelper();
mSettingsHelper = injector.getSettingsHelper();
mLocationPermissionsHelper = injector.getLocationPermissionsHelper();
mAppForegroundHelper = injector.getAppForegroundHelper();
+ mPackageResetHelper = injector.getPackageResetHelper();
mLocationManagerInternal = Objects.requireNonNull(
LocalServices.getService(LocationManagerInternal.class));
}
@@ -357,6 +372,7 @@
mLocationPackageBlacklistChangedListener);
mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
mAppForegroundHelper.addListener(mAppForegroundChangedListener);
+ mPackageResetHelper.register(mPackageResetResponder);
}
@Override
@@ -374,6 +390,7 @@
mLocationPackageBlacklistChangedListener);
mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
mAppForegroundHelper.removeListener(mAppForegroundChangedListener);
+ mPackageResetHelper.unregister(mPackageResetResponder);
}
private void onUserChanged(int userId, int change) {
@@ -407,6 +424,27 @@
updateRegistrations(registration -> registration.onForegroundChanged(uid, foreground));
}
+ private void onPackageReset(String packageName) {
+ // invoked when a package is "force quit" - move off the main thread
+ FgThread.getExecutor().execute(
+ () ->
+ updateRegistrations(
+ registration -> {
+ if (registration.getIdentity().getPackageName().equals(
+ packageName)) {
+ registration.remove();
+ }
+
+ return false;
+ }));
+ }
+
+ private boolean isResetableForPackage(String packageName) {
+ // invoked to find out if the given package has any state that can be "force quit"
+ return findRegistration(
+ registration -> registration.getIdentity().getPackageName().equals(packageName));
+ }
+
@Override
protected String getServiceState() {
if (!isSupported()) {
diff --git a/services/core/java/com/android/server/location/injector/Injector.java b/services/core/java/com/android/server/location/injector/Injector.java
index c0ce3a6..b2c8672 100644
--- a/services/core/java/com/android/server/location/injector/Injector.java
+++ b/services/core/java/com/android/server/location/injector/Injector.java
@@ -63,4 +63,7 @@
/** Returns a LocationUsageLogger. */
LocationUsageLogger getLocationUsageLogger();
+
+ /** Returns a PackageResetHelper. */
+ PackageResetHelper getPackageResetHelper();
}
diff --git a/services/core/java/com/android/server/location/injector/PackageResetHelper.java b/services/core/java/com/android/server/location/injector/PackageResetHelper.java
new file mode 100644
index 0000000..721c576
--- /dev/null
+++ b/services/core/java/com/android/server/location/injector/PackageResetHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.location.injector;
+
+import static com.android.server.location.LocationManagerService.D;
+import static com.android.server.location.LocationManagerService.TAG;
+
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/** Helpers for tracking queries and resets of package state. */
+public abstract class PackageResetHelper {
+
+ /** Interface for responding to reset events. */
+ public interface Responder {
+
+ /**
+ * Called when a package's runtime state is being reset for whatever reason and any
+ * components carrying runtime state on behalf of the package should clear that state.
+ *
+ * @param packageName The name of the package.
+ */
+ void onPackageReset(String packageName);
+
+ /**
+ * Called when the system queries whether this package has any active state for the given
+ * package. Should return true if the component has some runtime state that is resetable of
+ * behalf of the given package, and false otherwise.
+ *
+ * @param packageName The name of the package.
+ * @return True if this component has resetable state for the given package.
+ */
+ boolean isResetableForPackage(String packageName);
+ }
+
+ private final CopyOnWriteArrayList<Responder> mResponders;
+
+ public PackageResetHelper() {
+ mResponders = new CopyOnWriteArrayList<>();
+ }
+
+ /** Begin listening for package reset events. */
+ public synchronized void register(Responder responder) {
+ boolean empty = mResponders.isEmpty();
+ mResponders.add(responder);
+ if (empty) {
+ onRegister();
+ }
+ }
+
+ /** Stop listening for package reset events. */
+ public synchronized void unregister(Responder responder) {
+ mResponders.remove(responder);
+ if (mResponders.isEmpty()) {
+ onUnregister();
+ }
+ }
+
+ @GuardedBy("this")
+ protected abstract void onRegister();
+
+ @GuardedBy("this")
+ protected abstract void onUnregister();
+
+ protected final void notifyPackageReset(String packageName) {
+ if (D) {
+ Log.d(TAG, "package " + packageName + " reset");
+ }
+
+ for (Responder responder : mResponders) {
+ responder.onPackageReset(packageName);
+ }
+ }
+
+ protected final boolean queryResetableForPackage(String packageName) {
+ for (Responder responder : mResponders) {
+ if (responder.isResetableForPackage(packageName)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/services/core/java/com/android/server/location/injector/SystemPackageResetHelper.java b/services/core/java/com/android/server/location/injector/SystemPackageResetHelper.java
new file mode 100644
index 0000000..91b0212
--- /dev/null
+++ b/services/core/java/com/android/server/location/injector/SystemPackageResetHelper.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.location.injector;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+
+import com.android.internal.util.Preconditions;
+
+/** Listens to appropriate broadcasts for queries and resets. */
+public class SystemPackageResetHelper extends PackageResetHelper {
+
+ private final Context mContext;
+
+ @Nullable
+ private BroadcastReceiver mReceiver;
+
+ public SystemPackageResetHelper(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ protected void onRegister() {
+ Preconditions.checkState(mReceiver == null);
+ mReceiver = new Receiver();
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+ filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+ filter.addDataScheme("package");
+
+ // We don't filter for Intent.ACTION_PACKAGE_DATA_CLEARED as 1) it refers to persistent
+ // data, and 2) it should always be preceded by Intent.ACTION_PACKAGE_RESTARTED, which
+ // refers to runtime data. in this way we also avoid redundant callbacks.
+
+ mContext.registerReceiver(mReceiver, filter);
+ }
+
+ @Override
+ protected void onUnregister() {
+ Preconditions.checkState(mReceiver != null);
+ mContext.unregisterReceiver(mReceiver);
+ mReceiver = null;
+ }
+
+ private class Receiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
+ Uri data = intent.getData();
+ if (data == null) {
+ return;
+ }
+
+ String packageName = data.getSchemeSpecificPart();
+ if (packageName == null) {
+ return;
+ }
+
+ switch (action) {
+ case Intent.ACTION_QUERY_PACKAGE_RESTART:
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+ if (packages != null) {
+ // it would be more efficient to pass through the whole array, but at the
+ // moment the array is always size 1, and this makes for a nicer callback.
+ for (String pkg : packages) {
+ if (queryResetableForPackage(pkg)) {
+ setResultCode(Activity.RESULT_OK);
+ break;
+ }
+ }
+ }
+ break;
+ case Intent.ACTION_PACKAGE_CHANGED:
+ // make sure this is an enabled/disabled change to the package as a whole, not
+ // just some of its components. This avoids unnecessary work in the callback.
+ boolean isPackageChange = false;
+ String[] components = intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ if (components != null) {
+ for (String component : components) {
+ if (packageName.equals(component)) {
+ isPackageChange = true;
+ break;
+ }
+ }
+ }
+
+ if (isPackageChange) {
+ try {
+ ApplicationInfo appInfo =
+ context.getPackageManager().getApplicationInfo(packageName,
+ PackageManager.ApplicationInfoFlags.of(0));
+ if (!appInfo.enabled) {
+ notifyPackageReset(packageName);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ return;
+ }
+ }
+ break;
+ case Intent.ACTION_PACKAGE_REMOVED:
+ // fall through
+ case Intent.ACTION_PACKAGE_RESTARTED:
+ notifyPackageReset(packageName);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
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 a69a079..bd75251 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -106,6 +106,7 @@
import com.android.server.location.injector.LocationPowerSaveModeHelper;
import com.android.server.location.injector.LocationPowerSaveModeHelper.LocationPowerSaveModeChangedListener;
import com.android.server.location.injector.LocationUsageLogger;
+import com.android.server.location.injector.PackageResetHelper;
import com.android.server.location.injector.ScreenInteractiveHelper;
import com.android.server.location.injector.ScreenInteractiveHelper.ScreenInteractiveChangedListener;
import com.android.server.location.injector.SettingsHelper;
@@ -1373,6 +1374,7 @@
protected final ScreenInteractiveHelper mScreenInteractiveHelper;
protected final LocationUsageLogger mLocationUsageLogger;
protected final LocationFudger mLocationFudger;
+ private final PackageResetHelper mPackageResetHelper;
private final UserListener mUserChangedListener = this::onUserChanged;
private final LocationSettings.LocationUserSettingsListener mLocationUserSettingsListener =
@@ -1407,6 +1409,18 @@
this::onLocationPowerSaveModeChanged;
private final ScreenInteractiveChangedListener mScreenInteractiveChangedListener =
this::onScreenInteractiveChanged;
+ private final PackageResetHelper.Responder mPackageResetResponder =
+ new PackageResetHelper.Responder() {
+ @Override
+ public void onPackageReset(String packageName) {
+ LocationProviderManager.this.onPackageReset(packageName);
+ }
+
+ @Override
+ public boolean isResetableForPackage(String packageName) {
+ return LocationProviderManager.this.isResetableForPackage(packageName);
+ }
+ };
// acquiring mMultiplexerLock makes operations on mProvider atomic, but is otherwise unnecessary
protected final MockableLocationProvider mProvider;
@@ -1442,6 +1456,7 @@
mScreenInteractiveHelper = injector.getScreenInteractiveHelper();
mLocationUsageLogger = injector.getLocationUsageLogger();
mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
+ mPackageResetHelper = injector.getPackageResetHelper();
mProvider = new MockableLocationProvider(mMultiplexerLock);
@@ -1970,6 +1985,7 @@
mAppForegroundHelper.addListener(mAppForegroundChangedListener);
mLocationPowerSaveModeHelper.addListener(mLocationPowerSaveModeChangedListener);
mScreenInteractiveHelper.addListener(mScreenInteractiveChangedListener);
+ mPackageResetHelper.register(mPackageResetResponder);
}
@GuardedBy("mMultiplexerLock")
@@ -1988,6 +2004,7 @@
mAppForegroundHelper.removeListener(mAppForegroundChangedListener);
mLocationPowerSaveModeHelper.removeListener(mLocationPowerSaveModeChangedListener);
mScreenInteractiveHelper.removeListener(mScreenInteractiveChangedListener);
+ mPackageResetHelper.unregister(mPackageResetResponder);
}
@GuardedBy("mMultiplexerLock")
@@ -2391,6 +2408,27 @@
updateRegistrations(registration -> registration.onLocationPermissionsChanged(uid));
}
+ private void onPackageReset(String packageName) {
+ // invoked when a package is "force quit" - move off the main thread
+ FgThread.getExecutor().execute(
+ () ->
+ updateRegistrations(
+ registration -> {
+ if (registration.getIdentity().getPackageName().equals(
+ packageName)) {
+ registration.remove();
+ }
+
+ return false;
+ }));
+ }
+
+ private boolean isResetableForPackage(String packageName) {
+ // invoked to find out if the given package has any state that can be "force quit"
+ return findRegistration(
+ registration -> registration.getIdentity().getPackageName().equals(packageName));
+ }
+
@GuardedBy("mMultiplexerLock")
@Override
public void onStateChanged(
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakePackageResetHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakePackageResetHelper.java
new file mode 100644
index 0000000..c2768d51
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakePackageResetHelper.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.location.injector;
+
+/** Version of PackageResetHelper for testing. */
+public class FakePackageResetHelper extends PackageResetHelper {
+
+ public FakePackageResetHelper() {}
+
+ @Override
+ protected void onRegister() {}
+
+ @Override
+ protected void onUnregister() {}
+
+ public boolean isResetableForPackage(String packageName) {
+ return queryResetableForPackage(packageName);
+ }
+
+ public void reset(String packageName) {
+ notifyPackageReset(packageName);
+ }
+}
+
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/TestInjector.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/TestInjector.java
index 02cacb7..ca73091 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/TestInjector.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/TestInjector.java
@@ -35,6 +35,7 @@
private final FakeDeviceIdleHelper mDeviceIdleHelper;
private final FakeEmergencyHelper mEmergencyHelper;
private final LocationUsageLogger mLocationUsageLogger;
+ private final FakePackageResetHelper mPackageResetHelper;
public TestInjector(Context context) {
mUserInfoHelper = new FakeUserInfoHelper();
@@ -50,6 +51,7 @@
mDeviceIdleHelper = new FakeDeviceIdleHelper();
mEmergencyHelper = new FakeEmergencyHelper();
mLocationUsageLogger = new LocationUsageLogger();
+ mPackageResetHelper = new FakePackageResetHelper();
}
@Override
@@ -116,4 +118,9 @@
public LocationUsageLogger getLocationUsageLogger() {
return mLocationUsageLogger;
}
+
+ @Override
+ public FakePackageResetHelper getPackageResetHelper() {
+ return mPackageResetHelper;
+ }
}
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 0ac1443..20e4e80 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
@@ -1218,6 +1218,44 @@
assertThat(mProvider.getRequest().isActive()).isFalse();
}
+ @Test
+ public void testQueryPackageReset() {
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isFalse();
+
+ ILocationListener listener1 = createMockLocationListener();
+ mManager.registerLocationRequest(new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build(), IDENTITY, PERMISSION_FINE, listener1);
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isTrue();
+
+ ILocationListener listener2 = createMockLocationListener();
+ mManager.registerLocationRequest(new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build(), IDENTITY, PERMISSION_FINE, listener2);
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isTrue();
+
+ mManager.unregisterLocationRequest(listener1);
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isTrue();
+
+ mManager.unregisterLocationRequest(listener2);
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isFalse();
+ }
+
+ @Test
+ public void testPackageReset() {
+ ILocationListener listener1 = createMockLocationListener();
+ mManager.registerLocationRequest(new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build(), IDENTITY, PERMISSION_FINE, listener1);
+ ILocationListener listener2 = createMockLocationListener();
+ mManager.registerLocationRequest(new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build(), IDENTITY, PERMISSION_FINE, listener2);
+
+ assertThat(mProvider.getRequest().isActive()).isTrue();
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isTrue();
+
+ mInjector.getPackageResetHelper().reset("mypackage");
+ assertThat(mProvider.getRequest().isActive()).isFalse();
+ assertThat(mInjector.getPackageResetHelper().isResetableForPackage("mypackage")).isFalse();
+ }
+
private ILocationListener createMockLocationListener() {
return spy(new ILocationListener.Stub() {
@Override