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

Commit a162921b authored by Alexander Dorokhine's avatar Alexander Dorokhine Committed by Android (Google) Code Review
Browse files

Merge "Update Framework from Jetpack."

parents fa2a82b0 6a54e73a
Loading
Loading
Loading
Loading
+31 −27
Original line number Diff line number Diff line
@@ -45,33 +45,35 @@ public class SearchResults implements Closeable {

    private final IAppSearchManager mService;

    // The database name to search over. If null, this will search over all database names.
    @Nullable
    private final String mDatabaseName;

    @UserIdInt
    private final int mUserId;

    private final String mQueryExpression;

    private final SearchSpec mSearchSpec;

    @UserIdInt
    private final int mUserId;

    private final Executor mExecutor;

    private long mNextPageToken;

    private boolean mIsFirstLoad = true;

    SearchResults(@NonNull IAppSearchManager service,
    SearchResults(
            @NonNull IAppSearchManager service,
            @Nullable String databaseName,
            @NonNull String queryExpression,
            @NonNull SearchSpec searchSpec,
            @UserIdInt int userId,
            @NonNull @CallbackExecutor Executor executor) {
        mService = Objects.requireNonNull(service);
        mUserId = userId;
        mDatabaseName = Objects.requireNonNull(databaseName);
        mDatabaseName = databaseName;
        mQueryExpression = Objects.requireNonNull(queryExpression);
        mSearchSpec = Objects.requireNonNull(searchSpec);
        mUserId = userId;
        mExecutor = Objects.requireNonNull(executor);
    }

@@ -90,11 +92,14 @@ public class SearchResults implements Closeable {
            if (mIsFirstLoad) {
                mIsFirstLoad = false;
                if (mDatabaseName == null) {
                    // Global query, there's no one package-database combination to check.
                    mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), mUserId,
                            wrapCallback(callback));
                } else {
                    mService.query(mDatabaseName, mQueryExpression, mSearchSpec.getBundle(),
                            mUserId, wrapCallback(callback));
                    // Normal local query, pass in specified database.
                    mService.query(
                            mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId,
                            wrapCallback(callback));
                }
            } else {
                mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback));
@@ -104,31 +109,13 @@ public class SearchResults implements Closeable {
        }
    }

    private void invokeCallback(AppSearchResult result,
            @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
        if (result.isSuccess()) {
            try {
                SearchResultPage searchResultPage =
                        new SearchResultPage((Bundle) result.getResultValue());
                mNextPageToken = searchResultPage.getNextPageToken();
                callback.accept(AppSearchResult.newSuccessfulResult(
                        searchResultPage.getResults()));
            } catch (Throwable t) {
                callback.accept(AppSearchResult.throwableToFailedResult(t));
            }
        } else {
            callback.accept(result);
        }
    }
    @Override
    public void close() {
        mExecutor.execute(() -> {
        try {
            mService.invalidateNextPageToken(mNextPageToken, mUserId);
        } catch (RemoteException e) {
            Log.d(TAG, "Unable to close the SearchResults", e);
        }
        });
    }

    private IAppSearchResultCallback wrapCallback(
@@ -139,4 +126,21 @@ public class SearchResults implements Closeable {
            }
        };
    }

    private void invokeCallback(AppSearchResult result,
            @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
        if (result.isSuccess()) {
            try {
                SearchResultPage searchResultPage =
                        new SearchResultPage((Bundle) result.getResultValue());
                mNextPageToken = searchResultPage.getNextPageToken();
                callback.accept(AppSearchResult.newSuccessfulResult(
                        searchResultPage.getResults()));
            } catch (Throwable t) {
                callback.accept(AppSearchResult.throwableToFailedResult(t));
            }
        } else {
            callback.accept(result);
        }
    }
}
+140 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.exceptions.IllegalSearchSpecException;
import android.os.Bundle;
import android.util.ArrayMap;

import com.android.internal.util.Preconditions;

