Merge "Update framework from jetpack." into sc-dev

This commit is contained in:
Alexander Dorokhine
2021-02-25 02:35:57 +00:00
committed by Android (Google) Code Review
10 changed files with 229 additions and 244 deletions

View File

@@ -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");

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
* 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.
* 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 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.
*
* <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.
* @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

View File

@@ -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}.

View File

@@ -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.
*/

View File

@@ -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 {

View File

@@ -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>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 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() {

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")
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() {

View File

@@ -1 +1 @@
I895f5fb3bcb4be0642c6193000e57d80aafe2166
I593dfd22279739e5f578e07d36a55cf02ee942c5

View File

@@ -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.

View File

@@ -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