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

Commit 9d56fb91 authored by Terry Wang's avatar Terry Wang Committed by Android (Google) Code Review
Browse files

Merge "Porting the async AppSearchSession to platform."

parents 988aa5d9 b71cb7a5
Loading
Loading
Loading
Loading
+19 −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;

/** {@hide} */
parcelable AppSearchBatchResult;
 No newline at end of file
+146 −10
Original line number Diff line number Diff line
@@ -15,10 +15,12 @@
 */
package android.app.appsearch;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.Context;
import android.os.Bundle;
import android.os.ParcelableException;
import android.os.RemoteException;

import com.android.internal.infra.AndroidFuture;
@@ -27,7 +29,10 @@ import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * This class provides access to the centralized AppSearch index maintained by the system.
@@ -40,12 +45,99 @@ 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 = "";
    /**
     * The default empty database name.
     * @hide
     */
    public static final String DEFAULT_DATABASE_NAME = "";

    private final IAppSearchManager mService;

    /** @hide */
    public AppSearchManager(@NonNull IAppSearchManager service) {
        mService = service;
        mService = Objects.requireNonNull(service);
    }

    /** Contains information about how to create the search session. */
    public static final class SearchContext {
        final String mDatabaseName;

        SearchContext(@NonNull String databaseName) {
            mDatabaseName = Objects.requireNonNull(databaseName);
        }

        /**
         * Returns the name of the database to create or open.
         *
         * <p>Databases with different names are fully separate with distinct types, namespaces,
         * and data.
         */
        @NonNull
        public String getDatabaseName() {
            return mDatabaseName;
        }

        /** Builder for {@link SearchContext} objects. */
        public static final class Builder {
            private String mDatabaseName = DEFAULT_DATABASE_NAME;
            private boolean mBuilt = false;

            /**
             * Sets the name of the database associated with {@link AppSearchSession}.
             *
             * <p>{@link AppSearchSession} will create or open a database under the given name.
             *
             * <p>Databases with different names are fully separate with distinct types, namespaces,
             * and data.
             *
             * <p>Database name cannot contain {@code '/'}.
             *
             * <p>If not specified, defaults to {@link #DEFAULT_DATABASE_NAME}.
             * @param databaseName The name of the database.
             * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
             */
            @NonNull
            public Builder setDatabaseName(@NonNull String databaseName) {
                Preconditions.checkState(!mBuilt, "Builder has already been used");
                Objects.requireNonNull(databaseName);
                if (databaseName.contains("/")) {
                    throw new IllegalArgumentException("Database name cannot contain '/'");
                }
                mDatabaseName = databaseName;
                return this;
            }

            /** Builds a {@link SearchContext} instance. */
            @NonNull
            public SearchContext build() {
                Preconditions.checkState(!mBuilt, "Builder has already been used");
                mBuilt = true;
                return new SearchContext(mDatabaseName);
            }
        }
    }

    /**
     * Creates a new {@link AppSearchSession}.
     *
     * <p>This process requires an AppSearch native indexing file system for each user. If it's not
     * created for this user, the initialization process will create one under user's directory.
     *
     * @param searchContext The {@link SearchContext} contains all information to create a new
     *                      {@link AppSearchSession}
     * @param executor      Executor on which to invoke the callback.
     * @param callback      The {@link AppSearchResult}&lt;{@link AppSearchSession}&gt; of
     *                      performing this operation. Or a {@link AppSearchResult} with failure
     *                      reason code and error information.
     */
    public void createSearchSession(
            @NonNull SearchContext searchContext,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
        Objects.requireNonNull(searchContext);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        AppSearchSession.createSearchSession(searchContext, mService, executor, callback);
    }

    /**
@@ -99,7 +191,7 @@ public class AppSearchManager {
     *
     * @param request The schema update request.
     * @return the result of performing this operation.
     *
     * @deprecated use {@link AppSearchSession#setSchema} instead.
     * @hide
     */
    @NonNull
