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

Commit bd6bcf6a authored by Alexander Dorokhine's avatar Alexander Dorokhine
Browse files

Merge GenericDocument and SearchResult work from Jetpack.

Bug: 162450968
Test: AppSearchManagerTest
Change-Id: I5617ddad49fa27c6e45fc9742aa27607f0cb2413
parent 0dd233f3
Loading
Loading
Loading
Loading
+21 −37
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 * 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.
@@ -16,20 +16,26 @@

package android.app.appsearch;


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

import android.app.appsearch.AppSearchSchema.PropertyConfig;

/**
 * Encapsulates a {@link AppSearchDocument} that represent an email.
 * Encapsulates a {@link GenericDocument} that represent an email.
 *
 * <p>This class is a higher level implement of {@link AppSearchDocument}.
 * <p>This class is a higher level implement of {@link GenericDocument}.
 *
 * <p>This class will eventually migrate to Jetpack, where it will become public API.
 *
 * @hide
 */
public class AppSearchEmail extends AppSearchDocument {

public class AppSearchEmail extends GenericDocument {
    /** The name of the schema type for {@link AppSearchEmail} documents.*/
    public static final String SCHEMA_TYPE = "builtin:Email";

    private static final String KEY_FROM = "from";
    private static final String KEY_TO = "to";
    private static final String KEY_CC = "cc";
@@ -37,46 +43,43 @@ public class AppSearchEmail extends AppSearchDocument {
    private static final String KEY_SUBJECT = "subject";
    private static final String KEY_BODY = "body";

    /** The name of the schema type for {@link AppSearchEmail} documents.*/
    public static final String SCHEMA_TYPE = "builtin:Email";

    public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE)
            .addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_FROM)
            .addProperty(new PropertyConfig.Builder(KEY_FROM)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
                    .build()

            ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_TO)
            ).addProperty(new PropertyConfig.Builder(KEY_TO)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
                    .build()

            ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_CC)
            ).addProperty(new PropertyConfig.Builder(KEY_CC)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
                    .build()

            ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_BCC)
            ).addProperty(new PropertyConfig.Builder(KEY_BCC)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
                    .build()

            ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_SUBJECT)
            ).addProperty(new PropertyConfig.Builder(KEY_SUBJECT)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
                    .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
                    .build()

            ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_BODY)
            ).addProperty(new PropertyConfig.Builder(KEY_BODY)
                    .setDataType(PropertyConfig.DATA_TYPE_STRING)
                    .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
                    .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
@@ -87,12 +90,11 @@ public class AppSearchEmail extends AppSearchDocument {

    /**
     * Creates a new {@link AppSearchEmail} from the contents of an existing
     * {@link AppSearchDocument}.
     * {@link GenericDocument}.
     *
     * @param document The {@link AppSearchDocument} containing the email content.
     * @hide
     * @param document The {@link GenericDocument} containing the email content.
     */
    public AppSearchEmail(@NonNull AppSearchDocument document) {
    public AppSearchEmail(@NonNull GenericDocument document) {
        super(document);
    }

@@ -101,7 +103,6 @@ public class AppSearchEmail extends AppSearchDocument {
     *
     * @return Returns the subject of {@link AppSearchEmail} or {@code null} if it's not been set
     *         yet.
     * @hide
     */
    @Nullable
    public String getFrom() {
@@ -113,7 +114,6 @@ public class AppSearchEmail extends AppSearchDocument {
     *
     * @return Returns the destination addresses of {@link AppSearchEmail} or {@code null} if it's
     *         not been set yet.
     * @hide
     */
    @Nullable
    public String[] getTo() {
@@ -125,7 +125,6 @@ public class AppSearchEmail extends AppSearchDocument {
     *
     * @return Returns the CC list of {@link AppSearchEmail} or {@code null} if it's not been set
     *         yet.
     * @hide
     */
    @Nullable
    public String[] getCc() {
@@ -137,7 +136,6 @@ public class AppSearchEmail extends AppSearchDocument {
     *
     * @return Returns the BCC list of {@link AppSearchEmail} or {@code null} if it's not been set
     *         yet.
     * @hide
     */
    @Nullable
    public String[] getBcc() {
@@ -149,7 +147,6 @@ public class AppSearchEmail extends AppSearchDocument {
     *
     * @return Returns the value subject of {@link AppSearchEmail} or {@code null} if it's not been
     *         set yet.
     * @hide
     */
    @Nullable
    public String getSubject() {
@@ -160,7 +157,6 @@ public class AppSearchEmail extends AppSearchDocument {
     * Get the body of {@link AppSearchEmail}.
     *
     * @return Returns the body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
     * @hide
     */
    @Nullable
    public String getBody() {
@@ -169,14 +165,12 @@ public class AppSearchEmail extends AppSearchDocument {

    /**
     * The builder class for {@link AppSearchEmail}.
     * @hide
     */
    public static class Builder extends AppSearchDocument.Builder<AppSearchEmail.Builder> {
    public static class Builder extends GenericDocument.Builder<AppSearchEmail.Builder> {

        /**
         * Create a new {@link AppSearchEmail.Builder}
         * @param uri The Uri of the Email.
         * @hide
         */
        public Builder(@NonNull String uri) {
            super(uri, SCHEMA_TYPE);
@@ -184,7 +178,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the from address of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setFrom(@NonNull String from) {
@@ -194,7 +187,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the destination address of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setTo(@NonNull String... to) {
@@ -204,7 +196,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the CC list of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setCc(@NonNull String... cc) {
@@ -214,7 +205,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the BCC list of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
@@ -224,7 +214,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the subject of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setSubject(@NonNull String subject) {
@@ -234,7 +223,6 @@ public class AppSearchEmail extends AppSearchDocument {

        /**
         * Set the body of {@link AppSearchEmail}
         * @hide
         */
        @NonNull
        public AppSearchEmail.Builder setBody(@NonNull String body) {
@@ -242,11 +230,7 @@ public class AppSearchEmail extends AppSearchDocument {
            return this;
        }

        /**
         * Builds the {@link AppSearchEmail} object.
         *
         * @hide
         */
        /** Builds the {@link AppSearchEmail} object. */
        @NonNull
        @Override
        public AppSearchEmail build() {
+37 −65
Original line number Diff line number Diff line
@@ -23,11 +23,6 @@ import android.os.RemoteException;

import com.android.internal.infra.AndroidFuture;

import com.google.android.icing.proto.DocumentProto;
import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.StatusProto;
import com.google.protobuf.InvalidProtocolBufferException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -78,8 +73,8 @@ public class AppSearchManager {
     *     <li>Removal of an existing type
     *     <li>Removal of a property from a type
     *     <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
     *     <li>For properties of {@code AppSearchDocument} type, changing the schema type of
     *         {@code AppSearchDocument}s of that property
     *     <li>For properties of {@code GenericDocument} type, changing the schema type of
     *         {@code GenericDocument}s of that property
     *     <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an
     *         {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL
     *             OPTIONAL} property into a
@@ -148,31 +143,31 @@ public class AppSearchManager {
    }

    /**
     * Index {@link AppSearchDocument}s into AppSearch.
     * Index {@link GenericDocument}s into AppSearch.
     *
     * <p>You should not call this method directly; instead, use the
     * {@code AppSearch#putDocuments()} API provided by JetPack.
     *
     * <p>Each {@link AppSearchDocument}'s {@code schemaType} field must be set to the name of a
     * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
     * schema type previously registered via the {@link #setSchema} method.
     *
     * @param documents {@link AppSearchDocument}s that need to be indexed.
     * @param documents {@link GenericDocument}s that need to be indexed.
     * @return An {@link AppSearchBatchResult} mapping the document URIs to {@link Void} if they
     *     were successfully indexed, or a {@link Throwable} describing the failure if they could
     *     not be indexed.
     * @hide
     */
    public AppSearchBatchResult<String, Void> putDocuments(
            @NonNull List<AppSearchDocument> documents) {
            @NonNull List<GenericDocument> documents) {
        // TODO(b/146386470): Transmit these documents as a RemoteStream instead of sending them in
        // one big list.
        List<byte[]> documentsBytes = new ArrayList<>(documents.size());
        for (AppSearchDocument document : documents) {
            documentsBytes.add(document.getProto().toByteArray());
        List<Bundle> documentBundles = new ArrayList<>(documents.size());
        for (GenericDocument document : documents) {
            documentBundles.add(document.getBundle());
        }
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.putDocuments(documentsBytes, future);
            mService.putDocuments(documentBundles, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
@@ -180,19 +175,18 @@ public class AppSearchManager {
    }

    /**
     * Retrieves {@link AppSearchDocument}s by URI.
     * Retrieves {@link GenericDocument}s by URI.
     *
     * <p>You should not call this method directly; instead, use the
     * {@code AppSearch#getDocuments()} API provided by JetPack.
     *
     * @param uris URIs of the documents to look up.
     * @return An {@link AppSearchBatchResult} mapping the document URIs to
     *     {@link AppSearchDocument} values if they were successfully retrieved, a {@code null}
     *     {@link GenericDocument} values if they were successfully retrieved, a {@code null}
     *     failure if they were not found, or a {@link Throwable} failure describing the problem if
     *     an error occurred.
     */
    public AppSearchBatchResult<String, AppSearchDocument> getDocuments(
            @NonNull List<String> uris) {
    public AppSearchBatchResult<String, GenericDocument> getDocuments(@NonNull List<String> uris) {
        // TODO(b/146386470): Transmit the result documents as a RemoteStream instead of sending
        //     them in one big list.
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
@@ -202,43 +196,35 @@ public class AppSearchManager {
            future.completeExceptionally(e);
        }

        // Deserialize the protos into Document objects
        AppSearchBatchResult<String, byte[]> protoResults = getFutureOrThrow(future);
        AppSearchBatchResult.Builder<String, AppSearchDocument> documentResultBuilder =
        // Translate from document bundles to GenericDocument instances
        AppSearchBatchResult<String, Bundle> bundleResult = getFutureOrThrow(future);
        AppSearchBatchResult.Builder<String, GenericDocument> documentResultBuilder =
                new AppSearchBatchResult.Builder<>();

        // Translate successful results
        for (Map.Entry<String, byte[]> protoResult : protoResults.getSuccesses().entrySet()) {
            DocumentProto documentProto;
            try {
                documentProto = DocumentProto.parseFrom(protoResult.getValue());
            } catch (InvalidProtocolBufferException e) {
                documentResultBuilder.setFailure(
                        protoResult.getKey(), AppSearchResult.RESULT_IO_ERROR, e.getMessage());
                continue;
            }
            AppSearchDocument document;
        for (Map.Entry<String, Bundle> bundleEntry : bundleResult.getSuccesses().entrySet()) {
            GenericDocument document;
            try {
                document = new AppSearchDocument(documentProto);
                document = new GenericDocument(bundleEntry.getValue());
            } catch (Throwable t) {
                // These documents went through validation, so how could this fail? We must have
                // done something wrong.
                documentResultBuilder.setFailure(
                        protoResult.getKey(),
                        bundleEntry.getKey(),
                        AppSearchResult.RESULT_INTERNAL_ERROR,
                        t.getMessage());
                continue;
            }
            documentResultBuilder.setSuccess(protoResult.getKey(), document);
            documentResultBuilder.setSuccess(bundleEntry.getKey(), document);
        }

        // Translate failed results
        for (Map.Entry<String, AppSearchResult<byte[]>> protoResult :
                protoResults.getFailures().entrySet()) {
        for (Map.Entry<String, AppSearchResult<Bundle>> bundleEntry :
                bundleResult.getFailures().entrySet()) {
            documentResultBuilder.setFailure(
                    protoResult.getKey(),
                    protoResult.getValue().getResultCode(),
                    protoResult.getValue().getErrorMessage());
                    bundleEntry.getKey(),
                    bundleEntry.getValue().getResultCode(),
                    bundleEntry.getValue().getErrorMessage());
        }

        return documentResultBuilder.build();
@@ -287,43 +273,29 @@ public class AppSearchManager {
     * @hide
     */
    @NonNull
    public AppSearchResult<SearchResults> query(
    public AppSearchResult<List<SearchResult>> query(
            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
        // TODO(b/146386470): Transmit the result documents as a RemoteStream instead of sending
        //     them in one big list.
        AndroidFuture<AppSearchResult> searchResultFuture = new AndroidFuture<>();
        AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>();
        try {
            mService.query(queryExpression, searchSpec.getBundle(), searchResultFuture);
            mService.query(queryExpression, searchSpec.getBundle(), searchResultsFuture);
        } catch (RemoteException e) {
            searchResultFuture.completeExceptionally(e);
            searchResultsFuture.completeExceptionally(e);
        }

        // Deserialize the protos into Document objects
        AppSearchResult<byte[]> searchResultBytes = getFutureOrThrow(searchResultFuture);
        if (!searchResultBytes.isSuccess()) {
            return AppSearchResult.newFailedResult(
                    searchResultBytes.getResultCode(), searchResultBytes.getErrorMessage());
        }
        SearchResultProto searchResultProto;
        try {
            searchResultProto = SearchResultProto.parseFrom(searchResultBytes.getResultValue());
        } catch (InvalidProtocolBufferException e) {
            return AppSearchResult.newFailedResult(
                    AppSearchResult.RESULT_INTERNAL_ERROR, e.getMessage());
        }
        if (searchResultProto.getStatus().getCode() != StatusProto.Code.OK) {
            // This should never happen; AppSearchManagerService should catch failed searchResults
            // entries and transmit them as a failed AppSearchResult.
        // Translate the list of Bundle into a list of SearchResult
        AppSearchResult<SearchResults> searchResultsResult = getFutureOrThrow(searchResultsFuture);
        if (!searchResultsResult.isSuccess()) {
            return AppSearchResult.newFailedResult(
                    AppSearchResult.RESULT_INTERNAL_ERROR,
                    searchResultProto.getStatus().getMessage());
                    searchResultsResult.getResultCode(), searchResultsResult.getErrorMessage());
        }

        return AppSearchResult.newSuccessfulResult(new SearchResults(searchResultProto));
        SearchResults searchResults = searchResultsResult.getResultValue();
        return AppSearchResult.newSuccessfulResult(searchResults.mResults);
    }

    /**
     * Deletes {@link AppSearchDocument}s by URI.
     * Deletes {@link GenericDocument}s by URI.
     *
     * <p>You should not call this method directly; instead, use the {@code AppSearch#delete()} API
     * provided by JetPack.
+923 −0

File changed and moved.

Preview size limit exceeded, changes collapsed.

+8 −7
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.internal.infra.AndroidFuture;

parcelable AppSearchResult;
parcelable AppSearchBatchResult;
parcelable SearchResults;

/** {@hide} */
interface IAppSearchManager {
@@ -41,7 +42,7 @@ interface IAppSearchManager {
    /**
     * Inserts documents into the index.
     *
     * @param documentsBytes {@link List}&lt;byte[]&gt; of serialized DocumentProtos.
     * @param documentBundes List of GenericDocument bundles.
     * @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,
@@ -49,18 +50,19 @@ interface IAppSearchManager {
     *     {@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;
     *     where the keys are document URIs, and the values are {@code null}.
     */
    void putDocuments(in List documentsBytes, in AndroidFuture<AppSearchBatchResult> callback);
    void putDocuments(
        in List<Bundle> documentBundles, in AndroidFuture<AppSearchBatchResult> callback);

    /**
     * Retrieves documents from the index.
     *
     * @param uris The URIs of the documents to retrieve
     * @param callback
     *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link byte[]}&gt;&gt;.
     *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&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 byte[]}&gt;
     *     where the keys are document URIs, and the values are serialized Document protos.
     *     {@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);

@@ -69,8 +71,7 @@ interface IAppSearchManager {
     *
     * @param queryExpression String to search for
     * @param searchSpecBundle SearchSpec bundle
     * @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link byte[]}&gt;&gt;
     *     Will be completed with a serialized {@link SearchResultsProto}.
     * @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link SearchResults}&gt;&gt;
     */
    void query(
        in String queryExpression,
+0 −182

File deleted.

Preview size limit exceeded, changes collapsed.

Loading