Handle user stopping in AppSearch.

When a user stops, we can close its AppSearchImpl instance to release
resources. We'll also remove it from our cache of unlocked users so
future API calls won't execute on a locked user.

Bug: 179407490
Test: atest --rebuild-module-info CtsAppSearchHostTestCases
Change-Id: I09953d32ad4aaf2989386e99c93623b58d564c27
This commit is contained in:
Terry Wang
2021-04-28 19:45:07 -07:00
parent e8ce892093
commit 9a950ce716
3 changed files with 46 additions and 3 deletions

View File

@@ -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.");

View File

@@ -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.
*
* <p>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.
*

View File

@@ -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<AppSearchSessionShim> createSearchSession(
@NonNull AppSearchManager.SearchContext searchContext) {
return createSearchSession(searchContext, Executors.newCachedThreadPool());
Context context = ApplicationProvider.getApplicationContext();
return createSearchSession(context, searchContext, Executors.newCachedThreadPool());
}
/** Creates the SearchSession with given ExecutorService. */
/** Creates the SearchSessionShim with given SearchContext for the given user. */
@NonNull
public static ListenableFuture<AppSearchSessionShim> createSearchSession(
@NonNull AppSearchManager.SearchContext searchContext, @UserIdInt int userId) {
Context context = ApplicationProvider.getApplicationContext()
.createContextAsUser(new UserHandle(userId), /*flags=*/ 0);
return createSearchSession(context, searchContext, Executors.newCachedThreadPool());
}
/** Creates the SearchSession with given Context and ExecutorService. */
@NonNull
public static ListenableFuture<AppSearchSessionShim> createSearchSession(
@NonNull Context context,
@NonNull AppSearchManager.SearchContext searchContext,
@NonNull ExecutorService executor) {
Context context = ApplicationProvider.getApplicationContext();
AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
SettableFuture<AppSearchResult<AppSearchSession>> future = SettableFuture.create();
appSearchManager.createSearchSession(searchContext, executor, future::set);