Loading Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -510,6 +510,7 @@ java_library { "exoplayer2-core", "android.hardware.wifi-V1.0-java-constants", ], libs: ["icing-java-proto-lite"], apex_available: ["//apex_available:platform"], } Loading apex/appsearch/framework/Android.bp +23 −20 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ java_library { libs: [ "framework-minus-apex", // TODO(b/146218515) should be framework-system-stubs ], static_libs: [ "icing-java-proto-lite", ], visibility: [ "//frameworks/base/apex/appsearch:__subpackages__", // TODO(b/146218515) remove this when framework is built with the stub of appsearch Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +67 −4 Original line number Diff line number Diff line Loading @@ -15,21 +15,84 @@ */ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import com.android.internal.infra.AndroidFuture; import com.google.android.icing.proto.SchemaProto; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * TODO(b/142567528): add comments when implement this class * This class provides access to the centralized AppSearch index maintained by the system. * * <p>Apps can index structured text documents with AppSearch, which can then be retrieved through * the query API. * * @hide */ @SystemService(Context.APP_SEARCH_SERVICE) public class AppSearchManager { private final IAppSearchManager mService; /** @hide */ public AppSearchManager(@NonNull IAppSearchManager service) { mService = service; } /** * TODO(b/142567528): add comments when implement this class * Sets the schema being used by documents provided to the #put method. * * <p>This operation is performed asynchronously. On success, the provided callback will be * called with {@code null}. On failure, the provided callback will be called with a * {@link Throwable} describing the failure. * * <p>It is a no-op to set the same schema as has been previously set; this is handled * efficiently. * * <p>AppSearch automatically handles the following types of schema changes: * <ul> * <li>Addition of new types (No changes to storage or index) * <li>Removal of an existing type (All documents of the removed type are deleted) * <li>Addition of new 'optional' property to a type (No changes to storage or index) * <li>Removal of existing property of any cardinality (All documents reindexed) * </ul> * * <p>This method will return an error when attempting to make the following types of changes: * <ul> * <li>Changing the type of an existing property * <li>Adding a 'required' property * </ul> * * @param schema The schema config for this app. * @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}. * * @hide */ public AppSearchManager(IAppSearchManager service) { mService = service; // TODO(b/143789408): linkify #put after that API is created // TODO(b/145635424): add a 'force' param to setSchema after the corresponding API is finalized // in Icing Library // TODO(b/145635424): Update the documentation above once the Schema mutation APIs of Icing // Library are finalized public void setSchema( @NonNull AppSearchSchema schema, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<? super Throwable> callback) { SchemaProto schemaProto = schema.getProto(); byte[] schemaBytes = schemaProto.toByteArray(); AndroidFuture<Void> future = new AndroidFuture<>(); try { mService.setSchema(schemaBytes, future); } catch (RemoteException e) { future.completeExceptionally(e); } future.whenCompleteAsync((noop, err) -> callback.accept(err), executor); } } apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java 0 → 100644 +423 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; import com.google.android.icing.proto.PropertyConfigProto; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SchemaTypeConfigProto; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Representation of the AppSearch Schema. * * <p>The schema is the set of document types, properties, and config (like tokenization type) * understood by AppSearch for this app. * * @hide */ public final class AppSearchSchema { private final SchemaProto mProto; private AppSearchSchema(SchemaProto proto) { mProto = proto; } /** Creates a new {@link AppSearchSchema.Builder}. */ @NonNull public static AppSearchSchema.Builder newBuilder() { return new AppSearchSchema.Builder(); } /** Creates a new {@link SchemaType.Builder}. */ @NonNull public static SchemaType.Builder newSchemaTypeBuilder(@NonNull String typeName) { return new SchemaType.Builder(typeName); } /** Creates a new {@link PropertyConfig.Builder}. */ @NonNull public static PropertyConfig.Builder newPropertyBuilder(@NonNull String propertyName) { return new PropertyConfig.Builder(propertyName); } /** Creates a new {@link IndexingConfig.Builder}. */ @NonNull public static IndexingConfig.Builder newIndexingConfigBuilder() { return new IndexingConfig.Builder(); } /** * Returns the schema proto populated by the {@link AppSearchSchema} builders. * @hide */ @NonNull SchemaProto getProto() { return mProto; } /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { private final SchemaProto.Builder mProtoBuilder = SchemaProto.newBuilder(); private Builder() {} /** Adds a supported type to this app's AppSearch schema. */ @NonNull public AppSearchSchema.Builder addType(@NonNull SchemaType schemaType) { mProtoBuilder.addTypes(schemaType.mProto); return this; } /** * Constructs a new {@link AppSearchSchema} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public AppSearchSchema build() { return new AppSearchSchema(mProtoBuilder.build()); } } /** * Represents a type of a document. * * <p>For example, an e-mail message or a music recording could be a schema type. */ public static final class SchemaType { private final SchemaTypeConfigProto mProto; private SchemaType(SchemaTypeConfigProto proto) { mProto = proto; } /** Builder for {@link SchemaType} objects. */ public static final class Builder { private final SchemaTypeConfigProto.Builder mProtoBuilder = SchemaTypeConfigProto.newBuilder(); private Builder(@NonNull String typeName) { mProtoBuilder.setSchemaType(typeName); } /** Adds a property to the given type. */ @NonNull public SchemaType.Builder addProperty(@NonNull PropertyConfig propertyConfig) { mProtoBuilder.addProperties(propertyConfig.mProto); return this; } /** * Constructs a new {@link SchemaType} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public SchemaType build() { return new SchemaType(mProtoBuilder.build()); } } } /** * Configuration for a single property (field) of a document type. * * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be * a property. */ public static final class PropertyConfig { /** Physical data-types of the contents of the property. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.DataType.Code. @IntDef(prefix = {"DATA_TYPE_"}, value = { DATA_TYPE_STRING, DATA_TYPE_INT64, DATA_TYPE_DOUBLE, DATA_TYPE_BOOLEAN, DATA_TYPE_BYTES, DATA_TYPE_DOCUMENT, }) @Retention(RetentionPolicy.SOURCE) public @interface DataType {} public static final int DATA_TYPE_STRING = 1; public static final int DATA_TYPE_INT64 = 2; public static final int DATA_TYPE_DOUBLE = 3; public static final int DATA_TYPE_BOOLEAN = 4; /** Unstructured BLOB. */ public static final int DATA_TYPE_BYTES = 5; /** * Indicates that the property itself is an Document, making it part a hierarchical * Document schema. Any property using this DataType MUST have a valid * {@code schemaType}. */ public static final int DATA_TYPE_DOCUMENT = 6; /** The cardinality of the property (whether it is required, optional or repeated). */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code. @IntDef(prefix = {"CARDINALITY_"}, value = { CARDINALITY_REPEATED, CARDINALITY_OPTIONAL, CARDINALITY_REQUIRED, }) @Retention(RetentionPolicy.SOURCE) public @interface Cardinality {} /** Any number of items (including zero) [0...*]. */ public static final int CARDINALITY_REPEATED = 1; /** Zero or one value [0,1]. */ public static final int CARDINALITY_OPTIONAL = 2; /** Exactly one value [1]. */ public static final int CARDINALITY_REQUIRED = 3; private final PropertyConfigProto mProto; private PropertyConfig(PropertyConfigProto proto) { mProto = proto; } /** * Builder for {@link PropertyConfig}. * * <p>The following properties must be set, or {@link PropertyConfig} construction will * fail: * <ul> * <li>dataType * <li>cardinality * </ul> * * <p>In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType} * is also required. */ public static final class Builder { private final PropertyConfigProto.Builder mProtoBuilder = PropertyConfigProto.newBuilder(); private Builder(String propertyName) { mProtoBuilder.setPropertyName(propertyName); } /** * Type of data the property contains (e.g. string, int, bytes, etc). * * <p>This property must be set. */ @NonNull public PropertyConfig.Builder setDataType(@DataType int dataType) { PropertyConfigProto.DataType.Code dataTypeProto = PropertyConfigProto.DataType.Code.forNumber(dataType); if (dataTypeProto == null) { throw new IllegalArgumentException("Invalid dataType: " + dataType); } mProtoBuilder.setDataType(dataTypeProto); return this; } /** * The logical schema-type of the contents of this property. * * <p>Only required when {@link #setDataType(int)} is set to * {@link #DATA_TYPE_DOCUMENT}. Otherwise, it is ignored. */ @NonNull public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) { mProtoBuilder.setSchemaType(schemaType); return this; } /** * The cardinality of the property (whether it is optional, required or repeated). * * <p>This property must be set. */ @NonNull public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) { PropertyConfigProto.Cardinality.Code cardinalityProto = PropertyConfigProto.Cardinality.Code.forNumber(cardinality); if (cardinalityProto == null) { throw new IllegalArgumentException("Invalid cardinality: " + cardinality); } mProtoBuilder.setCardinality(cardinalityProto); return this; } /** * Configures how this property should be indexed. * * <p>If this is not supplied, the property will not be indexed at all. */ @NonNull public PropertyConfig.Builder setIndexingConfig( @NonNull IndexingConfig indexingConfig) { mProtoBuilder.setIndexingConfig(indexingConfig.mProto); return this; } /** * Constructs a new {@link PropertyConfig} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. * * @throws IllegalSchemaException If the property is not correctly populated (e.g. * missing {@code dataType}). */ @NonNull public PropertyConfig build() { if (mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.UNKNOWN) { throw new IllegalSchemaException("Missing dataType field"); } if (mProtoBuilder.getSchemaType().isEmpty() && mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.DOCUMENT) { throw new IllegalSchemaException( "Missing field: schemaType (required for configs with " + "dataType = DOCUMENT)"); } if (mProtoBuilder.getCardinality() == PropertyConfigProto.Cardinality.Code.UNKNOWN) { throw new IllegalSchemaException("Missing cardinality field"); } return new PropertyConfig(mProtoBuilder.build()); } } } /** Configures how a property should be indexed so that it can be retrieved by queries. */ public static final class IndexingConfig { /** Encapsulates the configurations on how AppSearch should query/index these terms. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.TermMatchType.Code. @IntDef(prefix = {"TERM_MATCH_TYPE_"}, value = { TERM_MATCH_TYPE_UNKNOWN, TERM_MATCH_TYPE_EXACT_ONLY, TERM_MATCH_TYPE_PREFIX, }) @Retention(RetentionPolicy.SOURCE) public @interface TermMatchType {} /** * Content in this property will not be tokenized or indexed. * * <p>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). All the properties inside the nested property won't be indexed regardless of the * value of {@code termMatchType} for the nested properties. */ public static final int TERM_MATCH_TYPE_UNKNOWN = 0; /** * Content in this property should only be returned for queries matching the exact tokens * appearing in this property. * * <p>Ex. A property with "fool" should NOT match a query for "foo". */ public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1; /** * Content in this property should be returned for queries that are either exact matches or * query matches of the tokens appearing in this property. * * <p>Ex. A property with "fool" <b>should</b> match a query for "foo". */ public static final int TERM_MATCH_TYPE_PREFIX = 2; /** Configures how tokens should be extracted from this property. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code. @IntDef(prefix = {"TOKENIZER_TYPE_"}, value = { TOKENIZER_TYPE_NONE, TOKENIZER_TYPE_PLAIN, }) @Retention(RetentionPolicy.SOURCE) public @interface TokenizerType {} /** * It is only valid for tokenizer_type to be 'NONE' if the data type is * {@link PropertyConfig#DATA_TYPE_DOCUMENT}. */ public static final int TOKENIZER_TYPE_NONE = 0; /** Tokenization for plain text. */ public static final int TOKENIZER_TYPE_PLAIN = 1; private final com.google.android.icing.proto.IndexingConfig mProto; private IndexingConfig(com.google.android.icing.proto.IndexingConfig proto) { mProto = proto; } /** * Builder for {@link IndexingConfig} objects. * * <p>You may skip adding an {@link IndexingConfig} for a property, which is equivalent to * an {@link IndexingConfig} having {@code termMatchType} equal to * {@link #TERM_MATCH_TYPE_UNKNOWN}. In this case the property will not be indexed. */ public static final class Builder { private final com.google.android.icing.proto.IndexingConfig.Builder mProtoBuilder = com.google.android.icing.proto.IndexingConfig.newBuilder(); private Builder() {} /** Configures how the content of this property should be matched in the index. */ @NonNull public IndexingConfig.Builder setTermMatchType(@TermMatchType int termMatchType) { com.google.android.icing.proto.TermMatchType.Code termMatchTypeProto = com.google.android.icing.proto.TermMatchType.Code.forNumber(termMatchType); if (termMatchTypeProto == null) { throw new IllegalArgumentException("Invalid termMatchType: " + termMatchType); } mProtoBuilder.setTermMatchType(termMatchTypeProto); return this; } /** Configures how this property should be tokenized (split into words). */ @NonNull public IndexingConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { com.google.android.icing.proto.IndexingConfig.TokenizerType.Code tokenizerTypeProto = com.google.android.icing.proto.IndexingConfig .TokenizerType.Code.forNumber(tokenizerType); if (tokenizerTypeProto == null) { throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); } mProtoBuilder.setTokenizerType(tokenizerTypeProto); return this; } /** * Constructs a new {@link IndexingConfig} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public IndexingConfig build() { return new IndexingConfig(mProtoBuilder.build()); } } } } apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,18 @@ * limitations under the License. */ package android.app.appsearch; import com.android.internal.infra.AndroidFuture; /** {@hide} */ interface IAppSearchManager { /** * Sets the schema. * * @param schemaProto serialized SchemaProto * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with * {@code null} upon successful completion of the setSchema call, or completed exceptionally * if setSchema fails. */ void setSchema(in byte[] schemaProto, in AndroidFuture callback); } Loading
Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -510,6 +510,7 @@ java_library { "exoplayer2-core", "android.hardware.wifi-V1.0-java-constants", ], libs: ["icing-java-proto-lite"], apex_available: ["//apex_available:platform"], } Loading
apex/appsearch/framework/Android.bp +23 −20 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ java_library { libs: [ "framework-minus-apex", // TODO(b/146218515) should be framework-system-stubs ], static_libs: [ "icing-java-proto-lite", ], visibility: [ "//frameworks/base/apex/appsearch:__subpackages__", // TODO(b/146218515) remove this when framework is built with the stub of appsearch Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +67 −4 Original line number Diff line number Diff line Loading @@ -15,21 +15,84 @@ */ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import com.android.internal.infra.AndroidFuture; import com.google.android.icing.proto.SchemaProto; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * TODO(b/142567528): add comments when implement this class * This class provides access to the centralized AppSearch index maintained by the system. * * <p>Apps can index structured text documents with AppSearch, which can then be retrieved through * the query API. * * @hide */ @SystemService(Context.APP_SEARCH_SERVICE) public class AppSearchManager { private final IAppSearchManager mService; /** @hide */ public AppSearchManager(@NonNull IAppSearchManager service) { mService = service; } /** * TODO(b/142567528): add comments when implement this class * Sets the schema being used by documents provided to the #put method. * * <p>This operation is performed asynchronously. On success, the provided callback will be * called with {@code null}. On failure, the provided callback will be called with a * {@link Throwable} describing the failure. * * <p>It is a no-op to set the same schema as has been previously set; this is handled * efficiently. * * <p>AppSearch automatically handles the following types of schema changes: * <ul> * <li>Addition of new types (No changes to storage or index) * <li>Removal of an existing type (All documents of the removed type are deleted) * <li>Addition of new 'optional' property to a type (No changes to storage or index) * <li>Removal of existing property of any cardinality (All documents reindexed) * </ul> * * <p>This method will return an error when attempting to make the following types of changes: * <ul> * <li>Changing the type of an existing property * <li>Adding a 'required' property * </ul> * * @param schema The schema config for this app. * @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}. * * @hide */ public AppSearchManager(IAppSearchManager service) { mService = service; // TODO(b/143789408): linkify #put after that API is created // TODO(b/145635424): add a 'force' param to setSchema after the corresponding API is finalized // in Icing Library // TODO(b/145635424): Update the documentation above once the Schema mutation APIs of Icing // Library are finalized public void setSchema( @NonNull AppSearchSchema schema, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<? super Throwable> callback) { SchemaProto schemaProto = schema.getProto(); byte[] schemaBytes = schemaProto.toByteArray(); AndroidFuture<Void> future = new AndroidFuture<>(); try { mService.setSchema(schemaBytes, future); } catch (RemoteException e) { future.completeExceptionally(e); } future.whenCompleteAsync((noop, err) -> callback.accept(err), executor); } }
apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java 0 → 100644 +423 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; import com.google.android.icing.proto.PropertyConfigProto; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SchemaTypeConfigProto; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Representation of the AppSearch Schema. * * <p>The schema is the set of document types, properties, and config (like tokenization type) * understood by AppSearch for this app. * * @hide */ public final class AppSearchSchema { private final SchemaProto mProto; private AppSearchSchema(SchemaProto proto) { mProto = proto; } /** Creates a new {@link AppSearchSchema.Builder}. */ @NonNull public static AppSearchSchema.Builder newBuilder() { return new AppSearchSchema.Builder(); } /** Creates a new {@link SchemaType.Builder}. */ @NonNull public static SchemaType.Builder newSchemaTypeBuilder(@NonNull String typeName) { return new SchemaType.Builder(typeName); } /** Creates a new {@link PropertyConfig.Builder}. */ @NonNull public static PropertyConfig.Builder newPropertyBuilder(@NonNull String propertyName) { return new PropertyConfig.Builder(propertyName); } /** Creates a new {@link IndexingConfig.Builder}. */ @NonNull public static IndexingConfig.Builder newIndexingConfigBuilder() { return new IndexingConfig.Builder(); } /** * Returns the schema proto populated by the {@link AppSearchSchema} builders. * @hide */ @NonNull SchemaProto getProto() { return mProto; } /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { private final SchemaProto.Builder mProtoBuilder = SchemaProto.newBuilder(); private Builder() {} /** Adds a supported type to this app's AppSearch schema. */ @NonNull public AppSearchSchema.Builder addType(@NonNull SchemaType schemaType) { mProtoBuilder.addTypes(schemaType.mProto); return this; } /** * Constructs a new {@link AppSearchSchema} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public AppSearchSchema build() { return new AppSearchSchema(mProtoBuilder.build()); } } /** * Represents a type of a document. * * <p>For example, an e-mail message or a music recording could be a schema type. */ public static final class SchemaType { private final SchemaTypeConfigProto mProto; private SchemaType(SchemaTypeConfigProto proto) { mProto = proto; } /** Builder for {@link SchemaType} objects. */ public static final class Builder { private final SchemaTypeConfigProto.Builder mProtoBuilder = SchemaTypeConfigProto.newBuilder(); private Builder(@NonNull String typeName) { mProtoBuilder.setSchemaType(typeName); } /** Adds a property to the given type. */ @NonNull public SchemaType.Builder addProperty(@NonNull PropertyConfig propertyConfig) { mProtoBuilder.addProperties(propertyConfig.mProto); return this; } /** * Constructs a new {@link SchemaType} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public SchemaType build() { return new SchemaType(mProtoBuilder.build()); } } } /** * Configuration for a single property (field) of a document type. * * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be * a property. */ public static final class PropertyConfig { /** Physical data-types of the contents of the property. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.DataType.Code. @IntDef(prefix = {"DATA_TYPE_"}, value = { DATA_TYPE_STRING, DATA_TYPE_INT64, DATA_TYPE_DOUBLE, DATA_TYPE_BOOLEAN, DATA_TYPE_BYTES, DATA_TYPE_DOCUMENT, }) @Retention(RetentionPolicy.SOURCE) public @interface DataType {} public static final int DATA_TYPE_STRING = 1; public static final int DATA_TYPE_INT64 = 2; public static final int DATA_TYPE_DOUBLE = 3; public static final int DATA_TYPE_BOOLEAN = 4; /** Unstructured BLOB. */ public static final int DATA_TYPE_BYTES = 5; /** * Indicates that the property itself is an Document, making it part a hierarchical * Document schema. Any property using this DataType MUST have a valid * {@code schemaType}. */ public static final int DATA_TYPE_DOCUMENT = 6; /** The cardinality of the property (whether it is required, optional or repeated). */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code. @IntDef(prefix = {"CARDINALITY_"}, value = { CARDINALITY_REPEATED, CARDINALITY_OPTIONAL, CARDINALITY_REQUIRED, }) @Retention(RetentionPolicy.SOURCE) public @interface Cardinality {} /** Any number of items (including zero) [0...*]. */ public static final int CARDINALITY_REPEATED = 1; /** Zero or one value [0,1]. */ public static final int CARDINALITY_OPTIONAL = 2; /** Exactly one value [1]. */ public static final int CARDINALITY_REQUIRED = 3; private final PropertyConfigProto mProto; private PropertyConfig(PropertyConfigProto proto) { mProto = proto; } /** * Builder for {@link PropertyConfig}. * * <p>The following properties must be set, or {@link PropertyConfig} construction will * fail: * <ul> * <li>dataType * <li>cardinality * </ul> * * <p>In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType} * is also required. */ public static final class Builder { private final PropertyConfigProto.Builder mProtoBuilder = PropertyConfigProto.newBuilder(); private Builder(String propertyName) { mProtoBuilder.setPropertyName(propertyName); } /** * Type of data the property contains (e.g. string, int, bytes, etc). * * <p>This property must be set. */ @NonNull public PropertyConfig.Builder setDataType(@DataType int dataType) { PropertyConfigProto.DataType.Code dataTypeProto = PropertyConfigProto.DataType.Code.forNumber(dataType); if (dataTypeProto == null) { throw new IllegalArgumentException("Invalid dataType: " + dataType); } mProtoBuilder.setDataType(dataTypeProto); return this; } /** * The logical schema-type of the contents of this property. * * <p>Only required when {@link #setDataType(int)} is set to * {@link #DATA_TYPE_DOCUMENT}. Otherwise, it is ignored. */ @NonNull public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) { mProtoBuilder.setSchemaType(schemaType); return this; } /** * The cardinality of the property (whether it is optional, required or repeated). * * <p>This property must be set. */ @NonNull public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) { PropertyConfigProto.Cardinality.Code cardinalityProto = PropertyConfigProto.Cardinality.Code.forNumber(cardinality); if (cardinalityProto == null) { throw new IllegalArgumentException("Invalid cardinality: " + cardinality); } mProtoBuilder.setCardinality(cardinalityProto); return this; } /** * Configures how this property should be indexed. * * <p>If this is not supplied, the property will not be indexed at all. */ @NonNull public PropertyConfig.Builder setIndexingConfig( @NonNull IndexingConfig indexingConfig) { mProtoBuilder.setIndexingConfig(indexingConfig.mProto); return this; } /** * Constructs a new {@link PropertyConfig} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. * * @throws IllegalSchemaException If the property is not correctly populated (e.g. * missing {@code dataType}). */ @NonNull public PropertyConfig build() { if (mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.UNKNOWN) { throw new IllegalSchemaException("Missing dataType field"); } if (mProtoBuilder.getSchemaType().isEmpty() && mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.DOCUMENT) { throw new IllegalSchemaException( "Missing field: schemaType (required for configs with " + "dataType = DOCUMENT)"); } if (mProtoBuilder.getCardinality() == PropertyConfigProto.Cardinality.Code.UNKNOWN) { throw new IllegalSchemaException("Missing cardinality field"); } return new PropertyConfig(mProtoBuilder.build()); } } } /** Configures how a property should be indexed so that it can be retrieved by queries. */ public static final class IndexingConfig { /** Encapsulates the configurations on how AppSearch should query/index these terms. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.TermMatchType.Code. @IntDef(prefix = {"TERM_MATCH_TYPE_"}, value = { TERM_MATCH_TYPE_UNKNOWN, TERM_MATCH_TYPE_EXACT_ONLY, TERM_MATCH_TYPE_PREFIX, }) @Retention(RetentionPolicy.SOURCE) public @interface TermMatchType {} /** * Content in this property will not be tokenized or indexed. * * <p>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). All the properties inside the nested property won't be indexed regardless of the * value of {@code termMatchType} for the nested properties. */ public static final int TERM_MATCH_TYPE_UNKNOWN = 0; /** * Content in this property should only be returned for queries matching the exact tokens * appearing in this property. * * <p>Ex. A property with "fool" should NOT match a query for "foo". */ public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1; /** * Content in this property should be returned for queries that are either exact matches or * query matches of the tokens appearing in this property. * * <p>Ex. A property with "fool" <b>should</b> match a query for "foo". */ public static final int TERM_MATCH_TYPE_PREFIX = 2; /** Configures how tokens should be extracted from this property. */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code. @IntDef(prefix = {"TOKENIZER_TYPE_"}, value = { TOKENIZER_TYPE_NONE, TOKENIZER_TYPE_PLAIN, }) @Retention(RetentionPolicy.SOURCE) public @interface TokenizerType {} /** * It is only valid for tokenizer_type to be 'NONE' if the data type is * {@link PropertyConfig#DATA_TYPE_DOCUMENT}. */ public static final int TOKENIZER_TYPE_NONE = 0; /** Tokenization for plain text. */ public static final int TOKENIZER_TYPE_PLAIN = 1; private final com.google.android.icing.proto.IndexingConfig mProto; private IndexingConfig(com.google.android.icing.proto.IndexingConfig proto) { mProto = proto; } /** * Builder for {@link IndexingConfig} objects. * * <p>You may skip adding an {@link IndexingConfig} for a property, which is equivalent to * an {@link IndexingConfig} having {@code termMatchType} equal to * {@link #TERM_MATCH_TYPE_UNKNOWN}. In this case the property will not be indexed. */ public static final class Builder { private final com.google.android.icing.proto.IndexingConfig.Builder mProtoBuilder = com.google.android.icing.proto.IndexingConfig.newBuilder(); private Builder() {} /** Configures how the content of this property should be matched in the index. */ @NonNull public IndexingConfig.Builder setTermMatchType(@TermMatchType int termMatchType) { com.google.android.icing.proto.TermMatchType.Code termMatchTypeProto = com.google.android.icing.proto.TermMatchType.Code.forNumber(termMatchType); if (termMatchTypeProto == null) { throw new IllegalArgumentException("Invalid termMatchType: " + termMatchType); } mProtoBuilder.setTermMatchType(termMatchTypeProto); return this; } /** Configures how this property should be tokenized (split into words). */ @NonNull public IndexingConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { com.google.android.icing.proto.IndexingConfig.TokenizerType.Code tokenizerTypeProto = com.google.android.icing.proto.IndexingConfig .TokenizerType.Code.forNumber(tokenizerType); if (tokenizerTypeProto == null) { throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); } mProtoBuilder.setTokenizerType(tokenizerTypeProto); return this; } /** * Constructs a new {@link IndexingConfig} from the contents of this builder. * * <p>After calling this method, the builder must no longer be used. */ @NonNull public IndexingConfig build() { return new IndexingConfig(mProtoBuilder.build()); } } } }
apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,18 @@ * limitations under the License. */ package android.app.appsearch; import com.android.internal.infra.AndroidFuture; /** {@hide} */ interface IAppSearchManager { /** * Sets the schema. * * @param schemaProto serialized SchemaProto * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with * {@code null} upon successful completion of the setSchema call, or completed exceptionally * if setSchema fails. */ void setSchema(in byte[] schemaProto, in AndroidFuture callback); }