Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57f1c75d authored by Terry Wang's avatar Terry Wang
Browse files

Support platform AppSearchManager(backend) to accept database name.

This change also add namespace for getByUri and deleteByUri in AppSearchManagerService

Bug: 170285774
Test: AppSearchManagerTest
Change-Id: I8044fc5f22dbd03b2d73f85806659e12d75d8afa
parent 07e62587
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -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);
        }
+28 −5
Original line number Diff line number Diff line
@@ -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}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -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}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;&gt;.
@@ -64,16 +71,22 @@ interface IAppSearchManager {
     *     {@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;
     *     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}&lt;{@link AppSearchResult}&lt;{@link SearchResults}&gt;&gt;
     */
    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}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -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}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -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}&lt;{@link AppSearchResult}&lt;{@link Void}&gt;&gt;.
     *     Will be completed with the result of the call.
     */
    void deleteAll(in AndroidFuture<AppSearchResult> callback);
    void deleteAll(in String databaseName, in AndroidFuture<AppSearchResult> callback);
}
+22 −16
Original line number Diff line number Diff line
@@ -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(