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

Commit a2f580f7 authored by Terry Wang's avatar Terry Wang
Browse files

Pull upstream changes from AndroidX.

Changes included:
#287105e: Refactor SearchResultPage out of localstorage to its
          own class.
#c89cdd0: Delete LocalBackendSyncImpl.
#4ac0d9d: Create GlobalAppSearchManager for global query.
#87c01a9: Replace AppSearch removeByNamespace, removeBySchemaType
          and removeAll by removeByQuery.

Bug: 162450968,169883602,169275184
Test: builds
Change-Id: Ib2d442deacb7b066786e00a3eabf95955abd8403
parent 41ce1f85
Loading
Loading
Loading
Loading
+8 −40
Original line number Diff line number Diff line
@@ -267,14 +267,14 @@ public class AppSearchManager {
            searchResultsFuture.completeExceptionally(e);
        }

        // Translate the list of Bundle into a list of SearchResult
        AppSearchResult<SearchResults> searchResultsResult = getFutureOrThrow(searchResultsFuture);
        if (!searchResultsResult.isSuccess()) {
            return AppSearchResult.newFailedResult(
                    searchResultsResult.getResultCode(), searchResultsResult.getErrorMessage());
        // Translate the Bundle into a searchResultPage.
        AppSearchResult<Bundle> bundleResult = getFutureOrThrow(searchResultsFuture);
        if (!bundleResult.isSuccess()) {
            return AppSearchResult.newFailedResult(bundleResult.getResultCode(),
                    bundleResult.getErrorMessage());
        }
        SearchResults searchResults = searchResultsResult.getResultValue();
        return AppSearchResult.newSuccessfulResult(searchResults.mResults);
        SearchResultPage searchResultPage = new SearchResultPage(bundleResult.getResultValue());
        return AppSearchResult.newSuccessfulResult(searchResultPage.getResults());
    }

    /**
@@ -294,39 +294,7 @@ public class AppSearchManager {
        List<String> uris = new ArrayList<>(request.getUris());
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.delete(DEFAULT_DATABASE, request.getNamespace(), uris, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
        return getFutureOrThrow(future);
    }

    /**
     * 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.
     *
     * @param schemaTypes Schema types whose documents to delete.
     * @return An {@link AppSearchBatchResult} mapping each schema type to a {@code null} success if
     *     deletion was successful, to a {@code null} failure if the type did not exist, or to a
     *     {@code throwable} failure if deletion failed for another reason.
     */
    public AppSearchBatchResult<String, Void> deleteByTypes(@NonNull List<String> schemaTypes) {
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.deleteByTypes(DEFAULT_DATABASE, schemaTypes, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
        return getFutureOrThrow(future);
    }

    /** Deletes all documents owned by the calling app. */
    public AppSearchResult<Void> deleteAll() {
        AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
        try {
            mService.deleteAll(DEFAULT_DATABASE, future);
            mService.removeByUri(DEFAULT_DATABASE, request.getNamespace(), uris, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
+11 −24
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ interface IAppSearchManager {
        in AndroidFuture<AppSearchResult> callback);

    /**
     * Deletes documents by URI.
     * Removes documents by URI.
     *
     * @param databaseName The databaseName the document is in.
     * @param namespace    Namespace of the document to remove.
@@ -105,36 +105,23 @@ 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(
    void removeByUri(
        in String databaseName,
        in String namespace,
        in List<String> uris,
        in AndroidFuture<AppSearchBatchResult> callback);

    /**
     * Deletes documents by schema type.
     * Removes documents by given query.
     *
     * @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;.
     *     If the call fails to start, {@code callback} will be completed exceptionally. Otherwise,
     *     {@code callback} will be completed with an
     *     {@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;
     *     where the keys are schema types. If a schema type doesn't exist, it will be reported as a
     *     failure where the {@code throwable} is {@code null}.
     * @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 deleteByTypes(
    void removeByQuery(
        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 String databaseName, in AndroidFuture<AppSearchResult> callback);
        in String queryExpression,
        in Bundle searchSpecBundle,
        in AndroidFuture<AppSearchResult> callback);
}
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.appsearch;

import android.os.Bundle;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * This class represents a page of {@link SearchResult}s
 * @hide
 */

public class SearchResultPage {
    public static final String RESULTS_FIELD = "results";
    public static final String NEXT_PAGE_TOKEN_FIELD = "nextPageToken";
    private final long mNextPageToken;

    @Nullable
    private List<SearchResult> mResults;

    @NonNull
    private final Bundle mBundle;

    public SearchResultPage(@NonNull Bundle bundle) {
        mBundle = Preconditions.checkNotNull(bundle);
        mNextPageToken = mBundle.getLong(NEXT_PAGE_TOKEN_FIELD);
    }

    /** Returns the {@link Bundle} of this class. */
    @NonNull
    public Bundle getBundle() {
        return mBundle;
    }

    /** Returns the Token to get next {@link SearchResultPage}. */
    public long getNextPageToken() {
        return mNextPageToken;
    }

    /** Returns all {@link android.app.appsearch.SearchResult}s of this page */
    @NonNull
    public List<SearchResult> getResults() {
        if (mResults == null) {
            ArrayList<Bundle> resultBundles = mBundle.getParcelableArrayList(RESULTS_FIELD);
            if (resultBundles == null) {
                mResults = Collections.emptyList();
            } else {
                mResults = new ArrayList<>(resultBundles.size());
                for (int i = 0; i < resultBundles.size(); i++) {
                    mResults.add(new SearchResult(resultBundles.get(i)));
                }
            }
        }
        return mResults;
    }
}
+32 −84
Original line number Diff line number Diff line
@@ -21,33 +21,23 @@ import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.IAppSearchManager;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResults;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.ArraySet;

import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.SearchResultToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.SearchSpecToProtoConverter;

import com.google.android.icing.proto.DocumentProto;
import com.google.android.icing.proto.SchemaProto;
import com.google.android.icing.proto.SchemaTypeConfigProto;
import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.SearchSpecProto;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * TODO(b/142567528): add comments when implement this class
@@ -72,21 +62,20 @@ public class AppSearchManagerService extends SystemService {
                @NonNull List<Bundle> schemaBundles,
                boolean forceOverride,
                @NonNull AndroidFuture<AppSearchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(schemaBundles);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
            int callingUserId = UserHandle.getUserId(callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                SchemaProto.Builder schemaProtoBuilder = SchemaProto.newBuilder();
                Set<AppSearchSchema> schemas = new ArraySet<>(schemaBundles.size());
                for (int i = 0; i < schemaBundles.size(); i++) {
                    AppSearchSchema schema = new AppSearchSchema(schemaBundles.get(i));
                    SchemaTypeConfigProto schemaTypeProto = SchemaToProtoConverter.convert(schema);
                    schemaProtoBuilder.addTypes(schemaTypeProto);
                    schemas.add(new AppSearchSchema(schemaBundles.get(i)));
                }
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                impl.setSchema(databaseName, schemaProtoBuilder.build(), forceOverride);
                impl.setSchema(databaseName, schemas, forceOverride);
                callback.complete(AppSearchResult.newSuccessfulResult(/*result=*/ null));
            } catch (Throwable t) {
                callback.complete(throwableToFailedResult(t));
@@ -100,6 +89,7 @@ public class AppSearchManagerService extends SystemService {
                @NonNull String databaseName,
                @NonNull List<Bundle> documentBundles,
                @NonNull AndroidFuture<AppSearchBatchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(documentBundles);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
@@ -112,9 +102,8 @@ public class AppSearchManagerService extends SystemService {
                        new AppSearchBatchResult.Builder<>();
                for (int i = 0; i < documentBundles.size(); i++) {
                    GenericDocument document = new GenericDocument(documentBundles.get(i));
                    DocumentProto documentProto = GenericDocumentToProtoConverter.convert(document);
                    try {
                        impl.putDocument(databaseName, documentProto);
                        impl.putDocument(databaseName, document);
                        resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
                    } catch (Throwable t) {
                        resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
@@ -131,6 +120,8 @@ public class AppSearchManagerService extends SystemService {
        @Override
        public void getDocuments(@NonNull String databaseName, @NonNull String namespace,
                @NonNull List<String> uris, @NonNull AndroidFuture<AppSearchBatchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(namespace);
            Preconditions.checkNotNull(uris);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
@@ -144,16 +135,8 @@ public class AppSearchManagerService extends SystemService {
                for (int i = 0; i < uris.size(); i++) {
                    String uri = uris.get(i);
                    try {
                        DocumentProto documentProto = impl.getDocument(
                                databaseName, namespace, uri);
                        if (documentProto == null) {
                            resultBuilder.setFailure(
                                    uri, AppSearchResult.RESULT_NOT_FOUND, /*errorMessage=*/ null);
                        } else {
                            GenericDocument genericDocument =
                                    GenericDocumentToProtoConverter.convert(documentProto);
                            resultBuilder.setSuccess(uri, genericDocument.getBundle());
                        }
                        GenericDocument document = impl.getDocument(databaseName, namespace, uri);
                        resultBuilder.setSuccess(uri, document.getBundle());
                    } catch (Throwable t) {
                        resultBuilder.setResult(uri, throwableToFailedResult(t));
                    }
@@ -167,12 +150,14 @@ public class AppSearchManagerService extends SystemService {
        }

        // TODO(sidchhabra): Do this in a threadpool.
        // TODO(b/162450968) handle pagination after getNextPage and SearchResults is ready.
        @Override
        public void query(
                @NonNull String databaseName,
                @NonNull String queryExpression,
                @NonNull Bundle searchSpecBundle,
                @NonNull AndroidFuture<AppSearchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(queryExpression);
            Preconditions.checkNotNull(searchSpecBundle);
            Preconditions.checkNotNull(callback);
@@ -180,29 +165,14 @@ public class AppSearchManagerService extends SystemService {
            int callingUserId = UserHandle.getUserId(callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                SearchSpec searchSpec = new SearchSpec(searchSpecBundle);
                SearchSpecProto searchSpecProto =
                        SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
                searchSpecProto = searchSpecProto.toBuilder()
                        .setQuery(queryExpression).build();
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                // TODO(adorokhine): handle pagination
                SearchResultProto searchResultProto = impl.query(
                SearchResultPage searchResultPage = impl.query(
                        databaseName,
                        searchSpecProto,
                        SearchSpecToProtoConverter.toResultSpecProto(searchSpec),
                        SearchSpecToProtoConverter.toScoringSpecProto(searchSpec));
                List<SearchResult> searchResultList =
                        new ArrayList<>(searchResultProto.getResultsCount());
                for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
                    SearchResult result = SearchResultToProtoConverter.convertSearchResult(
                            searchResultProto.getResults(i));
                    searchResultList.add(result);
                }
                SearchResults searchResults =
                        new SearchResults(searchResultList, searchResultProto.getNextPageToken());
                callback.complete(AppSearchResult.newSuccessfulResult(searchResults));
                        queryExpression,
                        new SearchSpec(searchSpecBundle));
                callback.complete(
                        AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
            } catch (Throwable t) {
                callback.complete(throwableToFailedResult(t));
            } finally {
@@ -211,8 +181,10 @@ public class AppSearchManagerService extends SystemService {
        }

        @Override
        public void delete(@NonNull String databaseName, @NonNull String namespace,
        public void removeByUri(@NonNull String databaseName, @NonNull String namespace,
                List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(namespace);
            Preconditions.checkNotNull(uris);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
@@ -241,38 +213,14 @@ public class AppSearchManagerService extends SystemService {
        }

        @Override
        public void deleteByTypes(@NonNull String databaseName,
                List<String> schemaTypes, AndroidFuture<AppSearchBatchResult> callback) {
            Preconditions.checkNotNull(schemaTypes);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
            int callingUserId = UserHandle.getUserId(callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                AppSearchBatchResult.Builder<String, Void> resultBuilder =
                        new AppSearchBatchResult.Builder<>();
                for (int i = 0; i < schemaTypes.size(); i++) {
                    String schemaType = schemaTypes.get(i);
                    try {
                        impl.removeByType(databaseName, schemaType);
                        resultBuilder.setSuccess(schemaType, /*result=*/ null);
                    } catch (Throwable t) {
                        resultBuilder.setResult(schemaType, throwableToFailedResult(t));
                    }
                }
                callback.complete(resultBuilder.build());
            } catch (Throwable t) {
                callback.completeExceptionally(t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
            }
        }

        @Override
        public void deleteAll(@NonNull String databaseName,
        public void removeByQuery(
                @NonNull String databaseName,
                @NonNull String queryExpression,
                @NonNull Bundle searchSpecBundle,
                @NonNull AndroidFuture<AppSearchResult> callback) {
            Preconditions.checkNotNull(databaseName);
            Preconditions.checkNotNull(queryExpression);
            Preconditions.checkNotNull(searchSpecBundle);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
            int callingUserId = UserHandle.getUserId(callingUid);
@@ -280,8 +228,8 @@ public class AppSearchManagerService extends SystemService {
            try {
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
                impl.removeAll(databaseName);
                callback.complete(AppSearchResult.newSuccessfulResult(null));
                impl.removeByQuery(databaseName, queryExpression, new SearchSpec(searchSpecBundle));
                callback.complete(AppSearchResult.newSuccessfulResult(/*result= */null));
            } catch (Throwable t) {
                callback.complete(throwableToFailedResult(t));
            } finally {
+220 −194

File changed.

Preview size limit exceeded, changes collapsed.

Loading