@@ -113,9 +205,14 @@ public class AppSearchManager {
        }
        AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
        try {
            mService.setSchema(DEFAULT_DATABASE, schemaBundles, request.isForceOverride(), future);
            mService.setSchema(DEFAULT_DATABASE_NAME, schemaBundles, request.isForceOverride(),
                    new IAppSearchResultCallback.Stub() {
                        public void onResult(AppSearchResult result) {
                            future.complete(result);
                        }
                    });
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }
@@ -134,6 +231,9 @@ public class AppSearchManager {
     * {@link AppSearchBatchResult} are the URIs of the input documents. The values are
     * {@code null} if they were successfully indexed, or a failed {@link AppSearchResult}
     * otherwise.
     * @throws RuntimeException If an error occurred during the execution.
     *
     * @deprecated use {@link AppSearchSession#putDocuments} instead.
     * @hide
     */
    public AppSearchBatchResult<String, Void> putDocuments(@NonNull PutDocumentsRequest request) {
@@ -146,7 +246,16 @@ public class AppSearchManager {
        }
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.putDocuments(DEFAULT_DATABASE, documentBundles, future);
            mService.putDocuments(DEFAULT_DATABASE_NAME, documentBundles,
                    new IAppSearchBatchResultCallback.Stub() {
                        public void onResult(AppSearchBatchResult result) {
                            future.complete(result);
                        }

                        public void onSystemError(ParcelableException exception) {
                            future.completeExceptionally(exception);
                        }
                    });
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
@@ -165,6 +274,9 @@ public class AppSearchManager {
     * {@link GenericDocument}s on success, or a failed {@link AppSearchResult} otherwise.
     * URIs that are not found will return a failed {@link AppSearchResult} with a result code
     * of {@link AppSearchResult#RESULT_NOT_FOUND}.
     * @throws RuntimeException If an error occurred during the execution.
     *
     * @deprecated use {@link AppSearchSession#getByUri} instead.
     */
    public AppSearchBatchResult<String, GenericDocument> getByUri(
            @NonNull GetByUriRequest request) {
@@ -173,7 +285,16 @@ public class AppSearchManager {
        List<String> uris = new ArrayList<>(request.getUris());
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.getDocuments(DEFAULT_DATABASE, request.getNamespace(), uris, future);
            mService.getDocuments(DEFAULT_DATABASE_NAME, request.getNamespace(), uris,
                    new IAppSearchBatchResultCallback.Stub() {
                        public void onResult(AppSearchBatchResult result) {
                            future.complete(result);
                        }

                        public void onSystemError(ParcelableException exception) {
                            future.completeExceptionally(exception);
                        }
                    });
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
@@ -252,6 +373,9 @@ public class AppSearchManager {
     *
     * @param queryExpression Query String to search.
     * @param searchSpec Spec for setting filters, raw query etc.
     * @throws RuntimeException If an error occurred during the execution.
     *
     * @deprecated use AppSearchSession#query instead.
     * @hide
     */
    @NonNull
@@ -261,7 +385,7 @@ public class AppSearchManager {
        //     them in one big list.
        AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>();
        try {
            mService.query(DEFAULT_DATABASE, queryExpression,
            mService.query(DEFAULT_DATABASE_NAME, queryExpression,
                    searchSpec.getBundle(), searchResultsFuture);
        } catch (RemoteException e) {
            searchResultsFuture.completeExceptionally(e);
@@ -278,7 +402,7 @@ public class AppSearchManager {
    }

    /**
     * Deletes {@link GenericDocument}s by URI.
     * Removes {@link GenericDocument}s by URI.
     *
     * <p>You should not call this method directly; instead, use the {@code AppSearch#delete()} API
     * provided by JetPack.
@@ -289,12 +413,24 @@ public class AppSearchManager {
     * or a failed {@link AppSearchResult} otherwise. URIs that are not found will return a
     * failed {@link AppSearchResult} with a result code of
     * {@link AppSearchResult#RESULT_NOT_FOUND}.
     * @throws RuntimeException If an error occurred during the execution.
     *
     * @deprecated use {@link AppSearchSession#removeByUri} instead.
     */
    public AppSearchBatchResult<String, Void> removeByUri(@NonNull RemoveByUriRequest request) {
        List<String> uris = new ArrayList<>(request.getUris());
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.removeByUri(DEFAULT_DATABASE, request.getNamespace(), uris, future);
            mService.removeByUri(DEFAULT_DATABASE_NAME, request.getNamespace(), uris,
                    new IAppSearchBatchResultCallback.Stub() {
                        public void onResult(AppSearchBatchResult result) {
                            future.complete(result);
                        }

                        public void onSystemError(ParcelableException exception) {
                            future.completeExceptionally(exception);
                        }
                    });
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
+19 −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;

/** {@hide} */
parcelable AppSearchResult;
 No newline at end of file
+23 −0
Original line number Diff line number Diff line
@@ -19,9 +19,11 @@ package android.app.appsearch;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.os.Parcel;
import android.os.Parcelable;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -218,4 +220,25 @@ public final class AppSearchResult<ValueType> implements Parcelable {
            @ResultCode int resultCode, @Nullable String errorMessage) {
        return new AppSearchResult<>(resultCode, /*resultValue=*/ null, errorMessage);
    }

    /** @hide */
    @NonNull
    public static <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
            @NonNull Throwable t) {
        if (t instanceof AppSearchException) {
            return ((AppSearchException) t).toAppSearchResult();
        }

        @AppSearchResult.ResultCode int resultCode;
        if (t instanceof IllegalStateException) {
            resultCode = AppSearchResult.RESULT_INTERNAL_ERROR;
        } else if (t instanceof IllegalArgumentException) {
            resultCode = AppSearchResult.RESULT_INVALID_ARGUMENT;
        } else if (t instanceof IOException) {
            resultCode = AppSearchResult.RESULT_IO_ERROR;
        } else {
            resultCode = AppSearchResult.RESULT_UNKNOWN_ERROR;
        }
        return AppSearchResult.newFailedResult(resultCode, t.toString());
    }
}
+312 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading