diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt index 401624f591978..ebb00707354bc 100644 --- a/apex/appsearch/framework/api/current.txt +++ b/apex/appsearch/framework/api/current.txt @@ -43,6 +43,15 @@ package android.app.appsearch { method @IntRange(from=0) public int getVersion(); } + public static final class AppSearchSchema.BooleanPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + } + + public static final class AppSearchSchema.BooleanPropertyConfig.Builder { + ctor public AppSearchSchema.BooleanPropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.BooleanPropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.BooleanPropertyConfig.Builder setCardinality(int); + } + public static final class AppSearchSchema.Builder { ctor public AppSearchSchema.Builder(@NonNull String); method @NonNull public android.app.appsearch.AppSearchSchema.Builder addProperty(@NonNull android.app.appsearch.AppSearchSchema.PropertyConfig); @@ -50,22 +59,58 @@ package android.app.appsearch { method @NonNull public android.app.appsearch.AppSearchSchema.Builder setVersion(@IntRange(from=0) int); } - public static final class AppSearchSchema.PropertyConfig { + public static final class AppSearchSchema.BytesPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + } + + public static final class AppSearchSchema.BytesPropertyConfig.Builder { + ctor public AppSearchSchema.BytesPropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.BytesPropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.BytesPropertyConfig.Builder setCardinality(int); + } + + public static final class AppSearchSchema.DocumentPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + method @NonNull public String getSchemaType(); + method public boolean isIndexNestedProperties(); + } + + public static final class AppSearchSchema.DocumentPropertyConfig.Builder { + ctor public AppSearchSchema.DocumentPropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setCardinality(int); + method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setIndexNestedProperties(boolean); + method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setSchemaType(@NonNull String); + } + + public static final class AppSearchSchema.DoublePropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + } + + public static final class AppSearchSchema.DoublePropertyConfig.Builder { + ctor public AppSearchSchema.DoublePropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.DoublePropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.DoublePropertyConfig.Builder setCardinality(int); + } + + public static final class AppSearchSchema.Int64PropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + } + + public static final class AppSearchSchema.Int64PropertyConfig.Builder { + ctor public AppSearchSchema.Int64PropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.Int64PropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.Int64PropertyConfig.Builder setCardinality(int); + } + + public abstract static class AppSearchSchema.PropertyConfig { method public int getCardinality(); method public int getDataType(); - method public int getIndexingType(); method @NonNull public String getName(); - method @Nullable public String getSchemaType(); - method public int getTokenizerType(); field public static final int CARDINALITY_OPTIONAL = 2; // 0x2 field public static final int CARDINALITY_REPEATED = 1; // 0x1 field public static final int CARDINALITY_REQUIRED = 3; // 0x3 - field public static final int DATA_TYPE_BOOLEAN = 4; // 0x4 - field public static final int DATA_TYPE_BYTES = 5; // 0x5 - field public static final int DATA_TYPE_DOCUMENT = 6; // 0x6 - field public static final int DATA_TYPE_DOUBLE = 3; // 0x3 - field public static final int DATA_TYPE_INT64 = 2; // 0x2 - field public static final int DATA_TYPE_STRING = 1; // 0x1 + } + + public static final class AppSearchSchema.StringPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig { + method public int getIndexingType(); + method public int getTokenizerType(); field public static final int INDEXING_TYPE_EXACT_TERMS = 1; // 0x1 field public static final int INDEXING_TYPE_NONE = 0; // 0x0 field public static final int INDEXING_TYPE_PREFIXES = 2; // 0x2 @@ -73,14 +118,12 @@ package android.app.appsearch { field public static final int TOKENIZER_TYPE_PLAIN = 1; // 0x1 } - public static final class AppSearchSchema.PropertyConfig.Builder { - ctor public AppSearchSchema.PropertyConfig.Builder(@NonNull String); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig build(); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setCardinality(int); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setDataType(int); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setIndexingType(int); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setSchemaType(@NonNull String); - method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int); + public static final class AppSearchSchema.StringPropertyConfig.Builder { + ctor public AppSearchSchema.StringPropertyConfig.Builder(@NonNull String); + method @NonNull public android.app.appsearch.AppSearchSchema.StringPropertyConfig build(); + method @NonNull public android.app.appsearch.AppSearchSchema.StringPropertyConfig.Builder setCardinality(int); + method @NonNull public android.app.appsearch.AppSearchSchema.StringPropertyConfig.Builder setIndexingType(int); + method @NonNull public android.app.appsearch.AppSearchSchema.StringPropertyConfig.Builder setTokenizerType(int); } public final class AppSearchSession implements java.io.Closeable { @@ -143,11 +186,15 @@ package android.app.appsearch { public final class GetByUriRequest { method @NonNull public String getNamespace(); + method @NonNull public java.util.Map> getProjections(); method @NonNull public java.util.Set getUris(); + field public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*"; } public static final class GetByUriRequest.Builder { ctor public GetByUriRequest.Builder(); + method @NonNull public android.app.appsearch.GetByUriRequest.Builder addProjection(@NonNull String, @NonNull java.lang.String...); + method @NonNull public android.app.appsearch.GetByUriRequest.Builder addProjection(@NonNull String, @NonNull java.util.Collection); method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUri(@NonNull java.lang.String...); method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUri(@NonNull java.util.Collection); method @NonNull public android.app.appsearch.GetByUriRequest build(); diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index ed4e0347b6a48..814800ebe41ea 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -330,6 +330,7 @@ public class AppSearchManager { DEFAULT_DATABASE_NAME, request.getNamespace(), uris, + request.getProjectionsVisibleToPackagesInternal(), mContext.getUserId(), new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java index 928bf7d45ee2f..c4c123c3df0c8 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -311,8 +311,13 @@ public final class AppSearchSession implements Closeable { Objects.requireNonNull(callback); Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed"); try { - mService.getDocuments(mPackageName, mDatabaseName, request.getNamespace(), - new ArrayList<>(request.getUris()), mUserId, + mService.getDocuments( + mPackageName, + mDatabaseName, + request.getNamespace(), + new ArrayList<>(request.getUris()), + request.getProjectionsVisibleToPackagesInternal(), + mUserId, new IAppSearchBatchResultCallback.Stub() { public void onResult(AppSearchBatchResult result) { executor.execute(() -> { diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index be76f42f19ad0..68ae23f9a9dbf 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -97,6 +97,8 @@ interface IAppSearchManager { * @param databaseName The databaseName this document resides in. * @param namespace The namespace this document resides in. * @param uris The URIs of the documents to retrieve + * @param typePropertyPaths A map of schema type to a list of property paths to return in the + * result. * @param userId Id of the calling user * @param callback * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} @@ -110,6 +112,7 @@ interface IAppSearchManager { in String databaseName, in String namespace, in List uris, + in Map> typePropertyPaths, in int userId, in IAppSearchBatchResultCallback callback); diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java index 9ca363ed9008e..d3949047ec5db 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java @@ -19,6 +19,7 @@ package android.app.appsearch; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.appsearch.AppSearchSchema.PropertyConfig; +import android.app.appsearch.AppSearchSchema.StringPropertyConfig; /** * Encapsulates a {@link GenericDocument} that represent an email. @@ -41,46 +42,40 @@ public class AppSearchEmail extends GenericDocument { public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE) .addProperty( - new PropertyConfig.Builder(KEY_FROM) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_FROM) .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .addProperty( - new PropertyConfig.Builder(KEY_TO) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_TO) .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .addProperty( - new PropertyConfig.Builder(KEY_CC) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_CC) .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .addProperty( - new PropertyConfig.Builder(KEY_BCC) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_BCC) .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .addProperty( - new PropertyConfig.Builder(KEY_SUBJECT) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_SUBJECT) .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .addProperty( - new PropertyConfig.Builder(KEY_BODY) - .setDataType(PropertyConfig.DATA_TYPE_STRING) + new StringPropertyConfig.Builder(KEY_BODY) .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build()) .build(); diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java index 1f882ec64844d..7f5d2020a6f41 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java @@ -98,7 +98,7 @@ public final class AppSearchSchema { } List ret = new ArrayList<>(propertyBundles.size()); for (int i = 0; i < propertyBundles.size(); i++) { - ret.add(new PropertyConfig(propertyBundles.get(i))); + ret.add(PropertyConfig.fromBundle(propertyBundles.get(i))); } return ret; } @@ -210,18 +210,15 @@ public final class AppSearchSchema { } /** - * Configuration for a single property (field) of a document type. + * Common configuration for a single property (field) in a Document. * *

For example, an {@code EmailMessage} would be a type and the {@code subject} would be a * property. */ - public static final class PropertyConfig { - private static final String NAME_FIELD = "name"; - private static final String DATA_TYPE_FIELD = "dataType"; - private static final String SCHEMA_TYPE_FIELD = "schemaType"; - private static final String CARDINALITY_FIELD = "cardinality"; - private static final String INDEXING_TYPE_FIELD = "indexingType"; - private static final String TOKENIZER_TYPE_FIELD = "tokenizerType"; + public abstract static class PropertyConfig { + static final String NAME_FIELD = "name"; + static final String DATA_TYPE_FIELD = "dataType"; + static final String CARDINALITY_FIELD = "cardinality"; /** * Physical data-types of the contents of the property. @@ -242,18 +239,31 @@ public final class AppSearchSchema { @Retention(RetentionPolicy.SOURCE) public @interface DataType {} + /** @hide */ public static final int DATA_TYPE_STRING = 1; + + /** @hide */ public static final int DATA_TYPE_INT64 = 2; + + /** @hide */ public static final int DATA_TYPE_DOUBLE = 3; + + /** @hide */ public static final int DATA_TYPE_BOOLEAN = 4; - /** Unstructured BLOB. */ + /** + * Unstructured BLOB. + * + * @hide + */ public static final int DATA_TYPE_BYTES = 5; /** * Indicates that the property is itself a {@link GenericDocument}, making it part of a * hierarchical schema. Any property using this DataType MUST have a valid {@link * PropertyConfig#getSchemaType}. + * + * @hide */ public static final int DATA_TYPE_DOCUMENT = 6; @@ -282,6 +292,97 @@ public final class AppSearchSchema { /** Exactly one value [1]. */ public static final int CARDINALITY_REQUIRED = 3; + final Bundle mBundle; + + @Nullable private Integer mHashCode; + + PropertyConfig(@NonNull Bundle bundle) { + mBundle = Preconditions.checkNotNull(bundle); + } + + @Override + public String toString() { + return mBundle.toString(); + } + + /** Returns the name of this property. */ + @NonNull + public String getName() { + return mBundle.getString(NAME_FIELD, ""); + } + + /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */ + public @DataType int getDataType() { + return mBundle.getInt(DATA_TYPE_FIELD, -1); + } + + /** + * Returns the cardinality of the property (whether it is optional, required or repeated). + */ + public @Cardinality int getCardinality() { + return mBundle.getInt(CARDINALITY_FIELD, -1); + } + + @Override + public boolean equals(@Nullable Object other) { + if (this == other) { + return true; + } + if (!(other instanceof PropertyConfig)) { + return false; + } + PropertyConfig otherProperty = (PropertyConfig) other; + return BundleUtil.deepEquals(this.mBundle, otherProperty.mBundle); + } + + @Override + public int hashCode() { + if (mHashCode == null) { + mHashCode = BundleUtil.deepHashCode(mBundle); + } + return mHashCode; + } + + /** + * Converts a {@link Bundle} into a {@link PropertyConfig} depending on its internal data + * type. + * + *

The bundle is not cloned. + * + * @throws IllegalArgumentException if the bundle does no contain a recognized value in its + * {@code DATA_TYPE_FIELD}. + * @hide + */ + @NonNull + public static PropertyConfig fromBundle(@NonNull Bundle propertyBundle) { + switch (propertyBundle.getInt(PropertyConfig.DATA_TYPE_FIELD)) { + case PropertyConfig.DATA_TYPE_STRING: + return new StringPropertyConfig(propertyBundle); + case PropertyConfig.DATA_TYPE_INT64: + return new Int64PropertyConfig(propertyBundle); + case PropertyConfig.DATA_TYPE_DOUBLE: + return new DoublePropertyConfig(propertyBundle); + case PropertyConfig.DATA_TYPE_BOOLEAN: + return new BooleanPropertyConfig(propertyBundle); + case PropertyConfig.DATA_TYPE_BYTES: + return new BytesPropertyConfig(propertyBundle); + case PropertyConfig.DATA_TYPE_DOCUMENT: + return new DocumentPropertyConfig(propertyBundle); + default: + throw new IllegalArgumentException( + "Unsupported property bundle of type " + + propertyBundle.getInt(PropertyConfig.DATA_TYPE_FIELD) + + "; contents: " + + propertyBundle); + } + } + } + + /** Configuration for a property of type String in a Document. */ + public static final class StringPropertyConfig extends PropertyConfig { + private static final String INDEXING_TYPE_FIELD = "indexingType"; + private static final String TOKENIZER_TYPE_FIELD = "tokenizerType"; + /** * Encapsulates the configurations on how AppSearch should query/index these terms. * @@ -296,14 +397,7 @@ public final class AppSearchSchema { @Retention(RetentionPolicy.SOURCE) public @interface IndexingType {} - /** - * Content in this property will not be tokenized or indexed. - * - *

Useful if the data type is not made up of terms (e.g. {@link - * PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} type). None - * of the properties inside the nested property will be indexed regardless of the value of - * {@code indexingType} for the nested properties. - */ + /** Content in this property will not be tokenized or indexed. */ public static final int INDEXING_TYPE_NONE = 0; /** @@ -338,54 +432,16 @@ public final class AppSearchSchema { public @interface TokenizerType {} /** - * It is only valid for tokenizer_type to be 'NONE' if the data type is {@link - * PropertyConfig#DATA_TYPE_DOCUMENT}. + * It is only valid for tokenizer_type to be 'NONE' if {@link #getIndexingType} is {@link + * #INDEXING_TYPE_NONE}. */ public static final int TOKENIZER_TYPE_NONE = 0; /** Tokenization for plain text. */ public static final int TOKENIZER_TYPE_PLAIN = 1; - final Bundle mBundle; - - @Nullable private Integer mHashCode; - - PropertyConfig(@NonNull Bundle bundle) { - mBundle = Preconditions.checkNotNull(bundle); - } - - @Override - public String toString() { - return mBundle.toString(); - } - - /** Returns the name of this property. */ - @NonNull - public String getName() { - return mBundle.getString(NAME_FIELD, ""); - } - - /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */ - public @DataType int getDataType() { - return mBundle.getInt(DATA_TYPE_FIELD, -1); - } - - /** - * Returns the logical schema-type of the contents of this property. - * - *

Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. Otherwise, - * it is {@code null}. - */ - @Nullable - public String getSchemaType() { - return mBundle.getString(SCHEMA_TYPE_FIELD); - } - - /** - * Returns the cardinality of the property (whether it is optional, required or repeated). - */ - public @Cardinality int getCardinality() { - return mBundle.getInt(CARDINALITY_FIELD, -1); + StringPropertyConfig(@NonNull Bundle bundle) { + super(bundle); } /** Returns how the property is indexed. */ @@ -398,75 +454,19 @@ public final class AppSearchSchema { return mBundle.getInt(TOKENIZER_TYPE_FIELD); } - @Override - public boolean equals(@Nullable Object other) { - if (this == other) { - return true; - } - if (!(other instanceof PropertyConfig)) { - return false; - } - PropertyConfig otherProperty = (PropertyConfig) other; - return BundleUtil.deepEquals(this.mBundle, otherProperty.mBundle); - } - - @Override - public int hashCode() { - if (mHashCode == null) { - mHashCode = BundleUtil.deepHashCode(mBundle); - } - return mHashCode; - } - /** - * Builder for {@link PropertyConfig}. + * Builder for {@link StringPropertyConfig}. * - *

The following properties must be set, or {@link PropertyConfig} construction will - * fail: - * - *

    - *
  • dataType - *
  • cardinality - *
- * - *

In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType} - * is also required. + *

{@link #setCardinality} must be called or {@link #build} will fail. */ public static final class Builder { private final Bundle mBundle = new Bundle(); private boolean mBuilt = false; - /** Creates a new {@link PropertyConfig.Builder}. */ + /** Creates a new {@link StringPropertyConfig.Builder}. */ public Builder(@NonNull String propertyName) { mBundle.putString(NAME_FIELD, propertyName); - } - - /** - * Type of data the property contains (e.g. string, int, bytes, etc). - * - *

This property must be set. - */ - @NonNull - public PropertyConfig.Builder setDataType(@DataType int dataType) { - Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkArgumentInRange( - dataType, DATA_TYPE_STRING, DATA_TYPE_DOCUMENT, "dataType"); - mBundle.putInt(DATA_TYPE_FIELD, dataType); - return this; - } - - /** - * The logical schema-type of the contents of this property. - * - *

Only required when {@link #setDataType} is set to {@link #DATA_TYPE_DOCUMENT}. - * Otherwise, it is ignored. - */ - @NonNull - public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) { - Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkNotNull(schemaType); - mBundle.putString(SCHEMA_TYPE_FIELD, schemaType); - return this; + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_STRING); } /** @@ -474,8 +474,9 @@ public final class AppSearchSchema { * *

This property must be set. */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass @NonNull - public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + public StringPropertyConfig.Builder setCardinality(@Cardinality int cardinality) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkArgumentInRange( cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); @@ -487,7 +488,7 @@ public final class AppSearchSchema { * Configures how a property should be indexed so that it can be retrieved by queries. */ @NonNull - public PropertyConfig.Builder setIndexingType(@IndexingType int indexingType) { + public StringPropertyConfig.Builder setIndexingType(@IndexingType int indexingType) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkArgumentInRange( indexingType, INDEXING_TYPE_NONE, INDEXING_TYPE_PREFIXES, "indexingType"); @@ -497,7 +498,7 @@ public final class AppSearchSchema { /** Configures how this property should be tokenized (split into words). */ @NonNull - public PropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { + public StringPropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkArgumentInRange( tokenizerType, TOKENIZER_TYPE_NONE, TOKENIZER_TYPE_PLAIN, "tokenizerType"); @@ -505,6 +506,337 @@ public final class AppSearchSchema { return this; } + /** + * Constructs a new {@link StringPropertyConfig} from the contents of this builder. + * + *

After calling this method, the builder must no longer be used. + * + * @throws IllegalSchemaException if the property is not correctly populated + */ + @NonNull + public StringPropertyConfig build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead + // of partially reimplementing some of the validation Icing does here. + if (!mBundle.containsKey(CARDINALITY_FIELD)) { + throw new IllegalSchemaException("Missing field: cardinality"); + } + mBuilt = true; + return new StringPropertyConfig(mBundle); + } + } + } + + /** Configuration for a property containing a 64-bit integer. */ + public static final class Int64PropertyConfig extends PropertyConfig { + Int64PropertyConfig(@NonNull Bundle bundle) { + super(bundle); + } + + /** + * Builder for {@link Int64PropertyConfig}. + * + *

{@link #setCardinality} must be called or {@link #build} will fail. + */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** Creates a new {@link Int64PropertyConfig.Builder}. */ + public Builder(@NonNull String propertyName) { + mBundle.putString(NAME_FIELD, propertyName); + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_INT64); + } + + /** + * The cardinality of the property (whether it is optional, required or repeated). + * + *

This property must be set. + */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass + @NonNull + public Int64PropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkArgumentInRange( + cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); + mBundle.putInt(CARDINALITY_FIELD, cardinality); + return this; + } + + /** + * Constructs a new {@link Int64PropertyConfig} from the contents of this builder. + * + *

After calling this method, the builder must no longer be used. + * + * @throws IllegalSchemaException if the property is not correctly populated + */ + @NonNull + public Int64PropertyConfig build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + if (!mBundle.containsKey(CARDINALITY_FIELD)) { + throw new IllegalSchemaException("Missing field: cardinality"); + } + mBuilt = true; + return new Int64PropertyConfig(mBundle); + } + } + } + + /** Configuration for a property containing a double-precision decimal number. */ + public static final class DoublePropertyConfig extends PropertyConfig { + DoublePropertyConfig(@NonNull Bundle bundle) { + super(bundle); + } + + /** + * Builder for {@link DoublePropertyConfig}. + * + *

{@link #setCardinality} must be called or {@link #build} will fail. + */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** Creates a new {@link DoublePropertyConfig.Builder}. */ + public Builder(@NonNull String propertyName) { + mBundle.putString(NAME_FIELD, propertyName); + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOUBLE); + } + + /** + * The cardinality of the property (whether it is optional, required or repeated). + * + *

This property must be set. + */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass + @NonNull + public DoublePropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkArgumentInRange( + cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); + mBundle.putInt(CARDINALITY_FIELD, cardinality); + return this; + } + + /** + * Constructs a new {@link DoublePropertyConfig} from the contents of this builder. + * + *

After calling this method, the builder must no longer be used. + * + * @throws IllegalSchemaException if the property is not correctly populated + */ + @NonNull + public DoublePropertyConfig build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + if (!mBundle.containsKey(CARDINALITY_FIELD)) { + throw new IllegalSchemaException("Missing field: cardinality"); + } + mBuilt = true; + return new DoublePropertyConfig(mBundle); + } + } + } + + /** Configuration for a property containing a boolean. */ + public static final class BooleanPropertyConfig extends PropertyConfig { + BooleanPropertyConfig(@NonNull Bundle bundle) { + super(bundle); + } + + /** + * Builder for {@link BooleanPropertyConfig}. + * + *

{@link #setCardinality} must be called or {@link #build} will fail. + */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** Creates a new {@link BooleanPropertyConfig.Builder}. */ + public Builder(@NonNull String propertyName) { + mBundle.putString(NAME_FIELD, propertyName); + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_BOOLEAN); + } + + /** + * The cardinality of the property (whether it is optional, required or repeated). + * + *

This property must be set. + */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass + @NonNull + public BooleanPropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkArgumentInRange( + cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); + mBundle.putInt(CARDINALITY_FIELD, cardinality); + return this; + } + + /** + * Constructs a new {@link BooleanPropertyConfig} from the contents of this builder. + * + *

After calling this method, the builder must no longer be used. + * + * @throws IllegalSchemaException if the property is not correctly populated + */ + @NonNull + public BooleanPropertyConfig build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + if (!mBundle.containsKey(CARDINALITY_FIELD)) { + throw new IllegalSchemaException("Missing field: cardinality"); + } + mBuilt = true; + return new BooleanPropertyConfig(mBundle); + } + } + } + + /** Configuration for a property containing a byte array. */ + public static final class BytesPropertyConfig extends PropertyConfig { + BytesPropertyConfig(@NonNull Bundle bundle) { + super(bundle); + } + + /** + * Builder for {@link BytesPropertyConfig}. + * + *

{@link #setCardinality} must be called or {@link #build} will fail. + */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** Creates a new {@link BytesPropertyConfig.Builder}. */ + public Builder(@NonNull String propertyName) { + mBundle.putString(NAME_FIELD, propertyName); + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_BYTES); + } + + /** + * The cardinality of the property (whether it is optional, required or repeated). + * + *

This property must be set. + */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass + @NonNull + public BytesPropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkArgumentInRange( + cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); + mBundle.putInt(CARDINALITY_FIELD, cardinality); + return this; + } + + /** + * Constructs a new {@link BytesPropertyConfig} from the contents of this builder. + * + *

After calling this method, the builder must no longer be used. + * + * @throws IllegalSchemaException if the property is not correctly populated + */ + @NonNull + public BytesPropertyConfig build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + if (!mBundle.containsKey(CARDINALITY_FIELD)) { + throw new IllegalSchemaException("Missing field: cardinality"); + } + mBuilt = true; + return new BytesPropertyConfig(mBundle); + } + } + } + + /** Configuration for a property containing another Document. */ + public static final class DocumentPropertyConfig extends PropertyConfig { + private static final String SCHEMA_TYPE_FIELD = "schemaType"; + private static final String INDEX_NESTED_PROPERTIES_FIELD = "indexNestedProperties"; + + DocumentPropertyConfig(@NonNull Bundle bundle) { + super(bundle); + } + + /** Returns the logical schema-type of the contents of this document property. */ + @NonNull + public String getSchemaType() { + return Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD)); + } + + /** + * Returns whether fields in the nested document should be indexed according to that + * document's schema. + * + *

If false, the nested document's properties are not indexed regardless of its own + * schema. + */ + public boolean isIndexNestedProperties() { + return mBundle.getBoolean(INDEX_NESTED_PROPERTIES_FIELD); + } + + /** + * Builder for {@link DocumentPropertyConfig}. + * + *

The following properties must be set, or {@link DocumentPropertyConfig} construction + * will fail: + * + *

    + *
  • cardinality + *
  • schemaType + *
+ */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** Creates a new {@link DocumentPropertyConfig.Builder}. */ + public Builder(@NonNull String propertyName) { + mBundle.putString(NAME_FIELD, propertyName); + mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOCUMENT); + } + + /** + * The logical schema-type of the contents of this property. + * + *

This property must be set. + */ + @NonNull + public DocumentPropertyConfig.Builder setSchemaType(@NonNull String schemaType) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(schemaType); + mBundle.putString(SCHEMA_TYPE_FIELD, schemaType); + return this; + } + + /** + * The cardinality of the property (whether it is optional, required or repeated). + * + *

This property must be set. + */ + @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass + @NonNull + public DocumentPropertyConfig.Builder setCardinality(@Cardinality int cardinality) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkArgumentInRange( + cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality"); + mBundle.putInt(CARDINALITY_FIELD, cardinality); + return this; + } + + /** + * Configures whether fields in the nested document should be indexed according to that + * document's schema. + * + *

If false, the nested document's properties are not indexed regardless of its own + * schema. + */ + @NonNull + public DocumentPropertyConfig.Builder setIndexNestedProperties( + boolean indexNestedProperties) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBundle.putBoolean(INDEX_NESTED_PROPERTIES_FIELD, indexNestedProperties); + return this; + } + /** * Constructs a new {@link PropertyConfig} from the contents of this builder. * @@ -514,24 +846,16 @@ public final class AppSearchSchema { * missing {@code dataType}). */ @NonNull - public PropertyConfig build() { + public DocumentPropertyConfig build() { Preconditions.checkState(!mBuilt, "Builder has already been used"); - // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead - // of partially reimplementing some of the validation Icing does here. - if (!mBundle.containsKey(DATA_TYPE_FIELD)) { - throw new IllegalSchemaException("Missing field: dataType"); - } - if (mBundle.getString(SCHEMA_TYPE_FIELD, "").isEmpty() - && mBundle.getInt(DATA_TYPE_FIELD) == DATA_TYPE_DOCUMENT) { - throw new IllegalSchemaException( - "Missing field: schemaType (required for configs with " - + "dataType = DOCUMENT)"); + if (mBundle.getString(SCHEMA_TYPE_FIELD, "").isEmpty()) { + throw new IllegalSchemaException("Missing field: schemaType"); } if (!mBundle.containsKey(CARDINALITY_FIELD)) { throw new IllegalSchemaException("Missing field: cardinality"); } mBuilt = true; - return new PropertyConfig(mBundle); + return new DocumentPropertyConfig(mBundle); } } } diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java index 11e7fab2b7d9e..2f02808bfb621 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java @@ -80,9 +80,9 @@ public class GenericDocument { /** * The maximum number of indexed properties a document can have. * - *

Indexed properties are properties where the {@link - * AppSearchSchema.PropertyConfig#getIndexingType()} constant is anything other than {@link - * AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}. + *

Indexed properties are properties which are strings where the {@link + * AppSearchSchema.StringPropertyConfig#getIndexingType} value is anything other than {@link + * AppSearchSchema.StringPropertyConfig.IndexingType#INDEXING_TYPE_NONE}. */ public static int getMaxIndexedProperties() { return MAX_INDEXED_PROPERTIES; diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java index 74afdd2c7a80b..38e0046f6791f 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java @@ -17,13 +17,17 @@ package android.app.appsearch; import android.annotation.NonNull; +import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.util.Preconditions; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -32,12 +36,24 @@ import java.util.Set; * @see AppSearchSession#getByUri */ public final class GetByUriRequest { + /** + * Schema type to be used in {@link android.app.appsearch.GetByUriRequest.Builder#addProjection} + * to apply property paths to all results, excepting any types that have had their own, specific + * property paths set. + */ + public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*"; + private final String mNamespace; private final Set mUris; + private final Map> mTypePropertyPathsMap; - GetByUriRequest(@NonNull String namespace, @NonNull Set uris) { - mNamespace = namespace; - mUris = uris; + GetByUriRequest( + @NonNull String namespace, + @NonNull Set uris, + @NonNull Map> typePropertyPathsMap) { + mNamespace = Preconditions.checkNotNull(namespace); + mUris = Preconditions.checkNotNull(uris); + mTypePropertyPathsMap = Preconditions.checkNotNull(typePropertyPathsMap); } /** Returns the namespace to get documents from. */ @@ -52,10 +68,43 @@ public final class GetByUriRequest { return Collections.unmodifiableSet(mUris); } + /** + * Returns a map from schema type to property paths to be used for projection. + * + *

If the map is empty, then all properties will be retrieved for all results. + * + *

Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this + * function, rather than calling it multiple times. + */ + @NonNull + public Map> getProjections() { + Map> copy = new ArrayMap<>(); + for (String key : mTypePropertyPathsMap.keySet()) { + copy.put(key, new ArrayList<>(mTypePropertyPathsMap.get(key))); + } + return copy; + } + + /** + * Returns a map from schema type to property paths to be used for projection. + * + *

If the map is empty, then all properties will be retrieved for all results. + * + *

A more efficient version of {@link #getProjections}, but it returns a modifiable map. This + * is not meant to be unhidden and should only be used by internal classes. + * + * @hide + */ + @NonNull + public Map> getProjectionsVisibleToPackagesInternal() { + return mTypePropertyPathsMap; + } + /** Builder for {@link GetByUriRequest} objects. */ public static final class Builder { private String mNamespace = GenericDocument.DEFAULT_NAMESPACE; private final Set mUris = new ArraySet<>(); + private final Map> mProjectionTypePropertyPaths = new ArrayMap<>(); private boolean mBuilt = false; /** @@ -87,12 +136,63 @@ public final class GetByUriRequest { return this; } + /** + * Adds property paths for the specified type to be used for projection. If property paths + * are added for a type, then only the properties referred to will be retrieved for results + * of that type. If a property path that is specified isn't present in a result, it will be + * ignored for that result. Property paths cannot be null. + * + *

If no property paths are added for a particular type, then all properties of results + * of that type will be retrieved. + * + *

If property path is added for the {@link + * GetByUriRequest#PROJECTION_SCHEMA_TYPE_WILDCARD}, then those property paths will apply to + * all results, excepting any types that have their own, specific property paths set. + * + *

{@see SearchSpec.Builder#addProjection(String, String...)} + */ + @NonNull + public Builder addProjection(@NonNull String schemaType, @NonNull String... propertyPaths) { + Preconditions.checkNotNull(propertyPaths); + return addProjection(schemaType, Arrays.asList(propertyPaths)); + } + + /** + * Adds property paths for the specified type to be used for projection. If property paths + * are added for a type, then only the properties referred to will be retrieved for results + * of that type. If a property path that is specified isn't present in a result, it will be + * ignored for that result. Property paths cannot be null. + * + *

If no property paths are added for a particular type, then all properties of results + * of that type will be retrieved. + * + *

If property path is added for the {@link + * GetByUriRequest#PROJECTION_SCHEMA_TYPE_WILDCARD}, then those property paths will apply to + * all results, excepting any types that have their own, specific property paths set. + * + *

{@see SearchSpec.Builder#addProjection(String, String...)} + */ + @NonNull + public Builder addProjection( + @NonNull String schemaType, @NonNull Collection propertyPaths) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(schemaType); + Preconditions.checkNotNull(propertyPaths); + List propertyPathsList = new ArrayList<>(propertyPaths.size()); + for (String propertyPath : propertyPaths) { + Preconditions.checkNotNull(propertyPath); + propertyPathsList.add(propertyPath); + } + mProjectionTypePropertyPaths.put(schemaType, propertyPathsList); + return this; + } + /** Builds a new {@link GetByUriRequest}. */ @NonNull public GetByUriRequest build() { Preconditions.checkState(!mBuilt, "Builder has already been used"); mBuilt = true; - return new GetByUriRequest(mNamespace, mUris); + return new GetByUriRequest(mNamespace, mUris, mProjectionTypePropertyPaths); } } } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index cfee7a4642b73..ec41353e76bbd 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -190,6 +190,7 @@ public class AppSearchManagerService extends SystemService { @NonNull String databaseName, @NonNull String namespace, @NonNull List uris, + @NonNull Map> typePropertyPaths, @UserIdInt int userId, @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(packageName); @@ -208,8 +209,8 @@ public class AppSearchManagerService extends SystemService { for (int i = 0; i < uris.size(); i++) { String uri = uris.get(i); try { - GenericDocument document = - impl.getDocument(packageName, databaseName, namespace, uri); + GenericDocument document = impl.getDocument(packageName, databaseName, + namespace, uri, typePropertyPaths); resultBuilder.setSuccess(uri, document.getBundle()); } catch (Throwable t) { resultBuilder.setResult(uri, throwableToFailedResult(t)); 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 15818476d1296..1665b1cf6d631 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 @@ -21,6 +21,7 @@ import android.annotation.WorkerThread; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.GenericDocument; +import android.app.appsearch.GetByUriRequest; import android.app.appsearch.PackageIdentifier; import android.app.appsearch.SearchResultPage; import android.app.appsearch.SearchSpec; @@ -38,6 +39,7 @@ import com.android.server.appsearch.external.localstorage.converter.GenericDocum import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter; import com.android.server.appsearch.external.localstorage.converter.SearchResultToProtoConverter; import com.android.server.appsearch.external.localstorage.converter.SearchSpecToProtoConverter; +import com.android.server.appsearch.external.localstorage.converter.TypePropertyPathToProtoConverter; import com.google.android.icing.IcingSearchEngine; import com.google.android.icing.proto.DeleteByQueryResultProto; @@ -428,6 +430,8 @@ public final class AppSearchImpl { * @param databaseName The databaseName this document resides in. * @param namespace The namespace this document resides in. * @param uri The URI of the document to get. + * @param typePropertyPaths A map of schema type to a list of property paths to return in the + * result. * @return The Document contents * @throws AppSearchException on IcingSearchEngine error. */ @@ -436,16 +440,35 @@ public final class AppSearchImpl { @NonNull String packageName, @NonNull String databaseName, @NonNull String namespace, - @NonNull String uri) + @NonNull String uri, + @NonNull Map> typePropertyPaths) throws AppSearchException { GetResultProto getResultProto; + List nonPrefixedPropertyMasks = + TypePropertyPathToProtoConverter.toTypePropertyMaskList(typePropertyPaths); + List prefixedPropertyMasks = + new ArrayList<>(nonPrefixedPropertyMasks.size()); + for (int i = 0; i < nonPrefixedPropertyMasks.size(); ++i) { + TypePropertyMask typePropertyMask = nonPrefixedPropertyMasks.get(i); + String nonPrefixedType = typePropertyMask.getSchemaType(); + String prefixedType = + nonPrefixedType.equals(GetByUriRequest.PROJECTION_SCHEMA_TYPE_WILDCARD) + ? nonPrefixedType + : createPrefix(packageName, databaseName) + nonPrefixedType; + prefixedPropertyMasks.add( + typePropertyMask.toBuilder().setSchemaType(prefixedType).build()); + } + GetResultSpecProto getResultSpec = + GetResultSpecProto.newBuilder() + .addAllTypePropertyMasks(prefixedPropertyMasks) + .build(); mReadWriteLock.readLock().lock(); try { getResultProto = mIcingSearchEngineLocked.get( createPrefix(packageName, databaseName) + namespace, uri, - GetResultSpecProto.getDefaultInstance()); + getResultSpec); } finally { mReadWriteLock.readLock().unlock(); } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java index 1c86cd6d6e783..24d64a04affda 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java @@ -85,15 +85,14 @@ class VisibilityStore { private static final AppSearchSchema VISIBILITY_SCHEMA = new AppSearchSchema.Builder(VISIBILITY_TYPE) .addProperty( - new AppSearchSchema.PropertyConfig.Builder( + new AppSearchSchema.StringPropertyConfig.Builder( NOT_PLATFORM_SURFACEABLE_PROPERTY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) .build()) .addProperty( - new AppSearchSchema.PropertyConfig.Builder(PACKAGE_ACCESSIBLE_PROPERTY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_DOCUMENT) + new AppSearchSchema.DocumentPropertyConfig.Builder( + PACKAGE_ACCESSIBLE_PROPERTY) .setSchemaType(PACKAGE_ACCESSIBLE_TYPE) .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) @@ -107,22 +106,20 @@ class VisibilityStore { private static final AppSearchSchema PACKAGE_ACCESSIBLE_SCHEMA = new AppSearchSchema.Builder(PACKAGE_ACCESSIBLE_TYPE) .addProperty( - new AppSearchSchema.PropertyConfig.Builder(PACKAGE_NAME_PROPERTY) + new AppSearchSchema.StringPropertyConfig.Builder(PACKAGE_NAME_PROPERTY) .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) .build()) .addProperty( - new AppSearchSchema.PropertyConfig.Builder(SHA_256_CERT_PROPERTY) + new AppSearchSchema.BytesPropertyConfig.Builder(SHA_256_CERT_PROPERTY) .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES) .build()) .addProperty( - new AppSearchSchema.PropertyConfig.Builder(ACCESSIBLE_SCHEMA_PROPERTY) + new AppSearchSchema.StringPropertyConfig.Builder( + ACCESSIBLE_SCHEMA_PROPERTY) .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) .build()) .build(); @@ -238,7 +235,8 @@ class VisibilityStore { PACKAGE_NAME, DATABASE_NAME, NAMESPACE, - /*uri=*/ addUriPrefix(prefix)); + /*uri=*/ addUriPrefix(prefix), + /*typePropertyPaths=*/ Collections.emptyMap()); // Update platform visibility settings String[] schemas = diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java index 69bf3d7b9f119..ce1c9f4d4744e 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java @@ -22,6 +22,7 @@ import android.util.Log; import com.android.internal.util.Preconditions; +import com.google.android.icing.proto.DocumentIndexingConfig; import com.google.android.icing.proto.PropertyConfigProto; import com.google.android.icing.proto.SchemaTypeConfigProto; import com.google.android.icing.proto.SchemaTypeConfigProtoOrBuilder; @@ -65,7 +66,6 @@ public final class SchemaToProtoConverter { Preconditions.checkNotNull(property); PropertyConfigProto.Builder builder = PropertyConfigProto.newBuilder().setPropertyName(property.getName()); - StringIndexingConfig.Builder indexingConfig = StringIndexingConfig.newBuilder(); // Set dataType @AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType(); @@ -76,12 +76,6 @@ public final class SchemaToProtoConverter { } builder.setDataType(dataTypeProto); - // Set schemaType - String schemaType = property.getSchemaType(); - if (schemaType != null) { - builder.setSchemaType(schemaType); - } - // Set cardinality @AppSearchSchema.PropertyConfig.Cardinality int cardinality = property.getCardinality(); PropertyConfigProto.Cardinality.Code cardinalityProto = @@ -91,36 +85,27 @@ public final class SchemaToProtoConverter { } builder.setCardinality(cardinalityProto); - // Set indexingType - @AppSearchSchema.PropertyConfig.IndexingType int indexingType = property.getIndexingType(); - TermMatchType.Code termMatchTypeProto; - switch (indexingType) { - case AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE: - termMatchTypeProto = TermMatchType.Code.UNKNOWN; - break; - case AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS: - termMatchTypeProto = TermMatchType.Code.EXACT_ONLY; - break; - case AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES: - termMatchTypeProto = TermMatchType.Code.PREFIX; - break; - default: - throw new IllegalArgumentException("Invalid indexingType: " + indexingType); - } - indexingConfig.setTermMatchType(termMatchTypeProto); + if (property instanceof AppSearchSchema.StringPropertyConfig) { + AppSearchSchema.StringPropertyConfig stringProperty = + (AppSearchSchema.StringPropertyConfig) property; + StringIndexingConfig stringIndexingConfig = + StringIndexingConfig.newBuilder() + .setTermMatchType( + convertTermMatchTypeToProto(stringProperty.getIndexingType())) + .setTokenizerType( + convertTokenizerTypeToProto(stringProperty.getTokenizerType())) + .build(); + builder.setStringIndexingConfig(stringIndexingConfig); - // Set tokenizerType - @AppSearchSchema.PropertyConfig.TokenizerType - int tokenizerType = property.getTokenizerType(); - StringIndexingConfig.TokenizerType.Code tokenizerTypeProto = - StringIndexingConfig.TokenizerType.Code.forNumber(tokenizerType); - if (tokenizerTypeProto == null) { - throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); + } else if (property instanceof AppSearchSchema.DocumentPropertyConfig) { + AppSearchSchema.DocumentPropertyConfig documentProperty = + (AppSearchSchema.DocumentPropertyConfig) property; + builder.setSchemaType(documentProperty.getSchemaType()) + .setDocumentIndexingConfig( + DocumentIndexingConfig.newBuilder() + .setIndexNestedProperties( + documentProperty.isIndexNestedProperties())); } - indexingConfig.setTokenizerType(tokenizerTypeProto); - - // Build! - builder.setStringIndexingConfig(indexingConfig); return builder.build(); } @@ -145,39 +130,99 @@ public final class SchemaToProtoConverter { private static AppSearchSchema.PropertyConfig toPropertyConfig( @NonNull PropertyConfigProto proto) { Preconditions.checkNotNull(proto); - AppSearchSchema.PropertyConfig.Builder builder = - new AppSearchSchema.PropertyConfig.Builder(proto.getPropertyName()) - .setDataType(proto.getDataType().getNumber()) + switch (proto.getDataType()) { + case STRING: + return toStringPropertyConfig(proto); + case INT64: + return new AppSearchSchema.Int64PropertyConfig.Builder(proto.getPropertyName()) + .setCardinality(proto.getCardinality().getNumber()) + .build(); + case DOUBLE: + return new AppSearchSchema.DoublePropertyConfig.Builder(proto.getPropertyName()) + .setCardinality(proto.getCardinality().getNumber()) + .build(); + case BOOLEAN: + return new AppSearchSchema.BooleanPropertyConfig.Builder(proto.getPropertyName()) + .setCardinality(proto.getCardinality().getNumber()) + .build(); + case BYTES: + return new AppSearchSchema.BytesPropertyConfig.Builder(proto.getPropertyName()) + .setCardinality(proto.getCardinality().getNumber()) + .build(); + case DOCUMENT: + return toDocumentPropertyConfig(proto); + default: + throw new IllegalArgumentException("Invalid dataType: " + proto.getDataType()); + } + } + + @NonNull + private static AppSearchSchema.StringPropertyConfig toStringPropertyConfig( + @NonNull PropertyConfigProto proto) { + AppSearchSchema.StringPropertyConfig.Builder builder = + new AppSearchSchema.StringPropertyConfig.Builder(proto.getPropertyName()) .setCardinality(proto.getCardinality().getNumber()) .setTokenizerType( proto.getStringIndexingConfig().getTokenizerType().getNumber()); - // Set schema - if (!proto.getSchemaType().isEmpty()) { - builder.setSchemaType(proto.getSchemaType()); - } - // Set indexingType - @AppSearchSchema.PropertyConfig.IndexingType int indexingType; TermMatchType.Code termMatchTypeProto = proto.getStringIndexingConfig().getTermMatchType(); - switch (termMatchTypeProto) { - case UNKNOWN: - indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE; - break; - case EXACT_ONLY: - indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS; - break; - case PREFIX: - indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES; - break; - default: - // Avoid crashing in the 'read' path; we should try to interpret the document to the - // extent possible. - Log.w(TAG, "Invalid indexingType: " + termMatchTypeProto.getNumber()); - indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE; - } - builder.setIndexingType(indexingType); + builder.setIndexingType(convertTermMatchTypeFromProto(termMatchTypeProto)); return builder.build(); } + + @NonNull + private static AppSearchSchema.DocumentPropertyConfig toDocumentPropertyConfig( + @NonNull PropertyConfigProto proto) { + return new AppSearchSchema.DocumentPropertyConfig.Builder(proto.getPropertyName()) + .setCardinality(proto.getCardinality().getNumber()) + .setSchemaType(proto.getSchemaType()) + .setIndexNestedProperties( + proto.getDocumentIndexingConfig().getIndexNestedProperties()) + .build(); + } + + @NonNull + private static TermMatchType.Code convertTermMatchTypeToProto( + @AppSearchSchema.StringPropertyConfig.IndexingType int indexingType) { + switch (indexingType) { + case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE: + return TermMatchType.Code.UNKNOWN; + case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS: + return TermMatchType.Code.EXACT_ONLY; + case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES: + return TermMatchType.Code.PREFIX; + default: + throw new IllegalArgumentException("Invalid indexingType: " + indexingType); + } + } + + @AppSearchSchema.StringPropertyConfig.IndexingType + private static int convertTermMatchTypeFromProto(@NonNull TermMatchType.Code termMatchType) { + switch (termMatchType) { + case UNKNOWN: + return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE; + case EXACT_ONLY: + return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS; + case PREFIX: + return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES; + default: + // Avoid crashing in the 'read' path; we should try to interpret the document to the + // extent possible. + Log.w(TAG, "Invalid indexingType: " + termMatchType.getNumber()); + return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE; + } + } + + @NonNull + private static StringIndexingConfig.TokenizerType.Code convertTokenizerTypeToProto( + @AppSearchSchema.StringPropertyConfig.TokenizerType int tokenizerType) { + StringIndexingConfig.TokenizerType.Code tokenizerTypeProto = + StringIndexingConfig.TokenizerType.Code.forNumber(tokenizerType); + if (tokenizerTypeProto == null) { + throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); + } + return tokenizerTypeProto; + } } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java index 417ea24e13b6d..07d50ae1a7054 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java @@ -25,10 +25,6 @@ import com.google.android.icing.proto.ResultSpecProto; import com.google.android.icing.proto.ScoringSpecProto; import com.google.android.icing.proto.SearchSpecProto; import com.google.android.icing.proto.TermMatchType; -import com.google.android.icing.proto.TypePropertyMask; - -import java.util.List; -import java.util.Map; /** * Translates a {@link SearchSpec} into icing search protos. @@ -61,22 +57,17 @@ public final class SearchSpecToProtoConverter { @NonNull public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) { Preconditions.checkNotNull(spec); - ResultSpecProto.Builder builder = - ResultSpecProto.newBuilder() - .setNumPerPage(spec.getResultCountPerPage()) - .setSnippetSpec( - ResultSpecProto.SnippetSpecProto.newBuilder() - .setNumToSnippet(spec.getSnippetCount()) - .setNumMatchesPerProperty(spec.getSnippetCountPerProperty()) - .setMaxWindowBytes(spec.getMaxSnippetSize())); - Map> projectionTypePropertyPaths = spec.getProjections(); - for (Map.Entry> e : projectionTypePropertyPaths.entrySet()) { - builder.addTypePropertyMasks( - TypePropertyMask.newBuilder() - .setSchemaType(e.getKey()) - .addAllPaths(e.getValue())); - } - return builder.build(); + return ResultSpecProto.newBuilder() + .setNumPerPage(spec.getResultCountPerPage()) + .setSnippetSpec( + ResultSpecProto.SnippetSpecProto.newBuilder() + .setNumToSnippet(spec.getSnippetCount()) + .setNumMatchesPerProperty(spec.getSnippetCountPerProperty()) + .setMaxWindowBytes(spec.getMaxSnippetSize())) + .addAllTypePropertyMasks( + TypePropertyPathToProtoConverter.toTypePropertyMaskList( + spec.getProjections())) + .build(); } /** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */ diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/TypePropertyPathToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/TypePropertyPathToProtoConverter.java new file mode 100644 index 0000000000000..6f6dad2077138 --- /dev/null +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/TypePropertyPathToProtoConverter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appsearch.external.localstorage.converter; + +import android.annotation.NonNull; + +import com.android.internal.util.Preconditions; + +import com.google.android.icing.proto.TypePropertyMask; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Translates a Map> into List. + * + * @hide + */ +public final class TypePropertyPathToProtoConverter { + private TypePropertyPathToProtoConverter() {} + + /** Extracts {@link TypePropertyMask} information from a {@link Map}. */ + @NonNull + public static List toTypePropertyMaskList( + @NonNull Map> typePropertyPaths) { + Preconditions.checkNotNull(typePropertyPaths); + List typePropertyMasks = new ArrayList<>(typePropertyPaths.size()); + for (Map.Entry> e : typePropertyPaths.entrySet()) { + typePropertyMasks.add( + TypePropertyMask.newBuilder() + .setSchemaType(e.getKey()) + .addAllPaths(e.getValue()) + .build()); + } + return typePropertyMasks; + } +} diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt index bca9424473e51..5ab34509c7026 100644 --- a/apex/appsearch/synced_jetpack_changeid.txt +++ b/apex/appsearch/synced_jetpack_changeid.txt @@ -1 +1 @@ -I87d10a6c5f7b8e22a633fa910385061fbca0db24 +Iff96eae150c7cdd281c9ecb5d93f4ef697e89f1a diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java index 459fd151ede40..13858a3252d29 100644 --- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java @@ -28,6 +28,7 @@ import android.app.appsearch.SearchResultsShim; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.Future; public class AppSearchTestUtils { @@ -59,6 +60,20 @@ public class AppSearchTestUtils { return list; } + public static List doGet(AppSearchSessionShim session, GetByUriRequest request) + throws Exception { + AppSearchBatchResult result = + checkIsBatchResultSuccess(session.getByUri(request)); + Set uris = request.getUris(); + assertThat(result.getSuccesses()).hasSize(uris.size()); + assertThat(result.getFailures()).isEmpty(); + List list = new ArrayList<>(uris.size()); + for (String uri : uris) { + list.add(result.getSuccesses().get(uri)); + } + return list; + } + public static List convertSearchResultsToDocuments( SearchResultsShim searchResults) throws Exception { List results = searchResults.getNextPage().get(); diff --git a/core/java/android/content/pm/AppSearchPerson.java b/core/java/android/content/pm/AppSearchPerson.java index 045c55f28bf17..d70ac918e2086 100644 --- a/core/java/android/content/pm/AppSearchPerson.java +++ b/core/java/android/content/pm/AppSearchPerson.java @@ -47,32 +47,24 @@ public class AppSearchPerson extends GenericDocument { } public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE) - .addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_NAME) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_NAME) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_KEY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_KEY) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_IS_BOT) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BOOLEAN) + ).addProperty(new AppSearchSchema.BooleanPropertyConfig.Builder(KEY_IS_BOT) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_IS_IMPORTANT) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BOOLEAN) + ).addProperty(new AppSearchSchema.BooleanPropertyConfig.Builder(KEY_IS_IMPORTANT) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() ).build(); diff --git a/core/java/android/content/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java index 14b8df86025c5..85549d854c6d6 100644 --- a/core/java/android/content/pm/AppSearchShortcutInfo.java +++ b/core/java/android/content/pm/AppSearchShortcutInfo.java @@ -73,131 +73,100 @@ public class AppSearchShortcutInfo extends GenericDocument { public static final String KEY_DISABLED_REASON = "disabledReason"; public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE) - .addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_PACKAGE_NAME) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_PACKAGE_NAME) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_ACTIVITY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ACTIVITY) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_TITLE) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_TITLE) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_TEXT) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_TEXT) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_DISABLED_MESSAGE) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_DISABLED_MESSAGE) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_CATEGORIES) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_CATEGORIES) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_INTENTS) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_INTENTS) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_INTENT_PERSISTABLE_EXTRAS) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES) + ).addProperty(new AppSearchSchema.BytesPropertyConfig.Builder( + KEY_INTENT_PERSISTABLE_EXTRAS) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_PERSON) + ).addProperty(new AppSearchSchema.DocumentPropertyConfig.Builder(KEY_PERSON) .setSchemaType(AppSearchPerson.SCHEMA_TYPE) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_DOCUMENT) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_LOCUS_ID) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_LOCUS_ID) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_RANK) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_RANK) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_EXTRAS) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES) + ).addProperty(new AppSearchSchema.BytesPropertyConfig.Builder(KEY_EXTRAS) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_FLAGS) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_FLAGS) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_ICON_RES_ID) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_ICON_RES_ID) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_ICON_RES_NAME) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ICON_RES_NAME) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_ICON_URI) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ICON_URI) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_BITMAP_PATH) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_BITMAP_PATH) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE) + .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE) .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder(KEY_DISABLED_REASON) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_DISABLED_REASON) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS) .build() ).build(); diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java index 7fcf877240147..dc225f11ae803 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java @@ -34,28 +34,26 @@ public class SchemaToProtoConverterTest { new AppSearchSchema.Builder("Email") .setVersion(12345) .addProperty( - new AppSearchSchema.PropertyConfig.Builder("subject") - .setDataType( - AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + new AppSearchSchema.StringPropertyConfig.Builder("subject") .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) .setIndexingType( - AppSearchSchema.PropertyConfig + AppSearchSchema.StringPropertyConfig .INDEXING_TYPE_PREFIXES) .setTokenizerType( - AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + AppSearchSchema.StringPropertyConfig + .TOKENIZER_TYPE_PLAIN) .build()) .addProperty( - new AppSearchSchema.PropertyConfig.Builder("body") - .setDataType( - AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + new AppSearchSchema.StringPropertyConfig.Builder("body") .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) .setIndexingType( - AppSearchSchema.PropertyConfig + AppSearchSchema.StringPropertyConfig .INDEXING_TYPE_PREFIXES) .setTokenizerType( - AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + AppSearchSchema.StringPropertyConfig + .TOKENIZER_TYPE_PLAIN) .build()) .build(); @@ -102,26 +100,20 @@ public class SchemaToProtoConverterTest { AppSearchSchema musicRecordingSchema = new AppSearchSchema.Builder("MusicRecording") .addProperty( - new AppSearchSchema.PropertyConfig.Builder("artist") - .setDataType( - AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + new AppSearchSchema.StringPropertyConfig.Builder("artist") .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) .setIndexingType( - AppSearchSchema.PropertyConfig + AppSearchSchema.StringPropertyConfig .INDEXING_TYPE_PREFIXES) .setTokenizerType( - AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + AppSearchSchema.StringPropertyConfig + .TOKENIZER_TYPE_PLAIN) .build()) .addProperty( - new AppSearchSchema.PropertyConfig.Builder("pubDate") - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + new AppSearchSchema.Int64PropertyConfig.Builder("pubDate") .setCardinality( AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType( - AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) - .setTokenizerType( - AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) .build()) .build(); @@ -147,14 +139,7 @@ public class SchemaToProtoConverterTest { .setPropertyName("pubDate") .setDataType(PropertyConfigProto.DataType.Code.INT64) .setCardinality( - PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig( - StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType - .Code.NONE) - .setTermMatchType( - TermMatchType.Code.UNKNOWN))) + PropertyConfigProto.Cardinality.Code.OPTIONAL)) .build(); assertThat(SchemaToProtoConverter.toSchemaTypeConfigProto(musicRecordingSchema))