@@ -33,6 +34,8 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This class represents the specification logic for AppSearch. It can be used to set the type of
@@ -40,6 +43,15 @@ import java.util.List;
 */
// TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
public final class SearchSpec {
    /**
     * Schema type to be used in {@link SearchSpec.Builder#addProjectionTypePropertyPath} to apply
     * property paths to all results, excepting any types that have had their own, specific property
     * paths set.
     *
     * @hide
     */
    public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";

    static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
    static final String SCHEMA_TYPE_FIELD = "schemaType";
    static final String NAMESPACE_FIELD = "namespace";
@@ -49,6 +61,7 @@ public final class SearchSpec {
    static final String SNIPPET_COUNT_FIELD = "snippetCount";
    static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty";
    static final String MAX_SNIPPET_FIELD = "maxSnippet";
    static final String PROJECTION_TYPE_PROPERTY_PATHS_FIELD = "projectionTypeFieldMasks";

    /** @hide */
    public static final int DEFAULT_NUM_PER_PAGE = 10;
@@ -206,12 +219,35 @@ public final class SearchSpec {
        return mBundle.getInt(MAX_SNIPPET_FIELD);
    }

    /**
     * Returns a map from schema type to property paths to be used for projection.
     *
     * <p>If the map is empty, then all properties will be retrieved for all results.
     *
     * <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this
     * function, rather than calling it multiple times.
     *
     * @hide
     */
    @NonNull
    public Map<String, List<String>> getProjectionTypePropertyPaths() {
        Bundle typePropertyPathsBundle = mBundle.getBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD);
        Set<String> schemaTypes = typePropertyPathsBundle.keySet();
        Map<String, List<String>> typePropertyPathsMap = new ArrayMap<>(schemaTypes.size());
        for (String schemaType : schemaTypes) {
            typePropertyPathsMap.put(
                    schemaType, typePropertyPathsBundle.getStringArrayList(schemaType));
        }
        return typePropertyPathsMap;
    }

    /** Builder for {@link SearchSpec objects}. */
    public static final class Builder {

        private final Bundle mBundle;
        private final ArrayList<String> mSchemaTypes = new ArrayList<>();
        private final ArrayList<String> mNamespaces = new ArrayList<>();
        private final Bundle mProjectionTypePropertyMasks = new Bundle();
        private boolean mBuilt = false;

        /** Creates a new {@link SearchSpec.Builder}. */
@@ -385,6 +421,109 @@ public final class SearchSpec {
            return this;
        }

        /**
         * Adds property paths for the specified type to be used for projection. If property paths
         * are added for a type, then only the properties referred to will be retrieved for results
         * of that type. If a property path that is specified isn't present in a result, it will be
         * ignored for that result. Property paths cannot be null.
         *
         * <p>If no property paths are added for a particular type, then all properties of results
         * of that type will be retrieved.
         *
         * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD},
         * then those property paths will apply to all results, excepting any types that have their
         * own, specific property paths set.
         *
         * <p>Suppose the following document is in the index.
         *
         * <pre>{@code
         * Email: Document {
         *   sender: Document {
         *     name: "Mr. Person"
         *     email: "mrperson123@google.com"
         *   }
         *   recipients: [
         *     Document {
         *       name: "John Doe"
         *       email: "johndoe123@google.com"
         *     }
         *     Document {
         *       name: "Jane Doe"
         *       email: "janedoe123@google.com"
         *     }
         *   ]
         *   subject: "IMPORTANT"
         *   body: "Limited time offer!"
         * }
         * }</pre>
         *
         * <p>Then, suppose that a query for "important" is issued with the following projection
         * type property paths:
         *
         * <pre>{@code
         * {schemaType: "Email", ["subject", "sender.name", "recipients.name"]}
         * }</pre>
         *
         * <p>The above document will be returned as:
         *
         * <pre>{@code
         * Email: Document {
         *   sender: Document {
         *     name: "Mr. Body"
         *   }
         *   recipients: [
         *     Document {
         *       name: "John Doe"
         *     }
         *     Document {
         *       name: "Jane Doe"
         *     }
         *   ]
         *   subject: "IMPORTANT"
         * }
         * }</pre>
         *
         * @hide
         */
        @NonNull
        public SearchSpec.Builder addProjectionTypePropertyPaths(
                @NonNull String schemaType, @NonNull String... propertyPaths) {
            Preconditions.checkNotNull(propertyPaths);
            return addProjectionTypePropertyPaths(schemaType, Arrays.asList(propertyPaths));
        }

