diff options
10 files changed, 229 insertions, 244 deletions
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java index 519c14f7bb40..31ab259127c3 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java @@ -28,11 +28,19 @@ import java.util.Collections; import java.util.Map; /** - * Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple - * inputs. + * Provides results for AppSearch batch operations which encompass multiple documents. * - * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}. - * @param <ValueType> The type of result objects associated with the keys. + * <p>Individual results of a batch operation are separated into two maps: one for successes and one + * for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of + * the value type. For failures, {@link #getFailures()} will return a map of keys to {@link + * AppSearchResult} objects. + * + * <p>Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for + * both successes and failures. + * + * @see AppSearchSession#put + * @see AppSearchSession#getByUri + * @see AppSearchSession#remove */ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { @NonNull private final Map<KeyType, ValueType> mSuccesses; @@ -75,8 +83,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl } /** - * Returns a {@link Map} of all successful keys mapped to the successful {@link - * AppSearchResult}s they produced. + * Returns a {@link Map} of keys mapped to instances of the value type for all successful + * individual results. + * + * <p>Example: {@link AppSearchSession#getByUri} returns an {@link AppSearchBatchResult}. Each + * key (a URI of {@code String} type) will map to a {@link GenericDocument} object. * * <p>The values of the {@link Map} will not be {@code null}. */ @@ -86,8 +97,8 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl } /** - * Returns a {@link Map} of all failed keys mapped to the failed {@link AppSearchResult}s they - * produced. + * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed + * individual results. * * <p>The values of the {@link Map} will not be {@code null}. */ @@ -97,7 +108,8 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl } /** - * Returns a {@link Map} of all keys mapped to the {@link AppSearchResult}s they produced. + * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all + * individual results. * * <p>The values of the {@link Map} will not be {@code null}. */ @@ -149,8 +161,8 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl /** * Builder for {@link AppSearchBatchResult} objects. * - * @param <KeyType> The type of keys. - * @param <ValueType> The type of result objects associated with the keys. + * <p>Once {@link #build} is called, the instance can no longer be used. + * * @hide */ public static final class Builder<KeyType, ValueType> { @@ -160,9 +172,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl private boolean mBuilt = false; /** - * Associates the {@code key} with the given successful return value. + * Associates the {@code key} with the provided successful return value. * * <p>Any previous mapping for a key, whether success or failure, is deleted. + * + * @throws IllegalStateException if the builder has already been used. */ @NonNull public Builder<KeyType, ValueType> setSuccess( @@ -173,9 +187,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl } /** - * Associates the {@code key} with the given failure code and error message. + * Associates the {@code key} with the provided failure code and error message. * * <p>Any previous mapping for a key, whether success or failure, is deleted. + * + * @throws IllegalStateException if the builder has already been used. */ @NonNull public Builder<KeyType, ValueType> setFailure( @@ -188,9 +204,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl } /** - * Associates the {@code key} with the given {@code result}. + * Associates the {@code key} with the provided {@code result}. * * <p>Any previous mapping for a key, whether success or failure, is deleted. + * + * @throws IllegalStateException if the builder has already been used. */ @NonNull public Builder<KeyType, ValueType> setResult( @@ -209,7 +227,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl return this; } - /** Builds an {@link AppSearchBatchResult} from the contents of this {@link Builder}. */ + /** + * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}. + * + * @throws IllegalStateException if the builder has already been used. + */ @NonNull public AppSearchBatchResult<KeyType, ValueType> build() { Preconditions.checkState(!mBuilt, "Builder has already been used"); diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java index 3c02d108507c..54f33509072b 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -41,7 +41,7 @@ import java.util.function.Consumer; * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be * placed and queried. * - * This class is thread safe. + * <p>This class is thread safe. */ public final class AppSearchSession implements Closeable { private static final String TAG = "AppSearchSession"; @@ -102,92 +102,23 @@ public final class AppSearchSession implements Closeable { } /** - * Sets the schema that will be used by documents provided to the {@link #put} method. - * - * <p>The schema provided here is compared to the stored copy of the schema previously supplied - * to {@link #setSchema}, if any, to determine how to treat existing documents. The following - * types of schema modifications are always safe and are made without deleting any existing - * documents: - * - * <ul> - * <li>Addition of new types - * <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or - * {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a - * type - * <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property. - * </ul> - * - * <p>The following types of schema changes are not backwards-compatible: - * - * <ul> - * <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 Document} type, changing the schema type of {@code Document}s - * of that property - * <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property). - * <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property. - * </ul> - * - * <p>Supplying a schema with such changes will, by default, result in this call completing its - * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of - * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility. - * In this case the previously set schema will remain active. - * - * <p>If you need to make non-backwards-compatible changes as described above, you can either: - * - * <ul> - * <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In - * this case, instead of completing its future with an {@link - * android.app.appsearch.exceptions.AppSearchException} with the {@link - * AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not - * compatible with the new schema will be deleted and the incompatible schema will be - * applied. Incompatible types and deleted types will be set into {@link - * SetSchemaResponse#getIncompatibleTypes()} and {@link - * SetSchemaResponse#getDeletedTypes()}, respectively. - * <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type - * and make no deletion. The migrator will migrate documents from it's old schema version - * to the new version. Migrated types will be set into both {@link - * SetSchemaResponse#getIncompatibleTypes()} and {@link - * SetSchemaResponse#getMigratedTypes()}. See the migration section below. - * </ul> - * - * <p>It is a no-op to set the same schema as has been previously set; this is handled - * efficiently. - * - * <p>By default, documents are visible on platform surfaces. To opt out, call {@code - * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any - * visibility settings apply only to the schemas that are included in the {@code request}. - * Visibility settings for a schema type do not apply or persist across {@link - * SetSchemaRequest}s. - * - * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old - * schema. You can save your documents by setting {@link - * android.app.appsearch.AppSearchSchema.Migrator} via the {@link - * SetSchemaRequest.Builder#setMigrator} for each type you want to save. - * - * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link - * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version - * number of the schema stored in AppSearch is different with the version in the request. + * Sets the schema that represents the organizational structure of data within the AppSearch + * database. * - * <p>If any error or Exception occurred in the {@link - * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link - * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link - * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be - * terminated, the setSchema request will be rejected unless the schema changes are - * backwards-compatible, and stored documents won't have any observable changes. + * <p>Upon creating an {@link AppSearchSession}, {@link #setSchema} should be called. If the + * schema needs to be updated, or it has not been previously set, then the provided schema will + * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a + * no-op call. * - * @param request The schema update request. + * @param request the schema to set or update the AppSearch database to. * @param executor Executor on which to invoke the callback. * @param callback Callback to receive errors resulting from setting the schema. If the * operation succeeds, the callback will be invoked with {@code null}. * @see android.app.appsearch.AppSearchSchema.Migrator * @see android.app.appsearch.AppSearchMigrationHelper.Transformer */ + // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are + // exposed. public void setSchema( @NonNull SetSchemaRequest request, @NonNull @CallbackExecutor Executor executor, @@ -280,12 +211,13 @@ public final class AppSearchSession implements Closeable { } /** - * Indexes documents into AppSearch. + * Indexes documents into the {@link AppSearchSession} database. * - * <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. + * <p>Each {@link GenericDocument} object must have a {@code schemaType} field set to an {@link + * AppSearchSchema} type that has been previously registered by calling the {@link #setSchema} + * method. * - * @param request {@link PutDocumentsRequest} containing documents to be indexed + * @param request containing documents to be indexed. * @param executor Executor on which to invoke the callback. * @param callback Callback to receive pending result of performing this operation. The keys * of the returned {@link AppSearchBatchResult} are the URIs of the input diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java index 09bca4fb3b9d..93b102b864f4 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java @@ -98,8 +98,7 @@ public class GlobalSearchSession implements Closeable { * <p>Document access can also be granted to system UIs by specifying {@link * SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} when building a schema. * - * <p>See {@link AppSearchSession#search} for a detailed explanation on - * forming a query string. + * <p>See {@link AppSearchSession#search} for a detailed explanation on forming a query string. * * <p>This method is lightweight. The heavy work will be done in {@link * SearchResults#getNextPage}. diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java index a63e01555f6c..e9e978eea943 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java @@ -33,12 +33,16 @@ import java.util.concurrent.Executor; import java.util.function.Consumer; /** - * SearchResults are a returned object from a query API. + * Encapsulates results of a search operation. * - * <p>Each {@link SearchResult} contains a document and may contain other fields like snippets based - * on request. + * <p>Each {@link AppSearchSession#search} operation returns a list of {@link SearchResult} objects, + * referred to as a "page", limited by the size configured by {@link + * SearchSpec.Builder#setResultCountPerPage}. * - * <p>Should close this object after finish fetching results. + * <p>To fetch a page of results, call {@link #getNextPage}. + * + * <p>All instances of {@link SearchResults} must call {@link SearchResults#close()} after the + * results are fetched. * * <p>This class is not thread safe. */ @@ -87,12 +91,12 @@ public class SearchResults implements Closeable { } /** - * Gets a whole page of {@link SearchResult}s. + * Retrieves the next page of {@link SearchResult} objects. * - * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an empty - * list. + * <p>The page size is configured by {@link SearchSpec.Builder#setResultCountPerPage}. * - * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}. + * <p>Continue calling this method to access results until it returns an empty list, signifying + * there are no more results. * * @param callback Callback to receive the pending result of performing this operation. */ diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java index 57700f89403e..01473be062bc 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java @@ -30,8 +30,6 @@ import java.util.List; /** * Encapsulates a request to index documents into an {@link AppSearchSession} database. * - * <p>@see AppSearchSession#putDocuments - * * @see AppSearchSession#put */ public final class PutDocumentsRequest { diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java index 2caa94a5ef07..426a903981b3 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java @@ -32,6 +32,41 @@ import java.util.Set; /** * Encapsulates a request to update the schema of an {@link AppSearchSession} database. * + * <p>The schema is composed of a collection of {@link AppSearchSchema} objects, each of which + * defines a unique type of data. + * + * <p>The first call to SetSchemaRequest will set the provided schema and store it within the {@link + * AppSearchSession} database. + * + * <p>Subsequent calls will compare the provided schema to the previously saved schema, to determine + * how to treat existing documents. + * + * <p>The following types of schema modifications are always safe and are made without deleting any + * existing documents: + * + * <ul> + * <li>Addition of new {@link AppSearchSchema} types + * <li>Addition of new properties to an existing {@link AppSearchSchema} type + * <li>Changing the cardinality of a property to be less restrictive + * </ul> + * + * <p>The following types of schema changes are not backwards compatible: + * + * <ul> + * <li>Removal of an existing {@link AppSearchSchema} type + * <li>Removal of a property from an existing {@link AppSearchSchema} type + * <li>Changing the data type of an existing property + * <li>Changing the cardinality of a property to be more restrictive + * </ul> + * + * <p>Providing a schema with incompatible changes, will throw an {@link + * android.app.appsearch.exceptions.AppSearchException}, with a message describing the + * incompatibility. As a result, the previously set schema will remain unchanged. + * + * <p>Backward incompatible changes can be made by setting {@link + * SetSchemaRequest.Builder#setForceOverride} method to {@code true}. This deletes all documents + * that are incompatible with the new schema. The new schema is then saved and persisted to disk. + * * @see AppSearchSession#setSchema */ public final class SetSchemaRequest { @@ -54,14 +89,15 @@ public final class SetSchemaRequest { mForceOverride = forceOverride; } - /** Returns the schemas that are part of this request. */ + /** Returns the {@link AppSearchSchema} types that are part of this request. */ @NonNull public Set<AppSearchSchema> getSchemas() { return Collections.unmodifiableSet(mSchemas); } /** - * Returns the set of schema types that have opted out of being visible on system UI surfaces. + * Returns all the schema types that are opted out of being displayed and visible on any system + * UI surface. */ @NonNull public Set<String> getSchemasNotVisibleToSystemUi() { @@ -70,10 +106,9 @@ public final class SetSchemaRequest { /** * Returns a mapping of schema types to the set of packages that have access to that schema - * type. Each package is represented by a {@link PackageIdentifier}. name and byte[] - * certificate. + * type. * - * <p>This method is inefficient to call repeatedly. + * <p>It’s inefficient to call this method repeatedly. */ @NonNull public Map<String, Set<PackageIdentifier>> getSchemasVisibleToPackages() { @@ -91,9 +126,8 @@ public final class SetSchemaRequest { } /** - * Returns a mapping of schema types to the set of packages that have access to that schema - * type. Each package is represented by a {@link PackageIdentifier}. name and byte[] - * certificate. + * Returns a mapping of {@link AppSearchSchema} types to the set of packages that have access to + * that schema type. * * <p>A more efficient version of {@link #getSchemasVisibleToPackages}, but it returns a * modifiable map. This is not meant to be unhidden and should only be used by internal classes. @@ -110,7 +144,11 @@ public final class SetSchemaRequest { return mForceOverride; } - /** Builder for {@link SetSchemaRequest} objects. */ + /** + * Builder for {@link SetSchemaRequest} objects. + * + * <p>Once {@link #build} is called, the instance can no longer be used. + */ public static final class Builder { private final Set<AppSearchSchema> mSchemas = new ArraySet<>(); private final Set<String> mSchemasNotVisibleToSystemUi = new ArraySet<>(); @@ -121,9 +159,11 @@ public final class SetSchemaRequest { private boolean mBuilt = false; /** - * Adds one or more types to the schema. + * Adds one or more {@link AppSearchSchema} types to the schema. + * + * <p>An {@link AppSearchSchema} object represents one type of structured data. * - * <p>Any documents of these types will be visible on system UI surfaces by default. + * @throws IllegalStateException if the builder has already been used. */ @NonNull public Builder addSchemas(@NonNull AppSearchSchema... schemas) { @@ -132,9 +172,11 @@ public final class SetSchemaRequest { } /** - * Adds one or more types to the schema. + * Adds a collection of {@link AppSearchSchema} objects to the schema. * - * <p>Any documents of these types will be visible on system UI surfaces by default. + * <p>An {@link AppSearchSchema} object represents one type of structured data. + * + * @throws IllegalStateException if the builder has already been used. */ @NonNull public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) { @@ -145,10 +187,17 @@ public final class SetSchemaRequest { } /** - * Sets visibility on system UI surfaces for the given {@code schemaType}. + * Sets whether or not documents from the provided {@code schemaType} will be displayed and + * visible on any system UI surface. + * + * <p>This setting applies to the provided {@code schemaType} only, and does not persist + * across {@link AppSearchSession#setSchema} calls. + * + * <p>By default, documents are displayed and visible on system UI surfaces. * * @param schemaType The schema type to set visibility on. * @param visible Whether the {@code schemaType} will be visible or not. + * @throws IllegalStateException if the builder has already been used. */ // Merged list available from getSchemasNotVisibleToSystemUi @SuppressLint("MissingGetterMatchingBuilder") @@ -167,11 +216,25 @@ public final class SetSchemaRequest { } /** - * Sets visibility for a package for the given {@code schemaType}. + * Sets whether or not documents from the provided {@code schemaType} can be read by the + * specified package. + * + * <p>Each package is represented by a {@link PackageIdentifier}, containing a package name + * and a byte array of type {@link android.content.pm.PackageManager#CERT_INPUT_SHA256}. + * + * <p>To opt into one-way data sharing with another application, the developer will need to + * explicitly grant the other application’s package name and certificate Read access to its + * data. + * + * <p>For two-way data sharing, both applications need to explicitly grant Read access to + * one another. + * + * <p>By default, data sharing between applications is disabled. * * @param schemaType The schema type to set visibility on. * @param visible Whether the {@code schemaType} will be visible or not. * @param packageIdentifier Represents the package that will be granted visibility. + * @throws IllegalStateException if the builder has already been used. */ // Merged list available from getSchemasVisibleToPackages @SuppressLint("MissingGetterMatchingBuilder") @@ -224,13 +287,15 @@ public final class SetSchemaRequest { } /** - * Configures the {@link SetSchemaRequest} to delete any existing documents that don't - * follow the new schema. + * Sets whether or not to override the current schema in the {@link AppSearchSession} + * database. * - * <p>By default, this is {@code false} and schema incompatibility causes the {@link - * AppSearchSession#setSchema} call to fail. + * <p>Call this method whenever backward incompatible changes need to be made by setting + * {@code forceOverride} to {@code true}. As a result, during execution of the setSchema + * operation, all documents that are incompatible with the new schema will be deleted and + * the new schema will be saved and persisted. * - * @see AppSearchSession#setSchema + * <p>By default, this is {@code false}. */ @NonNull public Builder setForceOverride(boolean forceOverride) { @@ -239,10 +304,11 @@ public final class SetSchemaRequest { } /** - * Builds a new {@link SetSchemaRequest}. + * Builds a new {@link SetSchemaRequest} object. * - * @throws IllegalArgumentException If schema types were referenced, but the corresponding - * {@link AppSearchSchema} was never added. + * @throws IllegalArgumentException if schema types were referenced, but the corresponding + * {@link AppSearchSchema} type was never added. + * @throws IllegalStateException if the builder has already been used. */ @NonNull public SetSchemaRequest build() { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java index 6c2e30e98877..e2c211b7d303 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java @@ -654,6 +654,35 @@ public final class AppSearchImpl implements Closeable { } } + /** + * Returns a mapping of package names to all the databases owned by that package. + * + * <p>This method is inefficient to call repeatedly. + */ + @NonNull + public Map<String, Set<String>> getPackageToDatabases() { + mReadWriteLock.readLock().lock(); + try { + Map<String, Set<String>> packageToDatabases = new ArrayMap<>(); + for (String prefix : mSchemaMapLocked.keySet()) { + String packageName = getPackageName(prefix); + + Set<String> databases = packageToDatabases.get(packageName); + if (databases == null) { + databases = new ArraySet<>(); + packageToDatabases.put(packageName, databases); + } + + String databaseName = getDatabaseName(prefix); + databases.add(databaseName); + } + + return packageToDatabases; + } finally { + mReadWriteLock.readLock().unlock(); + } + } + @GuardedBy("mReadWriteLock") private SearchResultPage doQueryLocked( @NonNull Set<String> prefixes, @@ -1211,26 +1240,8 @@ public final class AppSearchImpl implements Closeable { return schemaProto.getSchema(); } - /** - * Returns true if the {@code packageName} and {@code databaseName} has the {@code schemaType} - */ - @GuardedBy("mReadWriteLock") - boolean hasSchemaTypeLocked( - @NonNull String packageName, @NonNull String databaseName, @NonNull String schemaType) { - Preconditions.checkNotNull(packageName); - Preconditions.checkNotNull(databaseName); - Preconditions.checkNotNull(schemaType); - - String prefix = createPrefix(packageName, databaseName); - Set<String> schemaTypes = mSchemaMapLocked.get(prefix); - if (schemaTypes == null) { - return false; - } - - return schemaTypes.contains(prefix + schemaType); - } - /** Returns a set of all prefixes AppSearchImpl knows about. */ + // TODO(b/180058203): Remove this method once platform has switched away from using this method. @GuardedBy("mReadWriteLock") @NonNull Set<String> getPrefixesLocked() { diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt index fc0299ef88af..2c9477a5d76b 100644 --- a/apex/appsearch/synced_jetpack_changeid.txt +++ b/apex/appsearch/synced_jetpack_changeid.txt @@ -1 +1 @@ -I895f5fb3bcb4be0642c6193000e57d80aafe2166 +I593dfd22279739e5f578e07d36a55cf02ee942c5 diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java index 34c7ccbd4df1..1428fb1d3c7a 100644 --- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java @@ -33,90 +33,16 @@ import java.util.Set; public interface AppSearchSessionShim extends Closeable { /** - * Sets the schema that will be used by documents provided to the {@link #put} method. + * Sets the schema that represents the organizational structure of data within the AppSearch + * database. * - * <p>The schema provided here is compared to the stored copy of the schema previously supplied - * to {@link #setSchema}, if any, to determine how to treat existing documents. The following - * types of schema modifications are always safe and are made without deleting any existing - * documents: + * <p>Upon creating an {@link AppSearchSessionShim}, {@link #setSchema} should be called. If the + * schema needs to be updated, or it has not been previously set, then the provided schema will + * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a + * no-op call. * - * <ul> - * <li>Addition of new types - * <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or - * {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a - * type - * <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property. - * </ul> - * - * <p>The following types of schema changes are not backwards-compatible: - * - * <ul> - * <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 Document} type, changing the schema type of {@code Document}s - * of that property - * <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link - * AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property). - * <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property. - * </ul> - * - * <p>Supplying a schema with such changes will, by default, result in this call completing its - * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of - * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility. - * In this case the previously set schema will remain active. - * - * <p>If you need to make non-backwards-compatible changes as described above, you can either: - * - * <ul> - * <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In - * this case, instead of completing its future with an {@link - * android.app.appsearch.exceptions.AppSearchException} with the {@link - * AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not - * compatible with the new schema will be deleted and the incompatible schema will be - * applied. Incompatible types and deleted types will be set into {@link - * SetSchemaResponse#getIncompatibleTypes()} and {@link - * SetSchemaResponse#getDeletedTypes()}, respectively. - * <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type - * and make no deletion. The migrator will migrate documents from it's old schema version - * to the new version. Migrated types will be set into both {@link - * SetSchemaResponse#getIncompatibleTypes()} and {@link - * SetSchemaResponse#getMigratedTypes()}. See the migration section below. - * </ul> - * - * <p>It is a no-op to set the same schema as has been previously set; this is handled - * efficiently. - * - * <p>By default, documents are visible on platform surfaces. To opt out, call {@code - * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any - * visibility settings apply only to the schemas that are included in the {@code request}. - * Visibility settings for a schema type do not apply or persist across {@link - * SetSchemaRequest}s. - * - * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old - * schema. You can save your documents by setting {@link - * android.app.appsearch.AppSearchSchema.Migrator} via the {@link - * SetSchemaRequest.Builder#setMigrator} for each type you want to save. - * - * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link - * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version - * number of the schema stored in AppSearch is different with the version in the request. - * - * <p>If any error or Exception occurred in the {@link - * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link - * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link - * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be - * terminated, the setSchema request will be rejected unless the schema changes are - * backwards-compatible, and stored documents won't have any observable changes. - * - * @param request The schema update request. - * @return A {@link ListenableFuture} with exception if we hit any error. Or the pending {@link - * SetSchemaResponse} of performing this operation, if the schema has been successfully set. - * @see android.app.appsearch.AppSearchSchema.Migrator - * @see android.app.appsearch.AppSearchMigrationHelper.Transformer + * @param request the schema to set or update the AppSearch database to. + * @return a {@link ListenableFuture} which resolves to a {@link SetSchemaResponse} object. */ // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are // exposed. diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index 73b0105210c4..6890ed1688bb 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -28,6 +28,7 @@ import android.app.appsearch.SearchSpec; import android.app.appsearch.SetSchemaResponse; import android.app.appsearch.exceptions.AppSearchException; import android.content.Context; +import android.util.ArrayMap; import android.util.ArraySet; import androidx.test.core.app.ApplicationProvider; @@ -55,6 +56,7 @@ import org.junit.rules.TemporaryFolder; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; public class AppSearchImplTest { @@ -971,21 +973,46 @@ public class AppSearchImplTest { } @Test - public void testHasSchemaType() throws Exception { - // Nothing exists yet - assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse(); + public void testGetPackageToDatabases() throws Exception { + Map<String, Set<String>> existingMapping = mAppSearchImpl.getPackageToDatabases(); + Map<String, Set<String>> expectedMapping = new ArrayMap<>(); + expectedMapping.putAll(existingMapping); + // Has database1 + expectedMapping.put("package1", ImmutableSet.of("database1")); mAppSearchImpl.setSchema( - "package", - "database", - Collections.singletonList(new AppSearchSchema.Builder("Schema").build()), + "package1", + "database1", + Collections.singletonList(new AppSearchSchema.Builder("schema").build()), /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(), /*schemasPackageAccessible=*/ Collections.emptyMap(), /*forceOverride=*/ false); - assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue(); + assertThat(mAppSearchImpl.getPackageToDatabases()) + .containsExactlyEntriesIn(expectedMapping); - assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema")) - .isFalse(); + // Has both databases + expectedMapping.put("package1", ImmutableSet.of("database1", "database2")); + mAppSearchImpl.setSchema( + "package1", + "database2", + Collections.singletonList(new AppSearchSchema.Builder("schema").build()), + /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(), + /*schemasPackageAccessible=*/ Collections.emptyMap(), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getPackageToDatabases()) + .containsExactlyEntriesIn(expectedMapping); + + // Has both packages + expectedMapping.put("package2", ImmutableSet.of("database1")); + mAppSearchImpl.setSchema( + "package2", + "database1", + Collections.singletonList(new AppSearchSchema.Builder("schema").build()), + /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(), + /*schemasPackageAccessible=*/ Collections.emptyMap(), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getPackageToDatabases()) + .containsExactlyEntriesIn(expectedMapping); } @Test |