diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index a4188a2733b86..977b7a9425d5b 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -230,6 +230,18 @@ public class AppSearchManagerService extends SystemService { } } + @Override + public void onUserStopping(@NonNull TargetUser user) { + synchronized (mUnlockedUserIdsLocked) { + mUnlockedUserIdsLocked.remove(user.getUserIdentifier()); + try { + mImplInstanceManager.closeAndRemoveAppSearchImplForUser(user.getUserIdentifier()); + } catch (Throwable t) { + Log.e(TAG, "Error handling user stopping.", t); + } + } + } + private void verifyUserUnlocked(int callingUserId) { if (isUserLocked(callingUserId)) { throw new IllegalStateException("User " + callingUserId + " is locked or not running."); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java index 94ee830f8e742..b815de48569f8 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java @@ -117,10 +117,28 @@ public final class ImplInstanceManager { */ public void removeAppSearchImplForUser(@UserIdInt int userId) { synchronized (mInstancesLocked) { + // no need to close and persist data to disk since we are removing them now. mInstancesLocked.remove(userId); } } + /** + * Close and remove an instance of {@link AppSearchImpl} for the given user. + * + *
All mutation apply to this {@link AppSearchImpl} will be persisted to disk.
+ *
+ * @param userId The multi-user userId of the user that need to be removed.
+ */
+ public void closeAndRemoveAppSearchImplForUser(@UserIdInt int userId) {
+ synchronized (mInstancesLocked) {
+ AppSearchImpl appSearchImpl = mInstancesLocked.get(userId);
+ if (appSearchImpl != null) {
+ appSearchImpl.close();
+ mInstancesLocked.remove(userId);
+ }
+ }
+ }
+
/**
* Gets an instance of AppSearchImpl for the given user.
*
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
index 941cea9bc97a9..71b4f36a71279 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
@@ -17,6 +17,7 @@
package com.android.server.appsearch.testing;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchResult;
@@ -37,6 +38,7 @@ import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.StorageInfo;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
+import android.os.UserHandle;
import androidx.test.core.app.ApplicationProvider;
@@ -58,18 +60,29 @@ public class AppSearchSessionShimImpl implements AppSearchSessionShim {
private final AppSearchSession mAppSearchSession;
private final ExecutorService mExecutor;
+ /** Creates the SearchSessionShim with given SearchContext. */
@NonNull
public static ListenableFuture