Give ServiceWatcher a proper lifecycle
ServiceWatcher currently starts working once registered and can never be
unregistered.
Test: manual
Change-Id: I3c193d0c75eafb8e1934663f8928797396b723ba
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index b78b5d9..3ccb6e5 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -185,9 +185,49 @@
private final Handler mHandler;
private final Intent mIntent;
+ private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ return true;
+ }
+
+ @Override
+ public void onSomePackagesChanged() {
+ onBestServiceChanged(false);
+ }
+ };
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId == UserHandle.USER_NULL) {
+ return;
+ }
+
+ switch (action) {
+ case Intent.ACTION_USER_SWITCHED:
+ onUserSwitched(userId);
+ break;
+ case Intent.ACTION_USER_UNLOCKED:
+ onUserUnlocked(userId);
+ break;
+ default:
+ break;
+ }
+
+ }
+ };
+
@Nullable private final OnBindRunner mOnBind;
@Nullable private final Runnable mOnUnbind;
+ // write from caller thread only, read anywhere
+ private volatile boolean mRegistered;
+
// read/write from handler thread only
private int mCurrentUserId;
@@ -225,77 +265,65 @@
}
/**
- * Register this class, which will start the process of determining the best matching service
- * and maintaining a binding to it. Will return false and fail if there are no possible matching
- * services at the time this functions is called.
+ * Returns true if there is at least one component that could satisfy the ServiceWatcher's
+ * constraints.
*/
- public boolean register() {
- if (mContext.getPackageManager().queryIntentServicesAsUser(mIntent,
+ public boolean checkServiceResolves() {
+ return !mContext.getPackageManager().queryIntentServicesAsUser(mIntent,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE | MATCH_SYSTEM_ONLY,
- UserHandle.USER_SYSTEM).isEmpty()) {
- return false;
- }
+ UserHandle.USER_SYSTEM).isEmpty();
+ }
- new PackageMonitor() {
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- return true;
- }
+ /**
+ * Starts the process of determining the best matching service and maintaining a binding to it.
+ */
+ public void register() {
+ Preconditions.checkState(!mRegistered);
- @Override
- public void onSomePackagesChanged() {
- onBestServiceChanged(false);
- }
- }.register(mContext, UserHandle.ALL, true, mHandler);
+ mPackageMonitor.register(mContext, UserHandle.ALL, true, mHandler);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action == null) {
- return;
- }
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- if (userId == UserHandle.USER_NULL) {
- return;
- }
-
- switch (action) {
- case Intent.ACTION_USER_SWITCHED:
- onUserSwitched(userId);
- break;
- case Intent.ACTION_USER_UNLOCKED:
- onUserUnlocked(userId);
- break;
- default:
- break;
- }
-
- }
- }, UserHandle.ALL, intentFilter, null, mHandler);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, intentFilter, null,
+ mHandler);
mCurrentUserId = ActivityManager.getCurrentUser();
+ mRegistered = true;
+
mHandler.post(() -> onBestServiceChanged(false));
- return true;
+ }
+
+ /**
+ * Stops the process of determining the best matching service and releases any binding.
+ */
+ public void unregister() {
+ Preconditions.checkState(mRegistered);
+
+ mRegistered = false;
+
+ mPackageMonitor.unregister();
+ mContext.unregisterReceiver(mBroadcastReceiver);
+
+ mHandler.post(() -> onBestServiceChanged(false));
}
private void onBestServiceChanged(boolean forceRebind) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
- List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser(
- mIntent,
- GET_META_DATA | MATCH_DIRECT_BOOT_AUTO | MATCH_SYSTEM_ONLY,
- mCurrentUserId);
-
ServiceInfo bestServiceInfo = ServiceInfo.NONE;
- for (ResolveInfo resolveInfo : resolveInfos) {
- ServiceInfo serviceInfo = new ServiceInfo(resolveInfo, mCurrentUserId);
- if (serviceInfo.compareTo(bestServiceInfo) > 0) {
- bestServiceInfo = serviceInfo;
+
+ if (mRegistered) {
+ List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser(
+ mIntent,
+ GET_META_DATA | MATCH_DIRECT_BOOT_AUTO | MATCH_SYSTEM_ONLY,
+ mCurrentUserId);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ServiceInfo serviceInfo = new ServiceInfo(resolveInfo, mCurrentUserId);
+ if (serviceInfo.compareTo(bestServiceInfo) > 0) {
+ bestServiceInfo = serviceInfo;
+ }
}
}
diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index 3b74d5a..3ac148d 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -60,7 +60,11 @@
}
private boolean register() {
- return mServiceWatcher.register();
+ boolean resolves = mServiceWatcher.checkServiceResolves();
+ if (resolves) {
+ mServiceWatcher.register();
+ }
+ return resolves;
}
/**
diff --git a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
index eed1aac..7b400b6 100644
--- a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
@@ -75,7 +75,11 @@
}
private boolean register() {
- return mServiceWatcher.register();
+ boolean resolves = mServiceWatcher.checkServiceResolves();
+ if (resolves) {
+ mServiceWatcher.register();
+ }
+ return resolves;
}
private void onBind(IBinder binder, ComponentName service) throws RemoteException {
diff --git a/services/core/java/com/android/server/location/ProxyLocationProvider.java b/services/core/java/com/android/server/location/ProxyLocationProvider.java
index ce9b10d..555b2d2 100644
--- a/services/core/java/com/android/server/location/ProxyLocationProvider.java
+++ b/services/core/java/com/android/server/location/ProxyLocationProvider.java
@@ -92,7 +92,11 @@
}
private boolean register() {
- return mServiceWatcher.register();
+ boolean resolves = mServiceWatcher.checkServiceResolves();
+ if (resolves) {
+ mServiceWatcher.register();
+ }
+ return resolves;
}
private void onBind(IBinder binder, ComponentName service) throws RemoteException {
diff --git a/services/core/java/com/android/server/location/geofence/GeofenceProxy.java b/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
index 686a66b..bdfa6d7 100644
--- a/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
@@ -75,16 +75,16 @@
}
private boolean register(Context context) {
- if (mServiceWatcher.register()) {
+ boolean resolves = mServiceWatcher.checkServiceResolves();
+ if (resolves) {
+ mServiceWatcher.register();
context.bindServiceAsUser(
new Intent(context, GeofenceHardwareService.class),
new GeofenceProxyServiceConnection(),
Context.BIND_AUTO_CREATE,
UserHandle.SYSTEM);
- return true;
}
-
- return false;
+ return resolves;
}
private class GeofenceProxyServiceConnection implements ServiceConnection {
diff --git a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
index 3801877..94062fa 100644
--- a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
@@ -78,10 +78,14 @@
}
private boolean register() {
- return mServiceWatcher.register();
+ boolean resolves = mServiceWatcher.checkServiceResolves();
+ if (resolves) {
+ mServiceWatcher.register();
+ }
+ return resolves;
}
- private void onBind(IBinder binder, ComponentName componentName) throws RemoteException {
+ private void onBind(IBinder binder, ComponentName componentName) {
processServiceWatcherCallbackOnThreadingDomainThread(() -> onBindOnHandlerThread(binder));
}