Merge "Update framework from jetpack." into sc-dev am: b97100acaa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13690133

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I1ce625ea8a8d427d4d8c95976bb94b6eb4e5fc5d
This commit is contained in:
Alexander Dorokhine
2021-02-25 03:25:17 +00:00
committed by Automerger Merge Worker
10 changed files with 229 additions and 244 deletions

View File

@@ -28,11 +28,19 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
/** /**
* Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple * Provides results for AppSearch batch operations which encompass multiple documents.
* inputs.
* *
* @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}. * <p>Individual results of a batch operation are separated into two maps: one for successes and one
* @param <ValueType> The type of result objects associated with the keys. * 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 { public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable {
@NonNull private final Map<KeyType, ValueType> mSuccesses; @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 * Returns a {@link Map} of keys mapped to instances of the value type for all successful
* AppSearchResult}s they produced. * 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}. * <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 * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed
* produced. * individual results.
* *
* <p>The values of the {@link Map} will not be {@code null}. * <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}. * <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. * Builder for {@link AppSearchBatchResult} objects.
* *
* @param <KeyType> The type of keys. * <p>Once {@link #build} is called, the instance can no longer be used.
* @param <ValueType> The type of result objects associated with the keys. *
* @hide * @hide
*/ */
public static final class Builder<KeyType, ValueType> { public static final class Builder<KeyType, ValueType> {
@@ -160,9 +172,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
private boolean mBuilt = false; 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. * <p>Any previous mapping for a key, whether success or failure, is deleted.
*
* @throws IllegalStateException if the builder has already been used.
*/ */
@NonNull @NonNull
public Builder<KeyType, ValueType> setSuccess( 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. * <p>Any previous mapping for a key, whether success or failure, is deleted.
*
* @throws IllegalStateException if the builder has already been used.
*/ */
@NonNull @NonNull
public Builder<KeyType, ValueType> setFailure( 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. * <p>Any previous mapping for a key, whether success or failure, is deleted.
*
* @throws IllegalStateException if the builder has already been used.
*/ */
@NonNull @NonNull
public Builder<KeyType, ValueType> setResult( public Builder<KeyType, ValueType> setResult(
@@ -209,7 +227,11 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
return this; 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 @NonNull
public AppSearchBatchResult<KeyType, ValueType> build() { public AppSearchBatchResult<KeyType, ValueType> build() {
Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkState(!mBuilt, "Builder has already been used");

View File

@@ -41,7 +41,7 @@ import java.util.function.Consumer;
* Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
* placed and queried. * placed and queried.
* *
* This class is thread safe. * <p>This class is thread safe.
*/ */
public final class AppSearchSession implements Closeable { public final class AppSearchSession implements Closeable {
private static final String TAG = "AppSearchSession"; 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. * 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 * <p>Upon creating an {@link AppSearchSession}, {@link #setSchema} should be called. If the
* to {@link #setSchema}, if any, to determine how to treat existing documents. The following * schema needs to be updated, or it has not been previously set, then the provided schema will
* types of schema modifications are always safe and are made without deleting any existing * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
* documents: * no-op call.
* *
* <ul> * @param request the schema to set or update the AppSearch database to.
* <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.
* @param executor Executor on which to invoke the callback. * @param executor Executor on which to invoke the callback.
* @param callback Callback to receive errors resulting from setting the schema. If the * @param callback Callback to receive errors resulting from setting the schema. If the
* operation succeeds, the callback will be invoked with {@code null}. * operation succeeds, the callback will be invoked with {@code null}.
* @see android.app.appsearch.AppSearchSchema.Migrator * @see android.app.appsearch.AppSearchSchema.Migrator
* @see android.app.appsearch.AppSearchMigrationHelper.Transformer * @see android.app.appsearch.AppSearchMigrationHelper.Transformer
*/ */
// TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
// exposed.
public void setSchema( public void setSchema(
@NonNull SetSchemaRequest request, @NonNull SetSchemaRequest request,
@NonNull @CallbackExecutor Executor executor, @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 * <p>Each {@link GenericDocument} object must have a {@code schemaType} field set to an {@link
* schema type previously registered via the {@link #setSchema} method. * 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 executor Executor on which to invoke the callback.
* @param callback Callback to receive pending result of performing this operation. The keys * @param callback Callback to receive pending result of performing this operation. The keys
* of the returned {@link AppSearchBatchResult} are the URIs of the input * of the returned {@link AppSearchBatchResult} are the URIs of the input

View File

@@ -98,8 +98,7 @@ public class GlobalSearchSession implements Closeable {
* <p>Document access can also be granted to system UIs by specifying {@link * <p>Document access can also be granted to system UIs by specifying {@link
* SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} when building a schema. * SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} when building a schema.
* *
* <p>See {@link AppSearchSession#search} for a detailed explanation on * <p>See {@link AppSearchSession#search} for a detailed explanation on forming a query string.
* forming a query string.
* *
* <p>This method is lightweight. The heavy work will be done in {@link * <p>This method is lightweight. The heavy work will be done in {@link
* SearchResults#getNextPage}. * SearchResults#getNextPage}.

View File

@@ -33,12 +33,16 @@ import java.util.concurrent.Executor;
import java.util.function.Consumer; 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 * <p>Each {@link AppSearchSession#search} operation returns a list of {@link SearchResult} objects,
* on request. * 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. * <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 * <p>The page size is configured by {@link SearchSpec.Builder#setResultCountPerPage}.
* list.
* *
* <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. * @param callback Callback to receive the pending result of performing this operation.
*/ */

View File

@@ -30,8 +30,6 @@ import java.util.List;
/** /**
* Encapsulates a request to index documents into an {@link AppSearchSession} database. * Encapsulates a request to index documents into an {@link AppSearchSession} database.
* *
* <p>@see AppSearchSession#putDocuments
*
* @see AppSearchSession#put * @see AppSearchSession#put
*/ */
public final class PutDocumentsRequest { public final class PutDocumentsRequest {

View File

@@ -32,6 +32,41 @@ import java.util.Set;
/** /**
* Encapsulates a request to update the schema of an {@link AppSearchSession} database. * 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 * @see AppSearchSession#setSchema
*/ */
public final class SetSchemaRequest { public final class SetSchemaRequest {
@@ -54,14 +89,15 @@ public final class SetSchemaRequest {
mForceOverride = forceOverride; mForceOverride = forceOverride;
} }
/** Returns the schemas that are part of this request. */ /** Returns the {@link AppSearchSchema} types that are part of this request. */
@NonNull @NonNull
public Set<AppSearchSchema> getSchemas() { public Set<AppSearchSchema> getSchemas() {
return Collections.unmodifiableSet(mSchemas); 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 @NonNull
public Set<String> getSchemasNotVisibleToSystemUi() { 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 * 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[] * type.
* certificate.
* *
* <p>This method is inefficient to call repeatedly. * <p>It’s inefficient to call this method repeatedly.
*/ */
@NonNull @NonNull
public Map<String, Set<PackageIdentifier>> getSchemasVisibleToPackages() { 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 * Returns a mapping of {@link AppSearchSchema} types to the set of packages that have access to
* type. Each package is represented by a {@link PackageIdentifier}. name and byte[] * that schema type.
* certificate.
* *
* <p>A more efficient version of {@link #getSchemasVisibleToPackages}, but it returns a * <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. * 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; 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 { public static final class Builder {
private final Set<AppSearchSchema> mSchemas = new ArraySet<>(); private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
private final Set<String> mSchemasNotVisibleToSystemUi = new ArraySet<>(); private final Set<String> mSchemasNotVisibleToSystemUi = new ArraySet<>();
@@ -121,9 +159,11 @@ public final class SetSchemaRequest {
private boolean mBuilt = false; private boolean mBuilt = false;
/** /**
* Adds one or more types to the schema. * Adds one or more {@link AppSearchSchema} types 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 @NonNull
public Builder addSchemas(@NonNull AppSearchSchema... schemas) { 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 @NonNull
public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) { 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 schemaType The schema type to set visibility on.
* @param visible Whether the {@code schemaType} will be visible or not. * @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 // Merged list available from getSchemasNotVisibleToSystemUi
@SuppressLint("MissingGetterMatchingBuilder") @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 schemaType The schema type to set visibility on.
* @param visible Whether the {@code schemaType} will be visible or not. * @param visible Whether the {@code schemaType} will be visible or not.
* @param packageIdentifier Represents the package that will be granted visibility. * @param packageIdentifier Represents the package that will be granted visibility.
* @throws IllegalStateException if the builder has already been used.
*/ */
// Merged list available from getSchemasVisibleToPackages // Merged list available from getSchemasVisibleToPackages
@SuppressLint("MissingGetterMatchingBuilder") @SuppressLint("MissingGetterMatchingBuilder")
@@ -224,13 +287,15 @@ public final class SetSchemaRequest {
} }
/** /**
* Configures the {@link SetSchemaRequest} to delete any existing documents that don't * Sets whether or not to override the current schema in the {@link AppSearchSession}
* follow the new schema. * database.
* *
* <p>By default, this is {@code false} and schema incompatibility causes the {@link * <p>Call this method whenever backward incompatible changes need to be made by setting
* AppSearchSession#setSchema} call to fail. * {@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 @NonNull
public Builder setForceOverride(boolean forceOverride) { 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 * @throws IllegalArgumentException if schema types were referenced, but the corresponding
* {@link AppSearchSchema} was never added. * {@link AppSearchSchema} type was never added.
* @throws IllegalStateException if the builder has already been used.
*/ */
@NonNull @NonNull
public SetSchemaRequest build() { public SetSchemaRequest build() {

View File

@@ -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") @GuardedBy("mReadWriteLock")
private SearchResultPage doQueryLocked( private SearchResultPage doQueryLocked(
@NonNull Set<String> prefixes, @NonNull Set<String> prefixes,
@@ -1211,26 +1240,8 @@ public final class AppSearchImpl implements Closeable {
return schemaProto.getSchema(); 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. */ /** 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") @GuardedBy("mReadWriteLock")
@NonNull @NonNull
Set<String> getPrefixesLocked() { Set<String> getPrefixesLocked() {

View File

@@ -1 +1 @@
I895f5fb3bcb4be0642c6193000e57d80aafe2166 I593dfd22279739e5f578e07d36a55cf02ee942c5

View File

@@ -33,90 +33,16 @@ import java.util.Set;
public interface AppSearchSessionShim extends Closeable { 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 * <p>Upon creating an {@link AppSearchSessionShim}, {@link #setSchema} should be called. If the
* to {@link #setSchema}, if any, to determine how to treat existing documents. The following * schema needs to be updated, or it has not been previously set, then the provided schema will
* types of schema modifications are always safe and are made without deleting any existing * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
* documents: * no-op call.
* *
* <ul> * @param request the schema to set or update the AppSearch database to.
* <li>Addition of new types * @return a {@link ListenableFuture} which resolves to a {@link SetSchemaResponse} object.
* <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
*/ */
// TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
// exposed. // exposed.

View File

@@ -28,6 +28,7 @@ import android.app.appsearch.SearchSpec;
import android.app.appsearch.SetSchemaResponse; import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context; import android.content.Context;
import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -55,6 +56,7 @@ import org.junit.rules.TemporaryFolder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class AppSearchImplTest { public class AppSearchImplTest {
@@ -971,21 +973,46 @@ public class AppSearchImplTest {
} }
@Test @Test
public void testHasSchemaType() throws Exception { public void testGetPackageToDatabases() throws Exception {
// Nothing exists yet Map<String, Set<String>> existingMapping = mAppSearchImpl.getPackageToDatabases();
assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse(); Map<String, Set<String>> expectedMapping = new ArrayMap<>();
expectedMapping.putAll(existingMapping);
// Has database1
expectedMapping.put("package1", ImmutableSet.of("database1"));
mAppSearchImpl.setSchema( mAppSearchImpl.setSchema(
"package", "package1",
"database", "database1",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()), Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(), /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(), /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false); /*forceOverride=*/ false);
assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue(); assertThat(mAppSearchImpl.getPackageToDatabases())
.containsExactlyEntriesIn(expectedMapping);
assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema")) // Has both databases
.isFalse(); 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 @Test