diff options
3 files changed, 60 insertions, 29 deletions
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index 67fa6c89ad4a..18bc59b91aa0 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -40,6 +40,7 @@ import java.util.concurrent.ExecutionException; // TODO(b/148046169): This class header needs a detailed example/tutorial. @SystemService(Context.APP_SEARCH_SERVICE) public class AppSearchManager { + private static final String DEFAULT_DATABASE = ""; private final IAppSearchManager mService; /** @hide */ @@ -112,7 +113,7 @@ public class AppSearchManager { } AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { - mService.setSchema(schemaBundles, request.isForceOverride(), future); + mService.setSchema(DEFAULT_DATABASE, schemaBundles, request.isForceOverride(), future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -145,7 +146,7 @@ public class AppSearchManager { } AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.putDocuments(documentBundles, future); + mService.putDocuments(DEFAULT_DATABASE, documentBundles, future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -172,7 +173,7 @@ public class AppSearchManager { List<String> uris = new ArrayList<>(request.getUris()); AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.getDocuments(uris, future); + mService.getDocuments(DEFAULT_DATABASE, request.getNamespace(), uris, future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -260,7 +261,8 @@ public class AppSearchManager { // them in one big list. AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>(); try { - mService.query(queryExpression, searchSpec.getBundle(), searchResultsFuture); + mService.query(DEFAULT_DATABASE, queryExpression, + searchSpec.getBundle(), searchResultsFuture); } catch (RemoteException e) { searchResultsFuture.completeExceptionally(e); } @@ -292,7 +294,7 @@ public class AppSearchManager { List<String> uris = new ArrayList<>(request.getUris()); AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.delete(uris, future); + mService.delete(DEFAULT_DATABASE, request.getNamespace(), uris, future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -300,7 +302,7 @@ public class AppSearchManager { } /** - * Deletes {@link android.app.appsearch.AppSearch.Document}s by schema type. + * Deletes {@link android.app.appsearch.GenericDocument}s by schema type. * * <p>You should not call this method directly; instead, use the * {@code AppSearch#deleteByType()} API provided by JetPack. @@ -313,7 +315,7 @@ public class AppSearchManager { public AppSearchBatchResult<String, Void> deleteByTypes(@NonNull List<String> schemaTypes) { AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.deleteByTypes(schemaTypes, future); + mService.deleteByTypes(DEFAULT_DATABASE, schemaTypes, future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -324,7 +326,7 @@ public class AppSearchManager { public AppSearchResult<Void> deleteAll() { AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { - mService.deleteAll(future); + mService.deleteAll(DEFAULT_DATABASE, future); } catch (RemoteException e) { future.completeExceptionally(e); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index 8e18346ffece..352a980eef27 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -28,6 +28,7 @@ interface IAppSearchManager { /** * Sets the schema. * + * @param databaseName The databaseName this document resides in. * @param schemaBundles List of AppSearchSchema bundles. * @param forceOverride Whether to apply the new schema even if it is incompatible. All * incompatible documents will be deleted. @@ -35,6 +36,7 @@ interface IAppSearchManager { * The results of the call. */ void setSchema( + in String databaseName, in List<Bundle> schemaBundles, boolean forceOverride, in AndroidFuture<AppSearchResult> callback); @@ -42,6 +44,7 @@ interface IAppSearchManager { /** * Inserts documents into the index. * + * @param databaseName The name of the database where this document lives. * @param documentBundes List of GenericDocument bundles. * @param callback * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Void}>>. @@ -51,11 +54,15 @@ interface IAppSearchManager { * where the keys are document URIs, and the values are {@code null}. */ void putDocuments( - in List<Bundle> documentBundles, in AndroidFuture<AppSearchBatchResult> callback); + in String databaseName, + in List<Bundle> documentBundles, + in AndroidFuture<AppSearchBatchResult> callback); /** * Retrieves documents from the index. * + * @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 callback * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Bundle}>>. @@ -64,16 +71,22 @@ interface IAppSearchManager { * {@link AppSearchBatchResult}<{@link String}, {@link Bundle}> * where the keys are document URIs, and the values are Document bundles. */ - void getDocuments(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback); + void getDocuments( + in String databaseName, + in String namespace, + in List<String> uris, + in AndroidFuture<AppSearchBatchResult> callback); /** * Searches a document based on a given specifications. * + * @param databaseName The databaseName this query for. * @param queryExpression String to search for * @param searchSpecBundle SearchSpec bundle * @param callback {@link AndroidFuture}<{@link AppSearchResult}<{@link SearchResults}>> */ void query( + in String databaseName, in String queryExpression, in Bundle searchSpecBundle, in AndroidFuture<AppSearchResult> callback); @@ -81,6 +94,8 @@ interface IAppSearchManager { /** * Deletes documents by URI. * + * @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 callback * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Void}>>. @@ -90,11 +105,16 @@ interface IAppSearchManager { * where the keys are document URIs. If a document doesn't exist, it will be reported as a * failure where the {@code throwable} is {@code null}. */ - void delete(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback); + void delete( + in String databaseName, + in String namespace, + in List<String> uris, + in AndroidFuture<AppSearchBatchResult> callback); /** * Deletes documents by schema type. * + * @param databaseName The databaseName the document is in. * @param schemaTypes The schema types of the documents to delete * @param callback * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Void}>>. @@ -105,13 +125,16 @@ interface IAppSearchManager { * failure where the {@code throwable} is {@code null}. */ void deleteByTypes( - in List<String> schemaTypes, in AndroidFuture<AppSearchBatchResult> callback); + in String databaseName, + in List<String> schemaTypes, + in AndroidFuture<AppSearchBatchResult> callback); /** * Deletes all documents belonging to the calling app. * + * @param databaseName The databaseName to remove all documents from. * @param callback {@link AndroidFuture}<{@link AppSearchResult}<{@link Void}>>. * Will be completed with the result of the call. */ - void deleteAll(in AndroidFuture<AppSearchResult> callback); + void deleteAll(in String databaseName, in AndroidFuture<AppSearchResult> callback); } 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 06612ac31f63..7cd6ee24cb20 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -53,6 +53,7 @@ import java.util.List; */ public class AppSearchManagerService extends SystemService { private static final String TAG = "AppSearchManagerService"; + private static final char CALLING_NAME_DATABASE_DELIMITER = '$'; public AppSearchManagerService(Context context) { super(context); @@ -66,6 +67,7 @@ public class AppSearchManagerService extends SystemService { private class Stub extends IAppSearchManager.Stub { @Override public void setSchema( + @NonNull String databaseName, @NonNull List<Bundle> schemaBundles, boolean forceOverride, @NonNull AndroidFuture<AppSearchResult> callback) { @@ -82,7 +84,7 @@ public class AppSearchManagerService extends SystemService { schemaProtoBuilder.addTypes(schemaTypeProto); } AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); impl.setSchema(databaseName, schemaProtoBuilder.build(), forceOverride); callback.complete(AppSearchResult.newSuccessfulResult(/*result=*/ null)); } catch (Throwable t) { @@ -94,6 +96,7 @@ public class AppSearchManagerService extends SystemService { @Override public void putDocuments( + @NonNull String databaseName, @NonNull List<Bundle> documentBundles, @NonNull AndroidFuture<AppSearchBatchResult> callback) { Preconditions.checkNotNull(documentBundles); @@ -103,7 +106,7 @@ public class AppSearchManagerService extends SystemService { final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Void> resultBuilder = new AppSearchBatchResult.Builder<>(); for (int i = 0; i < documentBundles.size(); i++) { @@ -125,7 +128,7 @@ public class AppSearchManagerService extends SystemService { } @Override - public void getDocuments( + public void getDocuments(@NonNull String databaseName, @NonNull String namespace, @NonNull List<String> uris, @NonNull AndroidFuture<AppSearchBatchResult> callback) { Preconditions.checkNotNull(uris); Preconditions.checkNotNull(callback); @@ -134,14 +137,14 @@ public class AppSearchManagerService extends SystemService { final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Bundle> resultBuilder = new AppSearchBatchResult.Builder<>(); for (int i = 0; i < uris.size(); i++) { String uri = uris.get(i); try { DocumentProto documentProto = impl.getDocument( - databaseName, GenericDocument.DEFAULT_NAMESPACE, uri); + databaseName, namespace, uri); if (documentProto == null) { resultBuilder.setFailure( uri, AppSearchResult.RESULT_NOT_FOUND, /*errorMessage=*/ null); @@ -165,6 +168,7 @@ public class AppSearchManagerService extends SystemService { // TODO(sidchhabra): Do this in a threadpool. @Override public void query( + @NonNull String databaseName, @NonNull String queryExpression, @NonNull Bundle searchSpecBundle, @NonNull AndroidFuture<AppSearchResult> callback) { @@ -181,7 +185,7 @@ public class AppSearchManagerService extends SystemService { searchSpecProto = searchSpecProto.toBuilder() .setQuery(queryExpression).build(); AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); // TODO(adorokhine): handle pagination SearchResultProto searchResultProto = impl.query( databaseName, @@ -201,7 +205,8 @@ public class AppSearchManagerService extends SystemService { } @Override - public void delete(List<String> uris, AndroidFuture<AppSearchBatchResult> callback) { + public void delete(@NonNull String databaseName, @NonNull String namespace, + List<String> uris, AndroidFuture<AppSearchBatchResult> callback) { Preconditions.checkNotNull(uris); Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); @@ -209,13 +214,13 @@ public class AppSearchManagerService extends SystemService { final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Void> resultBuilder = new AppSearchBatchResult.Builder<>(); for (int i = 0; i < uris.size(); i++) { String uri = uris.get(i); try { - impl.remove(databaseName, GenericDocument.DEFAULT_NAMESPACE, uri); + impl.remove(databaseName, namespace, uri); resultBuilder.setSuccess(uri, /*result= */null); } catch (Throwable t) { resultBuilder.setResult(uri, throwableToFailedResult(t)); @@ -230,7 +235,7 @@ public class AppSearchManagerService extends SystemService { } @Override - public void deleteByTypes( + public void deleteByTypes(@NonNull String databaseName, List<String> schemaTypes, AndroidFuture<AppSearchBatchResult> callback) { Preconditions.checkNotNull(schemaTypes); Preconditions.checkNotNull(callback); @@ -239,7 +244,7 @@ public class AppSearchManagerService extends SystemService { final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Void> resultBuilder = new AppSearchBatchResult.Builder<>(); for (int i = 0; i < schemaTypes.size(); i++) { @@ -260,14 +265,15 @@ public class AppSearchManagerService extends SystemService { } @Override - public void deleteAll(@NonNull AndroidFuture<AppSearchResult> callback) { + public void deleteAll(@NonNull String databaseName, + @NonNull AndroidFuture<AppSearchResult> callback) { Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); int callingUserId = UserHandle.getUserId(callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - String databaseName = makeDatabaseName(callingUid); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); impl.removeAll(databaseName); callback.complete(AppSearchResult.newSuccessfulResult(null)); } catch (Throwable t) { @@ -278,13 +284,13 @@ public class AppSearchManagerService extends SystemService { } /** - * Returns a unique database name for the given uid. + * Rewrites the database name by adding a prefix of unique name for the given uid. * * <p>The current implementation returns the package name of the app with this uid in a * format like {@code com.example.package} or {@code com.example.sharedname:5678}. */ @NonNull - private String makeDatabaseName(int callingUid) { + private String rewriteDatabaseNameWithUid(String databaseName, int callingUid) { // For regular apps, this call will return the package name. If callingUid is an // android:sharedUserId, this value may be another type of name and have a :uid suffix. String callingUidName = getContext().getPackageManager().getNameForUid(callingUid); @@ -293,7 +299,7 @@ public class AppSearchManagerService extends SystemService { throw new IllegalStateException( "Failed to look up package name for uid " + callingUid); } - return callingUidName; + return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName; } private <ValueType> AppSearchResult<ValueType> throwableToFailedResult( |