From bcb007a9e1c5e62e71d7f170e7d740e82f4e7f80 Mon Sep 17 00:00:00 2001 From: Terry Wang Date: Mon, 30 Nov 2020 04:47:19 -0800 Subject: [PATCH] Support Multi-User AppSearch within SystemServer Bug: 173553485 Test: presubmit Change-Id: Id296ef9b309d6c7f46f2c78712f5951181c7c7ab --- .../app/appsearch/AppSearchManager.java | 16 +++- .../AppSearchManagerFrameworkInitializer.java | 5 +- .../app/appsearch/AppSearchSession.java | 25 ++++-- .../app/appsearch/GlobalSearchSession.java | 13 +++- .../app/appsearch/IAppSearchManager.aidl | 26 ++++++- .../android/app/appsearch/SearchResults.java | 27 ++++--- .../appsearch/AppSearchManagerService.java | 78 ++++++++++++------- 7 files changed, 130 insertions(+), 60 deletions(-) diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index c82119d14670d..4efc0abd62910 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -51,9 +51,11 @@ public class AppSearchManager { public static final String DEFAULT_DATABASE_NAME = ""; private final IAppSearchManager mService; + private final Context mContext; /** @hide */ - public AppSearchManager(@NonNull IAppSearchManager service) { + public AppSearchManager(@NonNull Context context, @NonNull IAppSearchManager service) { + mContext = Objects.requireNonNull(context); mService = Objects.requireNonNull(service); } @@ -137,7 +139,8 @@ public class AppSearchManager { Objects.requireNonNull(searchContext); Objects.requireNonNull(executor); Objects.requireNonNull(callback); - AppSearchSession.createSearchSession(searchContext, mService, executor, callback); + AppSearchSession.createSearchSession( + searchContext, mService, mContext.getUserId(), executor, callback); } /** @@ -158,7 +161,8 @@ public class AppSearchManager { @NonNull Consumer> callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); - GlobalSearchSession.createGlobalSearchSession(mService, executor, callback); + GlobalSearchSession.createGlobalSearchSession( + mService, mContext.getUserId(), executor, callback); } /** @@ -231,6 +235,7 @@ public class AppSearchManager { schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), + mContext.getUserId(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { future.complete(result); @@ -271,7 +276,7 @@ public class AppSearchManager { } AndroidFuture future = new AndroidFuture<>(); try { - mService.putDocuments(DEFAULT_DATABASE_NAME, documentBundles, + mService.putDocuments(DEFAULT_DATABASE_NAME, documentBundles, mContext.getUserId(), new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { future.complete(result); @@ -312,6 +317,7 @@ public class AppSearchManager { AndroidFuture future = new AndroidFuture<>(); try { mService.getDocuments(DEFAULT_DATABASE_NAME, request.getNamespace(), uris, + mContext.getUserId(), new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { future.complete(result); @@ -412,6 +418,7 @@ public class AppSearchManager { AndroidFuture future = new AndroidFuture<>(); try { mService.query(DEFAULT_DATABASE_NAME, queryExpression, searchSpec.getBundle(), + mContext.getUserId(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { future.complete(result); @@ -453,6 +460,7 @@ public class AppSearchManager { AndroidFuture future = new AndroidFuture<>(); try { mService.removeByUri(DEFAULT_DATABASE_NAME, request.getNamespace(), uris, + mContext.getUserId(), new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { future.complete(result); diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java index 02cc967e7daf8..ec0533e143913 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java @@ -36,8 +36,9 @@ public class AppSearchManagerFrameworkInitializer { * {@link SystemServiceRegistry} */ public static void initialize() { - SystemServiceRegistry.registerStaticService( + SystemServiceRegistry.registerContextAwareService( Context.APP_SEARCH_SERVICE, AppSearchManager.class, - (service) -> new AppSearchManager(IAppSearchManager.Stub.asInterface(service))); + (context, service) -> + new AppSearchManager(context, IAppSearchManager.Stub.asInterface(service))); } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java index 3e813eab6f04b..2f3deddae638c 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -18,6 +18,7 @@ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.os.Bundle; import android.os.ParcelableException; import android.os.RemoteException; @@ -39,15 +40,18 @@ import java.util.function.Consumer; */ public final class AppSearchSession { private final String mDatabaseName; + @UserIdInt + private final int mUserId; private final IAppSearchManager mService; static void createSearchSession( @NonNull AppSearchManager.SearchContext searchContext, @NonNull IAppSearchManager service, + @UserIdInt int userId, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer> callback) { AppSearchSession searchSession = - new AppSearchSession(searchContext.mDatabaseName, service); + new AppSearchSession(service, userId, searchContext.mDatabaseName); searchSession.initialize(executor, callback); } @@ -57,7 +61,7 @@ public final class AppSearchSession { @NonNull @CallbackExecutor Executor executor, @NonNull Consumer> callback) { try { - mService.initialize(new IAppSearchResultCallback.Stub() { + mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> { if (result.isSuccess()) { @@ -74,9 +78,11 @@ public final class AppSearchSession { } } - private AppSearchSession(@NonNull String databaseName, @NonNull IAppSearchManager service) { + private AppSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId, + @NonNull String databaseName) { mDatabaseName = databaseName; mService = service; + mUserId = userId; } /** @@ -154,6 +160,7 @@ public final class AppSearchSession { schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), + mUserId, new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> callback.accept(result)); @@ -178,6 +185,7 @@ public final class AppSearchSession { try { mService.getSchema( mDatabaseName, + mUserId, new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> { @@ -230,7 +238,7 @@ public final class AppSearchSession { documentBundles.add(documents.get(i).getBundle()); } try { - mService.putDocuments(mDatabaseName, documentBundles, + mService.putDocuments(mDatabaseName, documentBundles, mUserId, new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { executor.execute(() -> callback.onResult(result)); @@ -269,7 +277,7 @@ public final class AppSearchSession { Objects.requireNonNull(callback); try { mService.getDocuments(mDatabaseName, request.getNamespace(), - new ArrayList<>(request.getUris()), + new ArrayList<>(request.getUris()), mUserId, new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { executor.execute(() -> { @@ -371,7 +379,8 @@ public final class AppSearchSession { Objects.requireNonNull(queryExpression); Objects.requireNonNull(searchSpec); Objects.requireNonNull(executor); - return new SearchResults(mService, mDatabaseName, queryExpression, searchSpec, executor); + return new SearchResults(mService, mDatabaseName, queryExpression, searchSpec, mUserId, + executor); } /** @@ -397,7 +406,7 @@ public final class AppSearchSession { Objects.requireNonNull(callback); try { mService.removeByUri(mDatabaseName, request.getNamespace(), - new ArrayList<>(request.getUris()), + new ArrayList<>(request.getUris()), mUserId, new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { executor.execute(() -> callback.onResult(result)); @@ -440,7 +449,7 @@ public final class AppSearchSession { Objects.requireNonNull(executor); Objects.requireNonNull(callback); try { - mService.removeByQuery(mDatabaseName, queryExpression, searchSpec.getBundle(), + mService.removeByQuery(mDatabaseName, queryExpression, searchSpec.getBundle(), mUserId, new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> callback.accept(result)); diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java index 1c56a9b643e7e..95f7d796d007a 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java @@ -20,6 +20,7 @@ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.UserIdInt; import android.os.RemoteException; import java.util.Objects; @@ -36,12 +37,15 @@ import java.util.function.Consumer; public class GlobalSearchSession { private final IAppSearchManager mService; + @UserIdInt + private final int mUserId; static void createGlobalSearchSession( @NonNull IAppSearchManager service, + @UserIdInt int userId, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer> callback) { - GlobalSearchSession globalSearchSession = new GlobalSearchSession(service); + GlobalSearchSession globalSearchSession = new GlobalSearchSession(service, userId); globalSearchSession.initialize(executor, callback); } @@ -51,7 +55,7 @@ public class GlobalSearchSession { @NonNull @CallbackExecutor Executor executor, @NonNull Consumer> callback) { try { - mService.initialize(new IAppSearchResultCallback.Stub() { + mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> { if (result.isSuccess()) { @@ -68,8 +72,9 @@ public class GlobalSearchSession { } } - private GlobalSearchSession(@NonNull IAppSearchManager service) { + private GlobalSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId) { mService = service; + mUserId = userId; } /** @@ -125,6 +130,6 @@ public class GlobalSearchSession { Objects.requireNonNull(searchSpec); Objects.requireNonNull(executor); return new SearchResults(mService, /*databaseName=*/null, queryExpression, - searchSpec, executor); + searchSpec, mUserId, executor); } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index 7883046f258ed..c1c8047db7360 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -36,6 +36,7 @@ interface IAppSearchManager { * surfaces. * @param forceOverride Whether to apply the new schema even if it is incompatible. All * incompatible documents will be deleted. + * @param userId Id of the calling user * @param callback {@link IAppSearchResultCallback#onResult} will be called with an * {@link AppSearchResult}<{@link Void}>. */ @@ -44,6 +45,7 @@ interface IAppSearchManager { in List schemaBundles, in List schemasNotPlatformSurfaceable, boolean forceOverride, + in int userId, in IAppSearchResultCallback callback); @@ -51,17 +53,19 @@ interface IAppSearchManager { * Retrieves the AppSearch schema for this database. * * @param databaseName The name of the database to retrieve. + * @param userId Id of the calling user * @param callback {@link IAppSearchResultCallback#onResult} will be called with an * {@link AppSearchResult}<{@link List}<{@link Bundle}>>, where the value are * AppSearchSchema bundle. */ - void getSchema(in String databaseName, in IAppSearchResultCallback callback); + void getSchema(in String databaseName, in int userId, in IAppSearchResultCallback callback); /** * Inserts documents into the index. * * @param databaseName The name of the database where this document lives. * @param documentBundes List of GenericDocument bundles. + * @param userId Id of the calling user * @param callback * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} * will be called with the cause throwable. Otherwise, @@ -72,6 +76,7 @@ interface IAppSearchManager { void putDocuments( in String databaseName, in List documentBundles, + in int userId, in IAppSearchBatchResultCallback callback); /** @@ -80,6 +85,7 @@ interface IAppSearchManager { * @param databaseName The databaseName this document resides in. * @param namespace The namespace this document resides in. * @param uris The URIs of the documents to retrieve + * @param userId Id of the calling user * @param callback * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} * will be called with the cause throwable. Otherwise, @@ -91,6 +97,7 @@ interface IAppSearchManager { in String databaseName, in String namespace, in List uris, + in int userId, in IAppSearchBatchResultCallback callback); /** @@ -99,6 +106,7 @@ interface IAppSearchManager { * @param databaseName The databaseName this query for. * @param queryExpression String to search for * @param searchSpecBundle SearchSpec bundle + * @param userId Id of the calling user * @param callback {@link AppSearchResult}<{@link Bundle}> of performing this * operation. */ @@ -106,6 +114,7 @@ interface IAppSearchManager { in String databaseName, in String queryExpression, in Bundle searchSpecBundle, + in int userId, in IAppSearchResultCallback callback); /** @@ -114,12 +123,14 @@ interface IAppSearchManager { * * @param queryExpression String to search for * @param searchSpecBundle SearchSpec bundle + * @param userId Id of the calling user * @param callback {@link AppSearchResult}<{@link Bundle}> of performing this * operation. */ void globalQuery( in String queryExpression, in Bundle searchSpecBundle, + in int userId, in IAppSearchResultCallback callback); /** @@ -127,18 +138,20 @@ interface IAppSearchManager { * next-page token is invalid or all pages have been returned. * * @param nextPageToken The token of pre-loaded results of previously executed query. + * @param userId Id of the calling user * @param callback {@link AppSearchResult}<{@link Bundle}> of performing this * operation. */ - void getNextPage(in long nextPageToken, in IAppSearchResultCallback callback); + void getNextPage(in long nextPageToken, in int userId, in IAppSearchResultCallback callback); /** * Invalidates the next-page token so that no more results of the related query can be returned. * * @param nextPageToken The token of pre-loaded results of previously executed query to be * Invalidated. + * @param userId Id of the calling user */ - void invalidateNextPageToken(in long nextPageToken); + void invalidateNextPageToken(in long nextPageToken, in int userId); /** * Removes documents by URI. @@ -146,6 +159,7 @@ interface IAppSearchManager { * @param databaseName The databaseName the document is in. * @param namespace Namespace of the document to remove. * @param uris The URIs of the documents to delete + * @param userId Id of the calling user * @param callback * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} * will be called with the cause throwable. Otherwise, @@ -158,6 +172,7 @@ interface IAppSearchManager { in String databaseName, in String namespace, in List uris, + in int userId, in IAppSearchBatchResultCallback callback); /** @@ -166,6 +181,7 @@ interface IAppSearchManager { * @param databaseName The databaseName this query for. * @param queryExpression String to search for * @param searchSpecBundle SearchSpec bundle + * @param userId Id of the calling user * @param callback {@link IAppSearchResultCallback#onResult} will be called with an * {@link AppSearchResult}<{@link Void}>. */ @@ -173,13 +189,15 @@ interface IAppSearchManager { in String databaseName, in String queryExpression, in Bundle searchSpecBundle, + in int userId, in IAppSearchResultCallback callback); /** * Creates and initializes AppSearchImpl for the calling app. * + * @param userId Id of the calling user * @param callback {@link IAppSearchResultCallback#onResult} will be called with an * {@link AppSearchResult}<{@link Void}>. */ - void initialize(in IAppSearchResultCallback callback); + void initialize(in int userId, in IAppSearchResultCallback callback); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java index 7dc13b4102263..05735cc59d931 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java @@ -19,14 +19,14 @@ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; -import com.android.internal.util.Preconditions; - import java.io.Closeable; import java.util.List; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -48,6 +48,9 @@ public class SearchResults implements Closeable { @Nullable private final String mDatabaseName; + @UserIdInt + private final int mUserId; + private final String mQueryExpression; private final SearchSpec mSearchSpec; @@ -62,12 +65,14 @@ public class SearchResults implements Closeable { @Nullable String databaseName, @NonNull String queryExpression, @NonNull SearchSpec searchSpec, + @UserIdInt int userId, @NonNull @CallbackExecutor Executor executor) { - mService = Preconditions.checkNotNull(service); - mExecutor = Preconditions.checkNotNull(executor); - mDatabaseName = databaseName; - mQueryExpression = Preconditions.checkNotNull(queryExpression); - mSearchSpec = Preconditions.checkNotNull(searchSpec); + mService = Objects.requireNonNull(service); + mUserId = userId; + mDatabaseName = Objects.requireNonNull(databaseName); + mQueryExpression = Objects.requireNonNull(queryExpression); + mSearchSpec = Objects.requireNonNull(searchSpec); + mExecutor = Objects.requireNonNull(executor); } /** @@ -85,14 +90,14 @@ public class SearchResults implements Closeable { if (mIsFirstLoad) { mIsFirstLoad = false; if (mDatabaseName == null) { - mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), + mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); } else { mService.query(mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), - wrapCallback(callback)); + mUserId, wrapCallback(callback)); } } else { - mService.getNextPage(mNextPageToken, wrapCallback(callback)); + mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback)); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -119,7 +124,7 @@ public class SearchResults implements Closeable { public void close() { mExecutor.execute(() -> { try { - mService.invalidateNextPageToken(mNextPageToken); + mService.invalidateNextPageToken(mNextPageToken, mUserId); } catch (RemoteException e) { Log.d(TAG, "Unable to close the SearchResults", e); } 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 d81b79414359d..8cf1ca0927d96 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -18,6 +18,8 @@ package com.android.server.appsearch; import static android.app.appsearch.AppSearchResult.throwableToFailedResult; import android.annotation.NonNull; +import android.annotation.UserIdInt; +import android.app.ActivityManager; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; @@ -32,7 +34,6 @@ import android.os.Binder; import android.os.Bundle; import android.os.ParcelableException; import android.os.RemoteException; -import android.os.UserHandle; import android.util.Log; import com.android.internal.util.Preconditions; @@ -64,12 +65,13 @@ public class AppSearchManagerService extends SystemService { @NonNull List schemaBundles, @NonNull List schemasNotPlatformSurfaceable, boolean forceOverride, + @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(schemaBundles); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { List schemas = new ArrayList<>(schemaBundles.size()); @@ -92,11 +94,12 @@ public class AppSearchManagerService extends SystemService { @Override public void getSchema( @NonNull String databaseName, + @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -119,12 +122,13 @@ public class AppSearchManagerService extends SystemService { public void putDocuments( @NonNull String databaseName, @NonNull List documentBundles, + @UserIdInt int userId, @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(documentBundles); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchBatchResult.Builder resultBuilder = @@ -151,15 +155,18 @@ public class AppSearchManagerService extends SystemService { } @Override - public void getDocuments(@NonNull String databaseName, @NonNull String namespace, + public void getDocuments( + @NonNull String databaseName, + @NonNull String namespace, @NonNull List uris, + @UserIdInt int userId, @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(uris); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchBatchResult.Builder resultBuilder = @@ -190,13 +197,14 @@ public class AppSearchManagerService extends SystemService { @NonNull String databaseName, @NonNull String queryExpression, @NonNull Bundle searchSpecBundle, + @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(queryExpression); Preconditions.checkNotNull(searchSpecBundle); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -215,15 +223,17 @@ public class AppSearchManagerService extends SystemService { } } + @Override public void globalQuery( @NonNull String queryExpression, @NonNull Bundle searchSpecBundle, + @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(queryExpression); Preconditions.checkNotNull(searchSpecBundle); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -240,11 +250,11 @@ public class AppSearchManagerService extends SystemService { } @Override - public void getNextPage(long nextPageToken, + public void getNextPage(long nextPageToken, @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally // opened it @@ -261,9 +271,9 @@ public class AppSearchManagerService extends SystemService { } @Override - public void invalidateNextPageToken(long nextPageToken) { - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) { + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -276,14 +286,17 @@ public class AppSearchManagerService extends SystemService { } @Override - public void removeByUri(@NonNull String databaseName, @NonNull String namespace, + public void removeByUri( + @NonNull String databaseName, + @NonNull String namespace, @NonNull List uris, + @UserIdInt int userId, @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(uris); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchBatchResult.Builder resultBuilder = @@ -312,13 +325,14 @@ public class AppSearchManagerService extends SystemService { @NonNull String databaseName, @NonNull String queryExpression, @NonNull Bundle searchSpecBundle, + @UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(queryExpression); Preconditions.checkNotNull(searchSpecBundle); Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -334,10 +348,10 @@ public class AppSearchManagerService extends SystemService { } @Override - public void initialize(@NonNull IAppSearchResultCallback callback) { + public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(callback); - int callingUid = Binder.getCallingUidOrThrow(); - int callingUserId = UserHandle.getUserId(callingUid); + int callingUid = Binder.getCallingUid(); + int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { ImplInstanceManager.getInstance(getContext(), callingUserId); @@ -415,4 +429,14 @@ public class AppSearchManagerService extends SystemService { } } } + + //TODO(b/173553485) verifying that the caller has permission to access target user's data + //TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast + //TODO(b/173553485) Implement SystemService.onUserStopping() + private static int handleIncomingUser(@UserIdInt int userId, int callingUid) { + int callingPid = Binder.getCallingPid(); + return ActivityManager.handleIncomingUser(callingPid, callingUid, userId, + /*allowAll=*/ false, /*requireFull=*/ false, + /*name=*/ null, /*callerPackage=*/ null); + } }