        /**
         * Adds property paths for the specified type to be used for projection. If property paths
         * are added for a type, then only the properties referred to will be retrieved for results
         * of that type. If a property path that is specified isn't present in a result, it will be
         * ignored for that result. Property paths cannot be null.
         *
         * <p>If no property paths are added for a particular type, then all properties of results
         * of that type will be retrieved.
         *
         * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD},
         * then those property paths will apply to all results, excepting any types that have their
         * own, specific property paths set.
         *
         * <p>{@see SearchSpec.Builder#addProjectionTypePropertyPath(String, String...)}
         *
         * @hide
         */
        @NonNull
        public SearchSpec.Builder addProjectionTypePropertyPaths(
                @NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
            Preconditions.checkState(!mBuilt, "Builder has already been used");
            Preconditions.checkNotNull(schemaType);
            Preconditions.checkNotNull(propertyPaths);
            ArrayList<String> propertyPathsArrayList = new ArrayList<>(propertyPaths.size());
            for (String propertyPath : propertyPaths) {
                Preconditions.checkNotNull(propertyPath);
                propertyPathsArrayList.add(propertyPath);
            }
            mProjectionTypePropertyMasks.putStringArrayList(schemaType, propertyPathsArrayList);
            return this;
        }

        /**
         * Constructs a new {@link SearchSpec} from the contents of this builder.
         *
@@ -398,6 +537,7 @@ public final class SearchSpec {
            }
            mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces);
            mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes);
            mBundle.putBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD, mProjectionTypePropertyMasks);
            mBuilt = true;
            return new SearchSpec(mBundle);
        }
+1 −1
Original line number Diff line number Diff line
I0577839bfddf95a555399df441d317b00c7c7c48
Idd770a064edfeb6dc648571fc6706c087b8e605a
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.GlobalSearchSession;
import android.app.appsearch.GlobalSearchSessionShim;
import android.app.appsearch.SearchResults;
import android.app.appsearch.SearchResultsShim;
import android.app.appsearch.SearchSpec;
@@ -40,7 +41,7 @@ import java.util.concurrent.Executors;
 * a consistent interface.
 * @hide
 */
public class GlobalSearchSessionShimImpl {
public class GlobalSearchSessionShimImpl implements GlobalSearchSessionShim {
    private final GlobalSearchSession mGlobalSearchSession;
    private final ExecutorService mExecutor;

@@ -64,6 +65,7 @@ public class GlobalSearchSessionShimImpl {
    }

    @NonNull
    @Override
    public SearchResultsShim query(
            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
        SearchResults searchResults =
+4 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.appsearch.testing;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchSessionShim;
@@ -25,8 +26,6 @@ import android.app.appsearch.GetByUriRequest;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResultsShim;

import junit.framework.AssertionFailedError;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
@@ -36,9 +35,9 @@ public class AppSearchTestUtils {
    public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess(
            Future<AppSearchBatchResult<K, V>> future) throws Exception {
        AppSearchBatchResult<K, V> result = future.get();
        if (!result.isSuccess()) {
            throw new AssertionFailedError("AppSearchBatchResult not successful: " + result);
        }
        assertWithMessage("AppSearchBatchResult not successful: " + result)
                .that(result.isSuccess())
                .isTrue();
        return result;
    }

Loading