summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java65
1 files changed, 48 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index f25c65192066..f8d1195be7fd 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -38,6 +38,7 @@ import static com.android.server.location.LocationPermissions.PERMISSION_NONE;
import static java.lang.Math.max;
import static java.lang.Math.min;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.AlarmManager.OnAlarmListener;
import android.app.PendingIntent;
@@ -107,6 +108,8 @@ import com.android.server.location.util.UserInfoHelper;
import com.android.server.location.util.UserInfoHelper.UserListener;
import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -142,6 +145,14 @@ class LocationProviderManager extends
// will just be scheduled immediately
private static final long MIN_REQUEST_DELAY_MS = 30 * 1000;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATE_STARTED, STATE_STOPPING, STATE_STOPPED})
+ private @interface State {}
+
+ private static final int STATE_STARTED = 0;
+ private static final int STATE_STOPPING = 1;
+ private static final int STATE_STOPPED = 2;
+
protected interface LocationTransport {
void deliverOnLocationChanged(Location location, @Nullable Runnable onCompleteCallback)
@@ -1082,7 +1093,7 @@ class LocationProviderManager extends
protected final Context mContext;
@GuardedBy("mLock")
- private boolean mStarted;
+ private @State int mState;
// maps of user id to value
@GuardedBy("mLock")
@@ -1148,7 +1159,7 @@ class LocationProviderManager extends
mContext = context;
mName = Objects.requireNonNull(name);
mPassiveManager = passiveManager;
- mStarted = false;
+ mState = STATE_STOPPED;
mEnabled = new SparseBooleanArray(2);
mLastLocations = new SparseArray<>(2);
@@ -1180,7 +1191,8 @@ class LocationProviderManager extends
public void startManager() {
synchronized (mLock) {
- mStarted = true;
+ Preconditions.checkState(mState == STATE_STOPPED);
+ mState = STATE_STARTED;
mUserHelper.addListener(mUserChangedListener);
mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
@@ -1197,6 +1209,9 @@ class LocationProviderManager extends
public void stopManager() {
synchronized (mLock) {
+ Preconditions.checkState(mState == STATE_STARTED);
+ mState = STATE_STOPPING;
+
final long identity = Binder.clearCallingIdentity();
try {
onEnabledChanged(UserHandle.USER_ALL);
@@ -1205,11 +1220,19 @@ class LocationProviderManager extends
Binder.restoreCallingIdentity(identity);
}
+ setRealProvider(null);
+ setMockProvider(null);
+
mUserHelper.removeListener(mUserChangedListener);
mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
+ // if external entities are registering listeners it's their responsibility to
+ // unregister them before stopManager() is called
Preconditions.checkState(mEnabledListeners.isEmpty());
- mStarted = false;
+
+ mEnabled.clear();
+ mLastLocations.clear();
+ mState = STATE_STOPPED;
}
}
@@ -1252,21 +1275,21 @@ class LocationProviderManager extends
public void addEnabledListener(ProviderEnabledListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mEnabledListeners.add(listener);
}
}
public void removeEnabledListener(ProviderEnabledListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mEnabledListeners.remove(listener);
}
}
- public void setRealProvider(AbstractLocationProvider provider) {
+ public void setRealProvider(@Nullable AbstractLocationProvider provider) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
@@ -1279,7 +1302,7 @@ class LocationProviderManager extends
public void setMockProvider(@Nullable MockProvider provider) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mLocationEventLog.logProviderMocked(mName, provider != null);
@@ -1408,7 +1431,7 @@ class LocationProviderManager extends
Location location;
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
LastLocation lastLocation = mLastLocations.get(userId);
if (lastLocation == null) {
location = null;
@@ -1430,7 +1453,7 @@ class LocationProviderManager extends
public void injectLastLocation(Location location, int userId) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) {
setLastLocation(location, userId);
}
@@ -1478,7 +1501,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(callback.asBinder(), registration);
@@ -1520,7 +1543,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(listener.asBinder(), registration);
@@ -1539,7 +1562,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
putRegistration(pendingIntent, registration);
@@ -1551,7 +1574,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(ILocationListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(listener.asBinder());
@@ -1563,7 +1586,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(PendingIntent pendingIntent) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(pendingIntent);
@@ -1890,6 +1913,10 @@ class LocationProviderManager extends
private void onUserChanged(int userId, int change) {
synchronized (mLock) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
switch (change) {
case UserListener.CURRENT_USER_CHANGED:
updateRegistrations(
@@ -1907,6 +1934,10 @@ class LocationProviderManager extends
private void onLocationEnabledChanged(int userId) {
synchronized (mLock) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
onEnabledChanged(userId);
}
}
@@ -2105,7 +2136,7 @@ class LocationProviderManager extends
Preconditions.checkArgument(userId >= 0);
- boolean enabled = mStarted
+ boolean enabled = mState == STATE_STARTED
&& mProvider.getState().allowed
&& mSettingsHelper.isLocationEnabled(userId);