From f4a8941ff8d49c6675cd4d8f643157fbd3d9a668 Mon Sep 17 00:00:00 2001 From: Alexander Dorokhine Date: Fri, 20 Nov 2020 14:03:41 -0800 Subject: [PATCH] Re-export with google-java-format --aosp running on all exported classes This cleans up formatting issues arising from automatic rewriting. There are no functional changes in this CL. Bug: 162450968 Test: Builds Change-Id: I58a6f7af5ca48c6989b00f1afb8110d49f7552a7 --- .../android/app/appsearch/AppSearchEmail.java | 130 ++-- .../app/appsearch/AppSearchSchema.java | 96 +-- .../app/appsearch/GenericDocument.java | 183 +++--- .../app/appsearch/GetByUriRequest.java | 1 + .../app/appsearch/PutDocumentsRequest.java | 8 +- .../app/appsearch/RemoveByUriRequest.java | 1 + .../android/app/appsearch/SearchResult.java | 149 +++-- .../app/appsearch/SearchResultPage.java | 11 +- .../android/app/appsearch/SearchSpec.java | 101 +-- .../app/appsearch/SetSchemaRequest.java | 8 +- .../exceptions/AppSearchException.java | 10 +- .../exceptions/IllegalSchemaException.java | 2 - .../IllegalSearchSpecException.java | 6 +- .../external/localstorage/AppSearchImpl.java | 327 ++++----- .../localstorage/VisibilityStore.java | 97 +-- .../GenericDocumentToProtoConverter.java | 7 +- .../converter/SchemaToProtoConverter.java | 16 +- .../SearchResultToProtoConverter.java | 10 +- .../converter/SearchSpecToProtoConverter.java | 15 +- .../external/app/AppSearchEmailTest.java | 27 +- .../external/app/SearchSpecTest.java | 31 +- .../app/cts/AppSearchResultCtsTest.java | 25 +- .../app/cts/AppSearchSchemaCtsTest.java | 38 +- .../app/cts/GenericDocumentCtsTest.java | 304 +++++---- .../external/app/cts/SearchSpecCtsTest.java | 36 +- .../cts/customer/CustomerDocumentTest.java | 62 +- .../localstorage/AppSearchImplTest.java | 618 ++++++++++-------- .../localstorage/VisibilityStoreTest.java | 4 +- .../GenericDocumentToProtoConverterTest.java | 65 +- .../converter/SchemaToProtoConverterTest.java | 186 +++--- .../localstorage/converter/SnippetTest.java | 228 ++++--- 31 files changed, 1525 insertions(+), 1277 deletions(-) diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java index beb9ad3d27ea4..9ca363ed9008e 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java @@ -16,10 +16,8 @@ package android.app.appsearch; - import android.annotation.NonNull; import android.annotation.Nullable; - import android.app.appsearch.AppSearchSchema.PropertyConfig; /** @@ -29,9 +27,8 @@ import android.app.appsearch.AppSearchSchema.PropertyConfig; * * @hide */ - public class AppSearchEmail extends GenericDocument { - /** The name of the schema type for {@link AppSearchEmail} documents.*/ + /** The name of the schema type for {@link AppSearchEmail} documents. */ public static final String SCHEMA_TYPE = "builtin:Email"; private static final String KEY_FROM = "from"; @@ -41,54 +38,55 @@ public class AppSearchEmail extends GenericDocument { private static final String KEY_SUBJECT = "subject"; private static final String KEY_BODY = "body"; - public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE) - .addProperty(new PropertyConfig.Builder(KEY_FROM) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).addProperty(new PropertyConfig.Builder(KEY_TO) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).addProperty(new PropertyConfig.Builder(KEY_CC) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).addProperty(new PropertyConfig.Builder(KEY_BCC) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).addProperty(new PropertyConfig.Builder(KEY_SUBJECT) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).addProperty(new PropertyConfig.Builder(KEY_BODY) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .build() - - ).build(); + public static final AppSearchSchema SCHEMA = + new AppSearchSchema.Builder(SCHEMA_TYPE) + .addProperty( + new PropertyConfig.Builder(KEY_FROM) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .addProperty( + new PropertyConfig.Builder(KEY_TO) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .addProperty( + new PropertyConfig.Builder(KEY_CC) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .addProperty( + new PropertyConfig.Builder(KEY_BCC) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .addProperty( + new PropertyConfig.Builder(KEY_SUBJECT) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .addProperty( + new PropertyConfig.Builder(KEY_BODY) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build()) + .build(); /** - * Creates a new {@link AppSearchEmail} from the contents of an existing - * {@link GenericDocument}. + * Creates a new {@link AppSearchEmail} from the contents of an existing {@link + * GenericDocument}. * * @param document The {@link GenericDocument} containing the email content. */ @@ -109,8 +107,8 @@ public class AppSearchEmail extends GenericDocument { /** * Gets the destination addresses of {@link AppSearchEmail}. * - * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not - * been set yet. + * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not been + * set yet. */ @Nullable public String[] getTo() { @@ -157,9 +155,7 @@ public class AppSearchEmail extends GenericDocument { return getPropertyString(KEY_BODY); } - /** - * The builder class for {@link AppSearchEmail}. - */ + /** The builder class for {@link AppSearchEmail}. */ public static class Builder extends GenericDocument.Builder { /** @@ -171,54 +167,42 @@ public class AppSearchEmail extends GenericDocument { super(uri, SCHEMA_TYPE); } - /** - * Sets the from address of {@link AppSearchEmail} - */ + /** Sets the from address of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setFrom(@NonNull String from) { setPropertyString(KEY_FROM, from); return this; } - /** - * Sets the destination address of {@link AppSearchEmail} - */ + /** Sets the destination address of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setTo(@NonNull String... to) { setPropertyString(KEY_TO, to); return this; } - /** - * Sets the CC list of {@link AppSearchEmail} - */ + /** Sets the CC list of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setCc(@NonNull String... cc) { setPropertyString(KEY_CC, cc); return this; } - /** - * Sets the BCC list of {@link AppSearchEmail} - */ + /** Sets the BCC list of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setBcc(@NonNull String... bcc) { setPropertyString(KEY_BCC, bcc); return this; } - /** - * Sets the subject of {@link AppSearchEmail} - */ + /** Sets the subject of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setSubject(@NonNull String subject) { setPropertyString(KEY_SUBJECT, subject); return this; } - /** - * Sets the body of {@link AppSearchEmail} - */ + /** Sets the body of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setBody(@NonNull String body) { setPropertyString(KEY_BODY, body); diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java index 7fa69368d45f5..1e27d1f5d8569 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java @@ -16,15 +16,14 @@ package android.app.appsearch; -import android.annotation.SuppressLint; -import android.os.Bundle; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; - +import android.annotation.SuppressLint; import android.app.appsearch.exceptions.IllegalSchemaException; +import android.os.Bundle; import android.util.ArraySet; + import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -51,7 +50,6 @@ public final class AppSearchSchema { private final Bundle mBundle; /** @hide */ - public AppSearchSchema(@NonNull Bundle bundle) { Preconditions.checkNotNull(bundle); mBundle = bundle; @@ -59,9 +57,9 @@ public final class AppSearchSchema { /** * Returns the {@link Bundle} populated by this builder. + * * @hide */ - @NonNull public Bundle getBundle() { return mBundle; @@ -146,8 +144,8 @@ public final class AppSearchSchema { /** * Configuration for a single property (field) of a document type. * - *

For example, an {@code EmailMessage} would be a type and the {@code subject} would be - * a property. + *

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"; @@ -159,18 +157,20 @@ public final class AppSearchSchema { /** * Physical data-types of the contents of the property. + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.DataType.Code. - @IntDef(value = { - DATA_TYPE_STRING, - DATA_TYPE_INT64, - DATA_TYPE_DOUBLE, - DATA_TYPE_BOOLEAN, - DATA_TYPE_BYTES, - DATA_TYPE_DOCUMENT, - }) + @IntDef( + 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 {} @@ -183,23 +183,24 @@ public final class AppSearchSchema { 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}. + * 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). + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code. - @IntDef(value = { - CARDINALITY_REPEATED, - CARDINALITY_OPTIONAL, - CARDINALITY_REQUIRED, - }) + @IntDef( + value = { + CARDINALITY_REPEATED, + CARDINALITY_OPTIONAL, + CARDINALITY_REQUIRED, + }) @Retention(RetentionPolicy.SOURCE) public @interface Cardinality {} @@ -214,23 +215,25 @@ public final class AppSearchSchema { /** * Encapsulates the configurations on how AppSearch should query/index these terms. + * * @hide */ - @IntDef(value = { - INDEXING_TYPE_NONE, - INDEXING_TYPE_EXACT_TERMS, - INDEXING_TYPE_PREFIXES, - }) + @IntDef( + value = { + INDEXING_TYPE_NONE, + INDEXING_TYPE_EXACT_TERMS, + INDEXING_TYPE_PREFIXES, + }) @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). All the properties inside the nested property won't be indexed regardless of the - * value of {@code indexingType} for the nested properties. + *

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 indexingType} for the nested properties. */ public static final int INDEXING_TYPE_NONE = 0; @@ -252,20 +255,22 @@ public final class AppSearchSchema { /** * Configures how tokens should be extracted from this property. + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code. - @IntDef(value = { - TOKENIZER_TYPE_NONE, - TOKENIZER_TYPE_PLAIN, - }) + @IntDef( + 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}. + * 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; @@ -297,8 +302,8 @@ public final class AppSearchSchema { /** * 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}. + *

Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. Otherwise, + * it is {@code null}. */ @Nullable public String getSchemaType() { @@ -327,9 +332,10 @@ public final class AppSearchSchema { * *

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

* *

In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType} @@ -361,8 +367,8 @@ public final class AppSearchSchema { /** * 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. + *

Only required when {@link #setDataType} is set to {@link #DATA_TYPE_DOCUMENT}. + * Otherwise, it is ignored. */ @NonNull public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) { diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java index 8d343460ddc04..f41fa8df453a9 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java @@ -16,15 +16,14 @@ package android.app.appsearch; -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.util.Log; - import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; - +import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; +import android.os.Bundle; +import android.util.Log; + import com.android.internal.util.Preconditions; import java.lang.reflect.Array; @@ -46,12 +45,12 @@ import java.util.Set; public class GenericDocument { private static final String TAG = "GenericDocument"; - /** The default empty namespace.*/ + /** The default empty namespace. */ public static final String DEFAULT_NAMESPACE = ""; /** - * The maximum number of elements in a repeatable field. Will reject the request if exceed - * this limit. + * The maximum number of elements in a repeatable field. Will reject the request if exceed this + * limit. */ private static final int MAX_REPEATED_PROPERTY_LENGTH = 100; @@ -82,46 +81,43 @@ 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 where the {@link + * AppSearchSchema.PropertyConfig#getIndexingType()} constant is anything other than {@link + * AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}. */ public static int getMaxIndexedProperties() { return MAX_INDEXED_PROPERTIES; } - /** Contains {@link GenericDocument} basic information (uri, schemaType etc).*/ - @NonNull - final Bundle mBundle; + /** Contains {@link GenericDocument} basic information (uri, schemaType etc). */ + @NonNull final Bundle mBundle; - /** Contains all properties in {@link GenericDocument} to support getting properties via keys.*/ - @NonNull - private final Bundle mProperties; + /** + * Contains all properties in {@link GenericDocument} to support getting properties via keys. + */ + @NonNull private final Bundle mProperties; - @NonNull - private final String mUri; - @NonNull - private final String mSchemaType; + @NonNull private final String mUri; + @NonNull private final String mSchemaType; private final long mCreationTimestampMillis; - @Nullable - private Integer mHashCode; + @Nullable private Integer mHashCode; /** * Rebuilds a {@link GenericDocument} by the a bundle. - * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and - * a properties bundle contains all properties in {@link GenericDocument} to - * support getting properties via keys. + * + * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and a + * properties bundle contains all properties in {@link GenericDocument} to support getting + * properties via keys. * @hide */ - public GenericDocument(@NonNull Bundle bundle) { Preconditions.checkNotNull(bundle); mBundle = bundle; mProperties = Preconditions.checkNotNull(bundle.getParcelable(PROPERTIES_FIELD)); mUri = Preconditions.checkNotNull(mBundle.getString(URI_FIELD)); mSchemaType = Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD)); - mCreationTimestampMillis = mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, - System.currentTimeMillis()); + mCreationTimestampMillis = + mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis()); } /** @@ -135,9 +131,9 @@ public class GenericDocument { /** * Returns the {@link Bundle} populated by this builder. + * * @hide */ - @NonNull public Bundle getBundle() { return mBundle; @@ -178,7 +174,7 @@ public class GenericDocument { * time base, the document will be auto-deleted. * *

The default value is 0, which means the document is permanent and won't be auto-deleted - * until the app is uninstalled. + * until the app is uninstalled. */ public long getTtlMillis() { return mBundle.getLong(TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS); @@ -187,8 +183,8 @@ public class GenericDocument { /** * Returns the score of the {@link GenericDocument}. * - *

The score is a query-independent measure of the document's quality, relative to - * other {@link GenericDocument}s of the same type. + *

The score is a query-independent measure of the document's quality, relative to other + * {@link GenericDocument}s of the same type. * *

Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}. * Documents with higher scores are considered better than documents with lower scores. @@ -209,8 +205,8 @@ public class GenericDocument { * Retrieves a {@link String} value by key. * * @param key The key to look for. - * @return The first {@link String} associated with the given key or {@code null} if there - * is no such key or the value is of a different type. + * @return The first {@link String} associated with the given key or {@code null} if there is no + * such key or the value is of a different type. */ @Nullable public String getPropertyString(@NonNull String key) { @@ -228,7 +224,7 @@ public class GenericDocument { * * @param key The key to look for. * @return The first {@code long} associated with the given key or default value {@code 0} if - * there is no such key or the value is of a different type. + * there is no such key or the value is of a different type. */ public long getPropertyLong(@NonNull String key) { Preconditions.checkNotNull(key); @@ -245,7 +241,7 @@ public class GenericDocument { * * @param key The key to look for. * @return The first {@code double} associated with the given key or default value {@code 0.0} - * if there is no such key or the value is of a different type. + * if there is no such key or the value is of a different type. */ public double getPropertyDouble(@NonNull String key) { Preconditions.checkNotNull(key); @@ -261,8 +257,8 @@ public class GenericDocument { * Retrieves a {@code boolean} value by key. * * @param key The key to look for. - * @return The first {@code boolean} associated with the given key or default value - * {@code false} if there is no such key or the value is of a different type. + * @return The first {@code boolean} associated with the given key or default value {@code + * false} if there is no such key or the value is of a different type. */ public boolean getPropertyBoolean(@NonNull String key) { Preconditions.checkNotNull(key); @@ -278,8 +274,8 @@ public class GenericDocument { * Retrieves a {@code byte[]} value by key. * * @param key The key to look for. - * @return The first {@code byte[]} associated with the given key or {@code null} if there - * is no such key or the value is of a different type. + * @return The first {@code byte[]} associated with the given key or {@code null} if there is no + * such key or the value is of a different type. */ @Nullable public byte[] getPropertyBytes(@NonNull String key) { @@ -297,7 +293,7 @@ public class GenericDocument { * * @param key The key to look for. * @return The first {@link GenericDocument} associated with the given key or {@code null} if - * there is no such key or the value is of a different type. + * there is no such key or the value is of a different type. */ @Nullable public GenericDocument getPropertyDocument(@NonNull String key) { @@ -314,10 +310,18 @@ public class GenericDocument { private static void warnIfSinglePropertyTooLong( @NonNull String propertyType, @NonNull String key, int propertyLength) { if (propertyLength > 1) { - Log.w(TAG, "The value for \"" + key + "\" contains " + propertyLength - + " elements. Only the first one will be returned from " - + "getProperty" + propertyType + "(). Try getProperty" + propertyType - + "Array()."); + Log.w( + TAG, + "The value for \"" + + key + + "\" contains " + + propertyLength + + " elements. Only the first one will be returned from " + + "getProperty" + + propertyType + + "(). Try getProperty" + + propertyType + + "Array()."); } } @@ -325,8 +329,8 @@ public class GenericDocument { * Retrieves a repeated {@code String} property by key. * * @param key The key to look for. - * @return The {@code String[]} associated with the given key, or {@code null} if no value - * is set or the value is of a different type. + * @return The {@code String[]} associated with the given key, or {@code null} if no value is + * set or the value is of a different type. */ @Nullable public String[] getPropertyStringArray(@NonNull String key) { @@ -338,8 +342,8 @@ public class GenericDocument { * Retrieves a repeated {@link String} property by key. * * @param key The key to look for. - * @return The {@code long[]} associated with the given key, or {@code null} if no value is - * set or the value is of a different type. + * @return The {@code long[]} associated with the given key, or {@code null} if no value is set + * or the value is of a different type. */ @Nullable public long[] getPropertyLongArray(@NonNull String key) { @@ -351,8 +355,8 @@ public class GenericDocument { * Retrieves a repeated {@code double} property by key. * * @param key The key to look for. - * @return The {@code double[]} associated with the given key, or {@code null} if no value - * is set or the value is of a different type. + * @return The {@code double[]} associated with the given key, or {@code null} if no value is + * set or the value is of a different type. */ @Nullable public double[] getPropertyDoubleArray(@NonNull String key) { @@ -364,8 +368,8 @@ public class GenericDocument { * Retrieves a repeated {@code boolean} property by key. * * @param key The key to look for. - * @return The {@code boolean[]} associated with the given key, or {@code null} if no value - * is set or the value is of a different type. + * @return The {@code boolean[]} associated with the given key, or {@code null} if no value is + * set or the value is of a different type. */ @Nullable public boolean[] getPropertyBooleanArray(@NonNull String key) { @@ -377,8 +381,8 @@ public class GenericDocument { * Retrieves a {@code byte[][]} property by key. * * @param key The key to look for. - * @return The {@code byte[][]} associated with the given key, or {@code null} if no value - * is set or the value is of a different type. + * @return The {@code byte[][]} associated with the given key, or {@code null} if no value is + * set or the value is of a different type. */ @SuppressLint("ArrayReturn") @Nullable @@ -411,7 +415,7 @@ public class GenericDocument { * * @param key The key to look for. * @return The {@link GenericDocument}[] associated with the given key, or {@code null} if no - * value is set or the value is of a different type. + * value is set or the value is of a different type. */ @SuppressLint("ArrayReturn") @Nullable @@ -433,8 +437,8 @@ public class GenericDocument { } /** - * Gets a repeated property of the given key, and casts it to the given class type, which - * must be an array class type. + * Gets a repeated property of the given key, and casts it to the given class type, which must + * be an array class type. */ @Nullable private T getAndCastPropertyArray(@NonNull String key, @NonNull Class tClass) { @@ -464,6 +468,7 @@ public class GenericDocument { /** * Deeply checks whether two bundles are equal. + * *

Two bundles will be considered equal if they contain the same content. */ @SuppressWarnings("unchecked") @@ -551,8 +556,9 @@ public class GenericDocument { /** * Calculates the hash code for a bundle. - *

The hash code is only effected by the contents in the bundle. Bundles will get - * consistent hash code if they have same contents. + * + *

The hash code is only effected by the contents in the bundle. Bundles will get consistent + * hash code if they have same contents. */ @SuppressWarnings("unchecked") private static int bundleHashCode(Bundle bundle) { @@ -677,11 +683,11 @@ public class GenericDocument { * Create a new {@link GenericDocument.Builder}. * * @param uri The uri of {@link GenericDocument}. - * @param schemaType The schema type of the {@link GenericDocument}. The passed-in - * {@code schemaType} must be defined using {@link AppSearchSession#setSchema} prior - * to inserting a document of this {@code schemaType} into the AppSearch index using - * {@link AppSearchSession#putDocuments}. Otherwise, the document will be - * rejected by {@link AppSearchSession#putDocuments}. + * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code + * schemaType} must be defined using {@link AppSearchSession#setSchema} prior to + * inserting a document of this {@code schemaType} into the AppSearch index using {@link + * AppSearchSession#putDocuments}. Otherwise, the document will be rejected by {@link + * AppSearchSession#putDocuments}. */ @SuppressWarnings("unchecked") public Builder(@NonNull String uri, @NonNull String schemaType) { @@ -692,16 +698,16 @@ public class GenericDocument { mBundle.putString(GenericDocument.SCHEMA_TYPE_FIELD, schemaType); mBundle.putString(GenericDocument.NAMESPACE_FIELD, DEFAULT_NAMESPACE); // Set current timestamp for creation timestamp by default. - mBundle.putLong(GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, - System.currentTimeMillis()); + mBundle.putLong( + GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis()); mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS); mBundle.putInt(GenericDocument.SCORE_FIELD, DEFAULT_SCORE); mBundle.putBundle(PROPERTIES_FIELD, mProperties); } /** - * Sets the app-defined namespace this Document resides in. No special values are - * reserved or understood by the infrastructure. + * Sets the app-defined namespace this Document resides in. No special values are reserved + * or understood by the infrastructure. * *

URIs are unique within a namespace. * @@ -716,8 +722,8 @@ public class GenericDocument { /** * Sets the score of the {@link GenericDocument}. * - *

The score is a query-independent measure of the document's quality, relative to - * other {@link GenericDocument}s of the same type. + *

The score is a query-independent measure of the document's quality, relative to other + * {@link GenericDocument}s of the same type. * *

Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}. * Documents with higher scores are considered better than documents with lower scores. @@ -745,8 +751,8 @@ public class GenericDocument { @NonNull public BuilderType setCreationTimestampMillis(long creationTimestampMillis) { Preconditions.checkState(!mBuilt, "Builder has already been used"); - mBundle.putLong(GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, - creationTimestampMillis); + mBundle.putLong( + GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, creationTimestampMillis); return mBuilderTypeInstance; } @@ -754,8 +760,8 @@ public class GenericDocument { * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds. * *

The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of - * {@code creationTimestampMillis + ttlMillis}, measured in the - * {@link System#currentTimeMillis} time base, the document will be auto-deleted. + * {@code creationTimestampMillis + ttlMillis}, measured in the {@link + * System#currentTimeMillis} time base, the document will be auto-deleted. * *

The default value is 0, which means the document is permanent and won't be * auto-deleted until the app is uninstalled. @@ -774,8 +780,7 @@ public class GenericDocument { } /** - * Sets one or multiple {@code String} values for a property, replacing its previous - * values. + * Sets one or multiple {@code String} values for a property, replacing its previous values. * * @param key The key associated with the {@code values}. * @param values The {@code String} values of the property. @@ -806,8 +811,7 @@ public class GenericDocument { } /** - * Sets one or multiple {@code long} values for a property, replacing its previous - * values. + * Sets one or multiple {@code long} values for a property, replacing its previous values. * * @param key The key associated with the {@code values}. * @param values The {@code long} values of the property. @@ -822,8 +826,7 @@ public class GenericDocument { } /** - * Sets one or multiple {@code double} values for a property, replacing its previous - * values. + * Sets one or multiple {@code double} values for a property, replacing its previous values. * * @param key The key associated with the {@code values}. * @param values The {@code double} values of the property. @@ -876,9 +879,14 @@ public class GenericDocument { if (values[i] == null) { throw new IllegalArgumentException("The String at " + i + " is null."); } else if (values[i].length() > MAX_STRING_LENGTH) { - throw new IllegalArgumentException("The String at " + i + " length is: " - + values[i].length() + ", which exceeds length limit: " - + MAX_STRING_LENGTH + "."); + throw new IllegalArgumentException( + "The String at " + + i + + " length is: " + + values[i].length() + + ", which exceeds length limit: " + + MAX_STRING_LENGTH + + "."); } } mProperties.putStringArray(key, values); @@ -936,7 +944,10 @@ public class GenericDocument { throw new IllegalArgumentException("The input array is empty."); } else if (length > MAX_REPEATED_PROPERTY_LENGTH) { throw new IllegalArgumentException( - "Repeated property \"" + key + "\" has length " + length + "Repeated property \"" + + key + + "\" has length " + + length + ", which exceeds the limit of " + MAX_REPEATED_PROPERTY_LENGTH); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java index e4be785997ec3..053d401d06dc1 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java @@ -18,6 +18,7 @@ package android.app.appsearch; import android.annotation.NonNull; import android.util.ArraySet; + import com.android.internal.util.Preconditions; import java.util.Arrays; diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java index 3f24ea9eefd47..42f1ff2a716a0 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java @@ -16,10 +16,10 @@ package android.app.appsearch; -import android.annotation.SuppressLint; - import android.annotation.NonNull; +import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; + import com.android.internal.util.Preconditions; import java.util.ArrayList; @@ -53,7 +53,7 @@ public final class PutDocumentsRequest { private boolean mBuilt = false; /** Adds one or more documents to the request. */ - @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments() + @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments() @NonNull public Builder addGenericDocument(@NonNull GenericDocument... documents) { Preconditions.checkNotNull(documents); @@ -61,7 +61,7 @@ public final class PutDocumentsRequest { } /** Adds one or more documents to the request. */ - @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments() + @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments() @NonNull public Builder addGenericDocument(@NonNull Collection documents) { Preconditions.checkState(!mBuilt, "Builder has already been used"); diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java index 58aadcd082c0e..3d83c390fbad7 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java @@ -18,6 +18,7 @@ package android.app.appsearch; import android.annotation.NonNull; import android.util.ArraySet; + import com.android.internal.util.Preconditions; import java.util.Arrays; diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java index 1a79b1085bfd2..5f3c06ad2d103 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java @@ -16,26 +16,26 @@ package android.app.appsearch; -import android.os.Bundle; - import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Bundle; -import java.util.Objects; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * This class represents one of the results obtained from an AppSearch query. * *

This allows clients to obtain: + * *

+ * * *

"Snippet" refers to a substring of text from the content of document that is returned as a * part of search result. @@ -45,40 +45,32 @@ import java.util.List; */ public final class SearchResult { /** @hide */ - public static final String DOCUMENT_FIELD = "document"; /** @hide */ - public static final String MATCHES_FIELD = "matches"; - @NonNull - private final Bundle mBundle; + @NonNull private final Bundle mBundle; - @NonNull - private final Bundle mDocumentBundle; + @NonNull private final Bundle mDocumentBundle; /** Cache of the inflated document. Comes from inflating mDocumentBundle at first use. */ - @Nullable - private GenericDocument mDocument; + @Nullable private GenericDocument mDocument; /** * Contains a list of MatchInfo bundles that matched the request. * - * Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and + *

Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and * {@link SearchSpec.Builder#setSnippetCountPerProperty}. * * @see #getMatches() */ - @NonNull - private final List mMatchBundles; + @NonNull private final List mMatchBundles; /** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */ - @Nullable - private List mMatches; + @Nullable private List mMatches; /** @hide */ - public SearchResult(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); mDocumentBundle = Preconditions.checkNotNull(bundle.getBundle(DOCUMENT_FIELD)); @@ -86,7 +78,6 @@ public final class SearchResult { } /** @hide */ - @NonNull public Bundle getBundle() { return mBundle; @@ -94,6 +85,7 @@ public final class SearchResult { /** * Contains the matching {@link GenericDocument}. + * * @return Document object which matched the query. */ @NonNull @@ -107,10 +99,10 @@ public final class SearchResult { /** * Contains a list of Snippets that matched the request. * - * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using - * {@link SearchSpec.Builder#setSnippetCount} or - * {@link SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that - * value, this method returns an empty list. + * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using {@link + * SearchSpec.Builder#setSnippetCount} or {@link + * SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that value, this + * method returns an empty list. */ @NonNull public List getMatches() { @@ -125,77 +117,94 @@ public final class SearchResult { } /** - * This class represents a match objects for any Snippets that might be present in - * {@link SearchResults} from query. Using this class - * user can get the full text, exact matches and Snippets of document content for a given match. + * This class represents a match objects for any Snippets that might be present in {@link + * SearchResults} from query. Using this class user can get the full text, exact matches and + * Snippets of document content for a given match. + * + *

Class Example 1: A document contains following text in property subject: * - *

Class Example 1: - * A document contains following text in property subject: *

A commonly used fake word is foo. Another nonsense word that’s used a lot is bar. * *

If the queryExpression is "foo". * *

{@link MatchInfo#getPropertyPath()} returns "subject" + * *

{@link MatchInfo#getFullText()} returns "A commonly used fake word is foo. Another * nonsense word that’s used a lot is bar." + * *

{@link MatchInfo#getExactMatchPosition()} returns [29, 32] + * *

{@link MatchInfo#getExactMatch()} returns "foo" + * *

{@link MatchInfo#getSnippetPosition()} returns [26, 33] + * *

{@link MatchInfo#getSnippet()} returns "is foo." + * *

- *

Class Example 2: - * A document contains a property name sender which contains 2 property names name and email, so - * we will have 2 property paths: {@code sender.name} and {@code sender.email}. - *

Let {@code sender.name = "Test Name Jr."} and - * {@code sender.email = "TestNameJr@gmail.com"} + * + *

Class Example 2: A document contains a property name sender which contains 2 property + * names name and email, so we will have 2 property paths: {@code sender.name} and {@code + * sender.email}. + * + *

Let {@code sender.name = "Test Name Jr."} and {@code sender.email = + * "TestNameJr@gmail.com"} * *

If the queryExpression is "Test". We will have 2 matches. * - *

Match-1 + *

Match-1 + * *

{@link MatchInfo#getPropertyPath()} returns "sender.name" + * *

{@link MatchInfo#getFullText()} returns "Test Name Jr." + * *

{@link MatchInfo#getExactMatchPosition()} returns [0, 4] + * *

{@link MatchInfo#getExactMatch()} returns "Test" + * *

{@link MatchInfo#getSnippetPosition()} returns [0, 9] + * *

{@link MatchInfo#getSnippet()} returns "Test Name" - *

Match-2 + * + *

Match-2 + * *

{@link MatchInfo#getPropertyPath()} returns "sender.email" + * *

{@link MatchInfo#getFullText()} returns "TestNameJr@gmail.com" + * *

{@link MatchInfo#getExactMatchPosition()} returns [0, 20] + * *

{@link MatchInfo#getExactMatch()} returns "TestNameJr@gmail.com" + * *

{@link MatchInfo#getSnippetPosition()} returns [0, 20] + * *

{@link MatchInfo#getSnippet()} returns "TestNameJr@gmail.com" */ public static final class MatchInfo { /** * The path of the matching snippet property. + * * @hide */ - public static final String PROPERTY_PATH_FIELD = "propertyPath"; /** * The index of matching value in its property. A property may have multiple values. This * index indicates which value is the match. + * * @hide */ - public static final String VALUES_INDEX_FIELD = "valuesIndex"; /** @hide */ - public static final String EXACT_MATCH_POSITION_LOWER_FIELD = "exactMatchPositionLower"; /** @hide */ - public static final String EXACT_MATCH_POSITION_UPPER_FIELD = "exactMatchPositionUpper"; /** @hide */ - public static final String WINDOW_POSITION_LOWER_FIELD = "windowPositionLower"; /** @hide */ - public static final String WINDOW_POSITION_UPPER_FIELD = "windowPositionUpper"; private final String mFullText; @@ -208,16 +217,18 @@ public final class SearchResult { mBundle = Preconditions.checkNotNull(bundle); Preconditions.checkNotNull(document); mPropertyPath = Preconditions.checkNotNull(bundle.getString(PROPERTY_PATH_FIELD)); - mFullText = getPropertyValues( - document, mPropertyPath, mBundle.getInt(VALUES_INDEX_FIELD)); + mFullText = + getPropertyValues(document, mPropertyPath, mBundle.getInt(VALUES_INDEX_FIELD)); } /** * Gets the property path corresponding to the given entry. + * *

Property Path: '.' - delimited sequence of property names indicating which property in * the Document these snippets correspond to. - *

Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. - * For class example 1 this returns "subject" + * + *

Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. For class + * example 1 this returns "subject" */ @NonNull public String getPropertyPath() { @@ -226,6 +237,7 @@ public final class SearchResult { /** * Gets the full text corresponding to the given entry. + * *

For class example this returns "A commonly used fake word is foo. Another nonsense * word that's used a lot is bar." */ @@ -236,20 +248,23 @@ public final class SearchResult { /** * Gets the exact {@link MatchRange} corresponding to the given entry. + * *

For class example 1 this returns [29, 32] */ @NonNull public MatchRange getExactMatchPosition() { if (mExactMatchRange == null) { - mExactMatchRange = new MatchRange( - mBundle.getInt(EXACT_MATCH_POSITION_LOWER_FIELD), - mBundle.getInt(EXACT_MATCH_POSITION_UPPER_FIELD)); + mExactMatchRange = + new MatchRange( + mBundle.getInt(EXACT_MATCH_POSITION_LOWER_FIELD), + mBundle.getInt(EXACT_MATCH_POSITION_UPPER_FIELD)); } return mExactMatchRange; } /** - * Gets the {@link MatchRange} corresponding to the given entry. + * Gets the {@link MatchRange} corresponding to the given entry. + * *

For class example 1 this returns "foo" */ @NonNull @@ -259,26 +274,31 @@ public final class SearchResult { /** * Gets the snippet {@link MatchRange} corresponding to the given entry. - *

Only populated when set maxSnippetSize > 0 in - * {@link SearchSpec.Builder#setMaxSnippetSize}. + * + *

Only populated when set maxSnippetSize > 0 in {@link + * SearchSpec.Builder#setMaxSnippetSize}. + * *

For class example 1 this returns [29, 41]. */ @NonNull public MatchRange getSnippetPosition() { if (mWindowRange == null) { - mWindowRange = new MatchRange( - mBundle.getInt(WINDOW_POSITION_LOWER_FIELD), - mBundle.getInt(WINDOW_POSITION_UPPER_FIELD)); + mWindowRange = + new MatchRange( + mBundle.getInt(WINDOW_POSITION_LOWER_FIELD), + mBundle.getInt(WINDOW_POSITION_UPPER_FIELD)); } return mWindowRange; } /** * Gets the snippet corresponding to the given entry. + * *

Snippet - Provides a subset of the content to display. Only populated when requested - * maxSnippetSize > 0. The size of this content can be changed by - * {@link SearchSpec.Builder#setMaxSnippetSize}. Windowing is centered around the middle of - * the matched token with content on either side clipped to token boundaries. + * maxSnippetSize > 0. The size of this content can be changed by {@link + * SearchSpec.Builder#setMaxSnippetSize}. Windowing is centered around the middle of the + * matched token with content on either side clipped to token boundaries. + * *

For class example 1 this returns "foo. Another" */ @NonNull @@ -309,11 +329,10 @@ public final class SearchResult { /** * Class providing the position range of matching information. * - *

All ranges are finite, and the left side of the range is always {@code <=} the right - * side of the range. - * - *

Example: MatchRange(0, 100) represent a hundred ints from 0 to 99." + *

All ranges are finite, and the left side of the range is always {@code <=} the right side + * of the range. * + *

Example: MatchRange(0, 100) represent a hundred ints from 0 to 99." */ public static final class MatchRange { private final int mEnd; @@ -321,18 +340,18 @@ public final class SearchResult { /** * Creates a new immutable range. - *

The endpoints are {@code [start, end)}; that is the range is bounded. {@code start} + * + *

The endpoints are {@code [start, end)}; that is the range is bounded. {@code start} * must be lesser or equal to {@code end}. * * @param start The start point (inclusive) * @param end The end point (exclusive) * @hide */ - public MatchRange(int start, int end) { if (start > end) { - throw new IllegalArgumentException("Start point must be less than or equal to " - + "end point"); + throw new IllegalArgumentException( + "Start point must be less than or equal to " + "end point"); } mStart = start; mEnd = end; diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java index 756d1b5d673fd..dbd09d6bb91b5 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java @@ -16,10 +16,9 @@ package android.app.appsearch; -import android.os.Bundle; - import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Bundle; import com.android.internal.util.Preconditions; @@ -29,19 +28,17 @@ import java.util.List; /** * This class represents a page of {@link SearchResult}s + * * @hide */ - public class SearchResultPage { public static final String RESULTS_FIELD = "results"; public static final String NEXT_PAGE_TOKEN_FIELD = "nextPageToken"; private final long mNextPageToken; - @Nullable - private List mResults; + @Nullable private List mResults; - @NonNull - private final Bundle mBundle; + @NonNull private final Bundle mBundle; public SearchResultPage(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java index 261f5ac5e50ab..885802dd95d44 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java @@ -16,15 +16,14 @@ package android.app.appsearch; -import android.annotation.SuppressLint; -import android.os.Bundle; - import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; - +import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.IllegalSearchSpecException; +import android.os.Bundle; + import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -53,7 +52,6 @@ public final class SearchSpec { static final String MAX_SNIPPET_FIELD = "maxSnippet"; /** @hide */ - public static final int DEFAULT_NUM_PER_PAGE = 10; // TODO(b/170371356): In framework, we may want these limits to be flag controlled. @@ -65,43 +63,45 @@ public final class SearchSpec { /** * Term Match Type for the query. + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // {@link com.google.android.icing.proto.SearchSpecProto.termMatchType} - @IntDef(value = { - TERM_MATCH_EXACT_ONLY, - TERM_MATCH_PREFIX - }) + @IntDef(value = {TERM_MATCH_EXACT_ONLY, TERM_MATCH_PREFIX}) @Retention(RetentionPolicy.SOURCE) public @interface TermMatch {} /** * Query terms will only match exact tokens in the index. + * *

Ex. A query term "foo" will only match indexed token "foo", and not "foot" or "football". */ public static final int TERM_MATCH_EXACT_ONLY = 1; /** * Query terms will match indexed tokens when the query term is a prefix of the token. + * *

Ex. A query term "foo" will match indexed tokens like "foo", "foot", and "football". */ public static final int TERM_MATCH_PREFIX = 2; /** * Ranking Strategy for query result. + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // {@link ScoringSpecProto.RankingStrategy.Code} - @IntDef(value = { - RANKING_STRATEGY_NONE, - RANKING_STRATEGY_DOCUMENT_SCORE, - RANKING_STRATEGY_CREATION_TIMESTAMP - }) + @IntDef( + value = { + RANKING_STRATEGY_NONE, + RANKING_STRATEGY_DOCUMENT_SCORE, + RANKING_STRATEGY_CREATION_TIMESTAMP + }) @Retention(RetentionPolicy.SOURCE) public @interface RankingStrategy {} - /** No Ranking, results are returned in arbitrary order.*/ + /** No Ranking, results are returned in arbitrary order. */ public static final int RANKING_STRATEGY_NONE = 0; /** Ranked by app-provided document scores. */ public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1; @@ -110,14 +110,12 @@ public final class SearchSpec { /** * Order for query result. + * * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in // {@link ScoringSpecProto.Order.Code} - @IntDef(value = { - ORDER_DESCENDING, - ORDER_ASCENDING - }) + @IntDef(value = {ORDER_DESCENDING, ORDER_ASCENDING}) @Retention(RetentionPolicy.SOURCE) public @interface Order {} @@ -129,7 +127,6 @@ public final class SearchSpec { private final Bundle mBundle; /** @hide */ - public SearchSpec(@NonNull Bundle bundle) { Preconditions.checkNotNull(bundle); mBundle = bundle; @@ -137,9 +134,9 @@ public final class SearchSpec { /** * Returns the {@link Bundle} populated by this builder. + * * @hide */ - @NonNull public Bundle getBundle() { return mBundle; @@ -224,14 +221,12 @@ public final class SearchSpec { mBundle.putInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE); } - /** - * Indicates how the query terms should match {@code TermMatchCode} in the index. - */ + /** Indicates how the query terms should match {@code TermMatchCode} in the index. */ @NonNull public Builder setTermMatch(@TermMatch int termMatchTypeCode) { Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkArgumentInRange(termMatchTypeCode, TERM_MATCH_EXACT_ONLY, - TERM_MATCH_PREFIX, "Term match type"); + Preconditions.checkArgumentInRange( + termMatchTypeCode, TERM_MATCH_EXACT_ONLY, TERM_MATCH_PREFIX, "Term match type"); mBundle.putInt(TERM_MATCH_TYPE_FIELD, termMatchTypeCode); return this; } @@ -264,8 +259,9 @@ public final class SearchSpec { } /** - * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that - * have the specified namespaces. + * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that have + * the specified namespaces. + * *

If unset, the query will search over all namespaces. */ @NonNull @@ -276,8 +272,9 @@ public final class SearchSpec { } /** - * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that - * have the specified namespaces. + * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that have + * the specified namespaces. + * *

If unset, the query will search over all namespaces. */ @NonNull @@ -302,34 +299,37 @@ public final class SearchSpec { return this; } - /** Sets ranking strategy for AppSearch results.*/ + /** Sets ranking strategy for AppSearch results. */ @NonNull public Builder setRankingStrategy(@RankingStrategy int rankingStrategy) { Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkArgumentInRange(rankingStrategy, RANKING_STRATEGY_NONE, - RANKING_STRATEGY_CREATION_TIMESTAMP, "Result ranking strategy"); + Preconditions.checkArgumentInRange( + rankingStrategy, + RANKING_STRATEGY_NONE, + RANKING_STRATEGY_CREATION_TIMESTAMP, + "Result ranking strategy"); mBundle.putInt(RANKING_STRATEGY_FIELD, rankingStrategy); return this; } /** - * Indicates the order of returned search results, the default is - * {@link #ORDER_DESCENDING}, meaning that results with higher scores come first. + * Indicates the order of returned search results, the default is {@link #ORDER_DESCENDING}, + * meaning that results with higher scores come first. * *

This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}. */ @NonNull public Builder setOrder(@Order int order) { Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkArgumentInRange(order, ORDER_DESCENDING, ORDER_ASCENDING, - "Result ranking order"); + Preconditions.checkArgumentInRange( + order, ORDER_DESCENDING, ORDER_ASCENDING, "Result ranking order"); mBundle.putInt(ORDER_FIELD, order); return this; } /** - * Only the first {@code snippetCount} documents based on the ranking strategy - * will have snippet information provided. + * Only the first {@code snippetCount} documents based on the ranking strategy will have + * snippet information provided. * *

If set to 0 (default), snippeting is disabled and {@link SearchResult#getMatches} will * return {@code null} for that result. @@ -347,28 +347,31 @@ public final class SearchSpec { * Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty} * snippets for each property of {@link GenericDocument} will contain snippet information. * - *

If set to 0, snippeting is disabled and {@link SearchResult#getMatches} - * will return {@code null} for that result. + *

If set to 0, snippeting is disabled and {@link SearchResult#getMatches} will return + * {@code null} for that result. */ @NonNull public SearchSpec.Builder setSnippetCountPerProperty( @IntRange(from = 0, to = MAX_SNIPPET_PER_PROPERTY_COUNT) int snippetCountPerProperty) { Preconditions.checkState(!mBuilt, "Builder has already been used"); - Preconditions.checkArgumentInRange(snippetCountPerProperty, - 0, MAX_SNIPPET_PER_PROPERTY_COUNT, "snippetCountPerProperty"); + Preconditions.checkArgumentInRange( + snippetCountPerProperty, + 0, + MAX_SNIPPET_PER_PROPERTY_COUNT, + "snippetCountPerProperty"); mBundle.putInt(SNIPPET_COUNT_PER_PROPERTY_FIELD, snippetCountPerProperty); return this; } /** - * Sets {@code maxSnippetSize}, the maximum snippet size. Snippet windows start at - * {@code maxSnippetSize/2} bytes before the middle of the matching token and end at - * {@code maxSnippetSize/2} bytes after the middle of the matching token. It respects - * token boundaries, therefore the returned window may be smaller than requested. + * Sets {@code maxSnippetSize}, the maximum snippet size. Snippet windows start at {@code + * maxSnippetSize/2} bytes before the middle of the matching token and end at {@code + * maxSnippetSize/2} bytes after the middle of the matching token. It respects token + * boundaries, therefore the returned window may be smaller than requested. * - *

Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will - * be returned. If matches enabled is also set to false, then snippeting is disabled. + *

Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will be + * returned. If matches enabled is also set to false, then snippeting is disabled. * *

Ex. {@code maxSnippetSize} = 16. "foo bar baz bat rat" with a query of "baz" will * return a window of "bar baz bat" which is only 11 bytes long. diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java index 09c353bef3fdc..3e472fd019398 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java @@ -16,11 +16,11 @@ package android.app.appsearch; -import android.annotation.SuppressLint; - import android.annotation.NonNull; +import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.util.ArraySet; + import com.android.internal.util.Preconditions; import java.util.ArrayList; @@ -81,8 +81,8 @@ public final class SetSchemaRequest { * Configures the {@link SetSchemaRequest} to delete any existing documents that don't * follow the new schema. * - *

By default, this is {@code false} and schema incompatibility causes the - * {@link AppSearchSession#setSchema} call to fail. + *

By default, this is {@code false} and schema incompatibility causes the {@link + * AppSearchSession#setSchema} call to fail. * * @see AppSearchSession#setSchema */ diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java index 416e90ba709e0..704f180bffc42 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java +++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java @@ -23,8 +23,9 @@ import android.app.appsearch.AppSearchResult; /** * An exception thrown by {@link android.app.appsearch.AppSearchSession} or a subcomponent. * - *

These exceptions can be converted into a failed {@link AppSearchResult} - * for propagating to the client. + *

These exceptions can be converted into a failed {@link AppSearchResult} for propagating to the + * client. + * * @hide */ public class AppSearchException extends Exception { @@ -32,6 +33,7 @@ public class AppSearchException extends Exception { /** * Initializes an {@link AppSearchException} with no message. + * * @hide */ public AppSearchException(@AppSearchResult.ResultCode int resultCode) { @@ -58,9 +60,7 @@ public class AppSearchException extends Exception { return mResultCode; } - /** - * Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult} - */ + /** Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult} */ @NonNull public AppSearchResult toAppSearchResult() { return AppSearchResult.newFailedResult(mResultCode, getMessage()); diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java index 6dd86f5e6de17..5f8da7fe067a9 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java +++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java @@ -18,14 +18,12 @@ package android.app.appsearch.exceptions; import android.annotation.NonNull; - /** * Indicates that a {@link android.app.appsearch.AppSearchSchema} has logical inconsistencies such * as unpopulated mandatory fields or illegal combinations of parameters. * * @hide */ - public class IllegalSchemaException extends IllegalArgumentException { /** * Constructs a new {@link IllegalSchemaException}. diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java index 3ef887f09eabd..0b5dc2ece6f1f 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java +++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java @@ -18,14 +18,12 @@ package android.app.appsearch.exceptions; import android.annotation.NonNull; - /** - * Indicates that a {@link android.app.appsearch.SearchResult} has logical inconsistencies such - * as unpopulated mandatory fields or illegal combinations of parameters. + * Indicates that a {@link android.app.appsearch.SearchResult} has logical inconsistencies such as + * unpopulated mandatory fields or illegal combinations of parameters. * * @hide */ - public class IllegalSearchSpecException extends IllegalArgumentException { /** * Constructs a new {@link IllegalSearchSpecException}. 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 0b3c809aa9183..247089ba258b8 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 @@ -16,13 +16,7 @@ package com.android.server.appsearch.external.localstorage; -import android.os.Bundle; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; import android.annotation.NonNull; - -import com.android.internal.annotations.VisibleForTesting; import android.annotation.WorkerThread; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; @@ -30,12 +24,17 @@ import android.app.appsearch.GenericDocument; import android.app.appsearch.SearchResultPage; import android.app.appsearch.SearchSpec; import android.app.appsearch.exceptions.AppSearchException; +import android.os.Bundle; +import android.util.ArraySet; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter; 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 android.util.ArraySet; -import com.android.internal.util.Preconditions; import com.google.android.icing.IcingSearchEngine; import com.google.android.icing.proto.DeleteResultProto; @@ -77,43 +76,40 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * *

A single instance of {@link AppSearchImpl} can support all databases. Schemas and documents * are physically saved together in {@link IcingSearchEngine}, but logically isolated: + * *

* *

Methods in this class belong to two groups, the query group and the mutate group. + * *

* *

This class is thread safe. * * @hide */ - @WorkerThread public final class AppSearchImpl { private static final String TAG = "AppSearchImpl"; - @VisibleForTesting - static final char DATABASE_DELIMITER = '/'; + @VisibleForTesting static final char DATABASE_DELIMITER = '/'; - @VisibleForTesting - static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000; - @VisibleForTesting - static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB - @VisibleForTesting - static final int CHECK_OPTIMIZE_INTERVAL = 100; + @VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000; + @VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB + @VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100; private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock(); @@ -134,8 +130,7 @@ public final class AppSearchImpl { private final Map> mNamespaceMapLocked = new HashMap<>(); /** - * The counter to check when to call {@link #checkForOptimizeLocked(boolean)}. The - * interval is + * The counter to check when to call {@link #checkForOptimizeLocked(boolean)}. The interval is * {@link #CHECK_OPTIMIZE_INTERVAL}. */ @GuardedBy("mReadWriteLock") @@ -160,8 +155,10 @@ public final class AppSearchImpl { try { // We synchronize here because we don't want to call IcingSearchEngine.initialize() more // than once. It's unnecessary and can be a costly operation. - IcingSearchEngineOptions options = IcingSearchEngineOptions.newBuilder() - .setBaseDir(icingDir.getAbsolutePath()).build(); + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder() + .setBaseDir(icingDir.getAbsolutePath()) + .build(); mIcingSearchEngineLocked = new IcingSearchEngine(options); InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize(); @@ -182,13 +179,17 @@ public final class AppSearchImpl { // Populate schema map for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) { String qualifiedSchemaType = schema.getSchemaType(); - addToMap(mSchemaMapLocked, getDatabaseName(qualifiedSchemaType), + addToMap( + mSchemaMapLocked, + getDatabaseName(qualifiedSchemaType), qualifiedSchemaType); } // Populate namespace map for (String qualifiedNamespace : getAllNamespacesResultProto.getNamespacesList()) { - addToMap(mNamespaceMapLocked, getDatabaseName(qualifiedNamespace), + addToMap( + mNamespaceMapLocked, + getDatabaseName(qualifiedNamespace), qualifiedNamespace); } @@ -223,14 +224,17 @@ public final class AppSearchImpl { * *

This method belongs to mutate group. * - * @param databaseName The name of the database where this schema lives. - * @param schemas Schemas to set for this app. + * @param databaseName The name of the database where this schema lives. + * @param schemas Schemas to set for this app. * @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents - * which do not comply with the new schema will be deleted. + * which do not comply with the new schema will be deleted. * @throws AppSearchException on IcingSearchEngine error. */ - public void setSchema(@NonNull String databaseName, @NonNull Set schemas, - boolean forceOverride) throws AppSearchException { + public void setSchema( + @NonNull String databaseName, + @NonNull Set schemas, + boolean forceOverride) + throws AppSearchException { mReadWriteLock.writeLock().lock(); try { SchemaProto.Builder existingSchemaBuilder = getSchemaProtoLocked().toBuilder(); @@ -243,14 +247,13 @@ public final class AppSearchImpl { // Combine the existing schema (which may have types from other databases) with this // database's new schema. Modifies the existingSchemaBuilder. - RewrittenSchemaResults rewrittenSchemaResults = rewriteSchema(databaseName, - existingSchemaBuilder, - newSchemaBuilder.build()); + RewrittenSchemaResults rewrittenSchemaResults = + rewriteSchema(databaseName, existingSchemaBuilder, newSchemaBuilder.build()); // Apply schema SetSchemaResultProto setSchemaResultProto = - mIcingSearchEngineLocked.setSchema(existingSchemaBuilder.build(), - forceOverride); + mIcingSearchEngineLocked.setSchema( + existingSchemaBuilder.build(), forceOverride); // Determine whether it succeeded. try { @@ -259,11 +262,12 @@ public final class AppSearchImpl { // Improve the error message by merging in information about incompatible types. if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0 || setSchemaResultProto.getIncompatibleSchemaTypesCount() > 0) { - String newMessage = e.getMessage() - + "\n Deleted types: " - + setSchemaResultProto.getDeletedSchemaTypesList() - + "\n Incompatible types: " - + setSchemaResultProto.getIncompatibleSchemaTypesList(); + String newMessage = + e.getMessage() + + "\n Deleted types: " + + setSchemaResultProto.getDeletedSchemaTypesList() + + "\n Incompatible types: " + + setSchemaResultProto.getIncompatibleSchemaTypesList(); throw new AppSearchException(e.getResultCode(), newMessage, e.getCause()); } else { throw e; @@ -272,17 +276,17 @@ public final class AppSearchImpl { // Update derived data structures. mSchemaMapLocked.put(databaseName, rewrittenSchemaResults.mRewrittenQualifiedTypes); - mVisibilityStoreLocked.updateSchemas(databaseName, - rewrittenSchemaResults.mDeletedQualifiedTypes); + mVisibilityStoreLocked.updateSchemas( + databaseName, rewrittenSchemaResults.mDeletedQualifiedTypes); // Determine whether to schedule an immediate optimize. if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0 || (setSchemaResultProto.getIncompatibleSchemaTypesCount() > 0 - && forceOverride)) { + && forceOverride)) { // Any existing schemas which is not in 'schemas' will be deleted, and all // documents of these types were also deleted. And so well if we force override // incompatible schemas. - checkForOptimizeLocked(/* force= */true); + checkForOptimizeLocked(/* force= */ true); } } finally { mReadWriteLock.writeLock().unlock(); @@ -294,14 +298,12 @@ public final class AppSearchImpl { * *

This method belongs to the mutate group * - * @param databaseName The name of the database where the - * visibility settings will apply. - * @param schemasHiddenFromPlatformSurfaces Schemas that should be hidden from platform - * surfaces + * @param databaseName The name of the database where the visibility settings will apply. + * @param schemasHiddenFromPlatformSurfaces Schemas that should be hidden from platform surfaces * @throws AppSearchException on IcingSearchEngine error */ - public void setVisibility(@NonNull String databaseName, - @NonNull Set schemasHiddenFromPlatformSurfaces) + public void setVisibility( + @NonNull String databaseName, @NonNull Set schemasHiddenFromPlatformSurfaces) throws AppSearchException { mReadWriteLock.writeLock().lock(); try { @@ -311,14 +313,16 @@ public final class AppSearchImpl { for (String schema : schemasHiddenFromPlatformSurfaces) { Set existingSchemas = mSchemaMapLocked.get(databaseName); if (existingSchemas == null || !existingSchemas.contains(databasePrefix + schema)) { - throw new AppSearchException(AppSearchResult.RESULT_NOT_FOUND, - "Unknown schema(s): " + schemasHiddenFromPlatformSurfaces + throw new AppSearchException( + AppSearchResult.RESULT_NOT_FOUND, + "Unknown schema(s): " + + schemasHiddenFromPlatformSurfaces + " provided during setVisibility."); } qualifiedSchemasHiddenFromPlatformSurface.add(databasePrefix + schema); } - mVisibilityStoreLocked.setVisibility(databaseName, - qualifiedSchemasHiddenFromPlatformSurface); + mVisibilityStoreLocked.setVisibility( + databaseName, qualifiedSchemasHiddenFromPlatformSurface); } finally { mReadWriteLock.writeLock().lock(); } @@ -330,13 +334,13 @@ public final class AppSearchImpl { *

This method belongs to mutate group. * * @param databaseName The databaseName this document resides in. - * @param document The document to index. + * @param document The document to index. * @throws AppSearchException on IcingSearchEngine error. */ public void putDocument(@NonNull String databaseName, @NonNull GenericDocument document) throws AppSearchException { - DocumentProto.Builder documentBuilder = GenericDocumentToProtoConverter.convert( - document).toBuilder(); + DocumentProto.Builder documentBuilder = + GenericDocumentToProtoConverter.convert(document).toBuilder(); addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName)); PutResultProto putResultProto; @@ -346,7 +350,7 @@ public final class AppSearchImpl { addToMap(mNamespaceMapLocked, databaseName, documentBuilder.getNamespace()); // The existing documents with same URI will be deleted, so there maybe some resources // could be released after optimize(). - checkForOptimizeLocked(/* force= */false); + checkForOptimizeLocked(/* force= */ false); } finally { mReadWriteLock.writeLock().unlock(); } @@ -359,19 +363,20 @@ public final class AppSearchImpl { *

This method belongs to query group. * * @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 namespace The namespace this document resides in. + * @param uri The URI of the document to get. * @return The Document contents * @throws AppSearchException on IcingSearchEngine error. */ @NonNull - public GenericDocument getDocument(@NonNull String databaseName, @NonNull String namespace, - @NonNull String uri) throws AppSearchException { + public GenericDocument getDocument( + @NonNull String databaseName, @NonNull String namespace, @NonNull String uri) + throws AppSearchException { GetResultProto getResultProto; mReadWriteLock.readLock().lock(); try { - getResultProto = mIcingSearchEngineLocked.get( - getDatabasePrefix(databaseName) + namespace, uri); + getResultProto = + mIcingSearchEngineLocked.get(getDatabasePrefix(databaseName) + namespace, uri); } finally { mReadWriteLock.readLock().unlock(); } @@ -387,22 +392,22 @@ public final class AppSearchImpl { * *

This method belongs to query group. * - * @param databaseName The databaseName this query for. + * @param databaseName The databaseName this query for. * @param queryExpression Query String to search. - * @param searchSpec Spec for setting filters, raw query etc. - * @return The results of performing this search. It may contain an empty list of results if - * no documents matched the query. + * @param searchSpec Spec for setting filters, raw query etc. + * @return The results of performing this search. It may contain an empty list of results if no + * documents matched the query. * @throws AppSearchException on IcingSearchEngine error. */ @NonNull public SearchResultPage query( @NonNull String databaseName, @NonNull String queryExpression, - @NonNull SearchSpec searchSpec) throws AppSearchException { + @NonNull SearchSpec searchSpec) + throws AppSearchException { mReadWriteLock.readLock().lock(); try { - return doQueryLocked(Collections.singleton(databaseName), queryExpression, - searchSpec); + return doQueryLocked(Collections.singleton(databaseName), queryExpression, searchSpec); } finally { mReadWriteLock.readLock().unlock(); } @@ -415,15 +420,15 @@ public final class AppSearchImpl { *

This method belongs to query group. * * @param queryExpression Query String to search. - * @param searchSpec Spec for setting filters, raw query etc. - * @return The results of performing this search. It may contain an empty list of results if - * no documents matched the query. + * @param searchSpec Spec for setting filters, raw query etc. + * @return The results of performing this search. It may contain an empty list of results if no + * documents matched the query. * @throws AppSearchException on IcingSearchEngine error. */ @NonNull public SearchResultPage globalQuery( - @NonNull String queryExpression, - @NonNull SearchSpec searchSpec) throws AppSearchException { + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) + throws AppSearchException { // TODO(b/169883602): Check if the platform is querying us at a higher level. At this // point, we should add all platform-surfaceable schemas assuming the querier has been // verified. @@ -439,13 +444,13 @@ public final class AppSearchImpl { @GuardedBy("mReadWriteLock") private SearchResultPage doQueryLocked( - @NonNull Set databases, @NonNull String queryExpression, + @NonNull Set databases, + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) throws AppSearchException { - SearchSpecProto searchSpecProto = - SearchSpecToProtoConverter.toSearchSpecProto(searchSpec); - SearchSpecProto.Builder searchSpecBuilder = searchSpecProto.toBuilder() - .setQuery(queryExpression); + SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec); + SearchSpecProto.Builder searchSpecBuilder = + searchSpecProto.toBuilder().setQuery(queryExpression); ResultSpecProto resultSpec = SearchSpecToProtoConverter.toResultSpecProto(searchSpec); ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec); @@ -459,8 +464,8 @@ public final class AppSearchImpl { if (!rewriteSearchSpecForDatabasesLocked(searchSpecBuilder, databases)) { return new SearchResultPage(Bundle.EMPTY); } - searchResultProto = mIcingSearchEngineLocked.search( - searchSpecBuilder.build(), scoringSpec, resultSpec); + searchResultProto = + mIcingSearchEngineLocked.search(searchSpecBuilder.build(), scoringSpec, resultSpec); checkSuccess(searchResultProto.getStatus()); return rewriteSearchResultProto(searchResultProto); @@ -477,12 +482,11 @@ public final class AppSearchImpl { * @throws AppSearchException on IcingSearchEngine error. */ @NonNull - public SearchResultPage getNextPage(long nextPageToken) - throws AppSearchException { + public SearchResultPage getNextPage(long nextPageToken) throws AppSearchException { mReadWriteLock.readLock().lock(); try { - SearchResultProto searchResultProto = mIcingSearchEngineLocked.getNextPage( - nextPageToken); + SearchResultProto searchResultProto = + mIcingSearchEngineLocked.getNextPage(nextPageToken); checkSuccess(searchResultProto.getStatus()); return rewriteSearchResultProto(searchResultProto); } finally { @@ -496,7 +500,7 @@ public final class AppSearchImpl { *

This method belongs to query group. * * @param nextPageToken The token of pre-loaded results of previously executed query to be - * Invalidated. + * Invalidated. */ public void invalidateNextPageToken(long nextPageToken) { mReadWriteLock.readLock().lock(); @@ -513,18 +517,18 @@ public final class AppSearchImpl { *

This method belongs to mutate group. * * @param databaseName The databaseName the document is in. - * @param namespace Namespace of the document to remove. - * @param uri URI of the document to remove. + * @param namespace Namespace of the document to remove. + * @param uri URI of the document to remove. * @throws AppSearchException on IcingSearchEngine error. */ - public void remove(@NonNull String databaseName, @NonNull String namespace, - @NonNull String uri) throws AppSearchException { + public void remove(@NonNull String databaseName, @NonNull String namespace, @NonNull String uri) + throws AppSearchException { String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace; DeleteResultProto deleteResultProto; mReadWriteLock.writeLock().lock(); try { deleteResultProto = mIcingSearchEngineLocked.delete(qualifiedNamespace, uri); - checkForOptimizeLocked(/* force= */false); + checkForOptimizeLocked(/* force= */ false); } finally { mReadWriteLock.writeLock().unlock(); } @@ -536,38 +540,38 @@ public final class AppSearchImpl { * *

This method belongs to mutate group. * - * @param databaseName The databaseName the document is in. + * @param databaseName The databaseName the document is in. * @param queryExpression Query String to search. - * @param searchSpec Defines what and how to remove + * @param searchSpec Defines what and how to remove * @throws AppSearchException on IcingSearchEngine error. */ - public void removeByQuery(@NonNull String databaseName, @NonNull String queryExpression, + public void removeByQuery( + @NonNull String databaseName, + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) throws AppSearchException { - SearchSpecProto searchSpecProto = - SearchSpecToProtoConverter.toSearchSpecProto(searchSpec); - SearchSpecProto.Builder searchSpecBuilder = searchSpecProto.toBuilder() - .setQuery(queryExpression); + SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec); + SearchSpecProto.Builder searchSpecBuilder = + searchSpecProto.toBuilder().setQuery(queryExpression); DeleteResultProto deleteResultProto; mReadWriteLock.writeLock().lock(); try { // Only rewrite SearchSpec for non empty database. // rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we // should skip sending request to Icing and return in here. - if (!rewriteSearchSpecForDatabasesLocked(searchSpecBuilder, - Collections.singleton(databaseName))) { + if (!rewriteSearchSpecForDatabasesLocked( + searchSpecBuilder, Collections.singleton(databaseName))) { return; } - deleteResultProto = mIcingSearchEngineLocked.deleteByQuery( - searchSpecBuilder.build()); - checkForOptimizeLocked(/* force= */true); + deleteResultProto = mIcingSearchEngineLocked.deleteByQuery(searchSpecBuilder.build()); + checkForOptimizeLocked(/* force= */ true); } finally { mReadWriteLock.writeLock().unlock(); } // It seems that the caller wants to get success if the data matching the query is not in // the DB because it was not there or was successfully deleted. - checkCodeOneOf(deleteResultProto.getStatus(), - StatusProto.Code.OK, StatusProto.Code.NOT_FOUND); + checkCodeOneOf( + deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND); } /** @@ -610,18 +614,20 @@ public final class AppSearchImpl { * Rewrites all types mentioned in the given {@code newSchema} to prepend {@code prefix}. * Rewritten types will be added to the {@code existingSchema}. * - * @param databaseName The name of the database where this schema lives. + * @param databaseName The name of the database where this schema lives. * @param existingSchema A schema that may contain existing types from across all database - * instances. Will be mutated to contain the properly rewritten schema - * types from {@code newSchema}. - * @param newSchema Schema with types to add to the {@code existingSchema}. + * instances. Will be mutated to contain the properly rewritten schema types from {@code + * newSchema}. + * @param newSchema Schema with types to add to the {@code existingSchema}. * @return a RewrittenSchemaResults contains all qualified schema type names in the given - * database as well as a set of schema types that were deleted from the database. + * database as well as a set of schema types that were deleted from the database. */ @VisibleForTesting - static RewrittenSchemaResults rewriteSchema(@NonNull String databaseName, + static RewrittenSchemaResults rewriteSchema( + @NonNull String databaseName, @NonNull SchemaProto.Builder existingSchema, - @NonNull SchemaProto newSchema) throws AppSearchException { + @NonNull SchemaProto newSchema) + throws AppSearchException { String prefix = getDatabasePrefix(databaseName); HashMap newTypesToProto = new HashMap<>(); // Rewrite the schema type to include the typePrefix. @@ -640,8 +646,7 @@ public final class AppSearchImpl { PropertyConfigProto.Builder propertyConfigBuilder = typeConfigBuilder.getProperties(propertyIdx).toBuilder(); if (!propertyConfigBuilder.getSchemaType().isEmpty()) { - String newPropertySchemaType = - prefix + propertyConfigBuilder.getSchemaType(); + String newPropertySchemaType = prefix + propertyConfigBuilder.getSchemaType(); propertyConfigBuilder.setSchemaType(newPropertySchemaType); typeConfigBuilder.setProperties(propertyIdx, propertyConfigBuilder); } @@ -678,16 +683,15 @@ public final class AppSearchImpl { } /** - * Prepends {@code prefix} to all types and namespaces mentioned anywhere in - * {@code documentBuilder}. + * Prepends {@code prefix} to all types and namespaces mentioned anywhere in {@code + * documentBuilder}. * * @param documentBuilder The document to mutate - * @param prefix The prefix to add + * @param prefix The prefix to add */ @VisibleForTesting static void addPrefixToDocument( - @NonNull DocumentProto.Builder documentBuilder, - @NonNull String prefix) { + @NonNull DocumentProto.Builder documentBuilder, @NonNull String prefix) { // Rewrite the type name to include/remove the prefix. String newSchema = prefix + documentBuilder.getSchema(); documentBuilder.setSchema(newSchema); @@ -715,8 +719,8 @@ public final class AppSearchImpl { } /** - * Removes any database names from types and namespaces mentioned anywhere in - * {@code documentBuilder}. + * Removes any database names from types and namespaces mentioned anywhere in {@code + * documentBuilder}. * * @param documentBuilder The document to mutate */ @@ -749,8 +753,9 @@ public final class AppSearchImpl { /** * Rewrites the schemaTypeFilters and namespacesFilters that exist in {@code databaseNames}. * - *

If the searchSpec has empty filter lists, all existing databases from - * {@code databaseNames} will be added. + *

If the searchSpec has empty filter lists, all existing databases from {@code + * databaseNames} will be added. + * *

This method should be only called in query methods and get the READ lock to keep thread * safety. * @@ -857,7 +862,8 @@ public final class AppSearchImpl { // Add 1 to include the char size of the DATABASE_DELIMITER return prefixedString.substring(delimiterIndex + 1); } - throw new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR, + throw new AppSearchException( + AppSearchResult.RESULT_UNKNOWN_ERROR, "The prefixed value doesn't contains a valid database name."); } @@ -865,14 +871,15 @@ public final class AppSearchImpl { private static String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException { int delimiterIndex = prefixedValue.indexOf(DATABASE_DELIMITER); if (delimiterIndex == -1) { - throw new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR, + throw new AppSearchException( + AppSearchResult.RESULT_UNKNOWN_ERROR, "The databaseName prefixed value doesn't contains a valid database name."); } return prefixedValue.substring(0, delimiterIndex); } - private static void addToMap(Map> map, String databaseName, - String prefixedValue) { + private static void addToMap( + Map> map, String databaseName, String prefixedValue) { Set values = map.get(databaseName); if (values == null) { values = new ArraySet<>(); @@ -891,8 +898,8 @@ public final class AppSearchImpl { } /** - * Checks the given status code is one of the provided codes, and throws an - * {@link AppSearchException} if it is not. + * Checks the given status code is one of the provided codes, and throws an {@link + * AppSearchException} if it is not. */ private static void checkCodeOneOf(StatusProto statusProto, StatusProto.Code... codes) throws AppSearchException { @@ -918,10 +925,12 @@ public final class AppSearchImpl { * *

This method should be only called in mutate methods and get the WRITE lock to keep thread * safety. - *

{@link IcingSearchEngine#optimize()} should be called only if - * {@link GetOptimizeInfoResultProto} shows there is enough resources could be released. - *

{@link IcingSearchEngine#getOptimizeInfo()} should be called once per - * {@link #CHECK_OPTIMIZE_INTERVAL} of remove executions. + * + *

{@link IcingSearchEngine#optimize()} should be called only if {@link + * GetOptimizeInfoResultProto} shows there is enough resources could be released. + * + *

{@link IcingSearchEngine#getOptimizeInfo()} should be called once per {@link + * #CHECK_OPTIMIZE_INTERVAL} of remove executions. * * @param force whether we should directly call {@link IcingSearchEngine#getOptimizeInfo()}. */ @@ -934,8 +943,7 @@ public final class AppSearchImpl { checkSuccess(optimizeInfo.getStatus()); // Second threshold, decide when to call optimize(). if (optimizeInfo.getOptimizableDocs() >= OPTIMIZE_THRESHOLD_DOC_COUNT - || optimizeInfo.getEstimatedOptimizableBytes() - >= OPTIMIZE_THRESHOLD_BYTES) { + || optimizeInfo.getEstimatedOptimizableBytes() >= OPTIMIZE_THRESHOLD_BYTES) { // TODO(b/155939114): call optimize in the same thread will slow down api calls // significantly. Move this call to background. OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize(); @@ -977,34 +985,35 @@ public final class AppSearchImpl { } /** - * Converts an erroneous status code to an AppSearchException. Callers should ensure that - * the status code is not OK or WARNING_DATA_LOSS. + * Converts an erroneous status code to an AppSearchException. Callers should ensure that the + * status code is not OK or WARNING_DATA_LOSS. * * @param statusProto StatusProto with error code and message to translate into - * AppSearchException. + * AppSearchException. * @return AppSearchException with the parallel error code. */ private static AppSearchException statusProtoToAppSearchException(StatusProto statusProto) { switch (statusProto.getCode()) { case INVALID_ARGUMENT: - return new AppSearchException(AppSearchResult.RESULT_INVALID_ARGUMENT, - statusProto.getMessage()); + return new AppSearchException( + AppSearchResult.RESULT_INVALID_ARGUMENT, statusProto.getMessage()); case NOT_FOUND: - return new AppSearchException(AppSearchResult.RESULT_NOT_FOUND, - statusProto.getMessage()); + return new AppSearchException( + AppSearchResult.RESULT_NOT_FOUND, statusProto.getMessage()); case FAILED_PRECONDITION: // Fallthrough case ABORTED: // Fallthrough case INTERNAL: - return new AppSearchException(AppSearchResult.RESULT_INTERNAL_ERROR, - statusProto.getMessage()); + return new AppSearchException( + AppSearchResult.RESULT_INTERNAL_ERROR, statusProto.getMessage()); case OUT_OF_SPACE: - return new AppSearchException(AppSearchResult.RESULT_OUT_OF_SPACE, - statusProto.getMessage()); + return new AppSearchException( + AppSearchResult.RESULT_OUT_OF_SPACE, statusProto.getMessage()); default: // Some unknown/unsupported error - return new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR, + return new AppSearchException( + AppSearchResult.RESULT_UNKNOWN_ERROR, "Unknown IcingSearchEngine status code: " + statusProto.getCode()); } } 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 07c64da10bc80..47228221a1f50 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 @@ -17,13 +17,14 @@ package com.android.server.appsearch.external.localstorage; import android.annotation.NonNull; -import com.android.internal.annotations.VisibleForTesting; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.GenericDocument; import android.app.appsearch.exceptions.AppSearchException; import android.util.ArrayMap; import android.util.ArraySet; + +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.util.Arrays; @@ -37,11 +38,11 @@ import java.util.Set; * *

The VisibilityStore creates a document for each database. This document holds the visibility * settings that apply to that database. The VisibilityStore also creates a schema for these - * documents and has its own database so that its data doesn't interfere with any clients' data. - * It persists the document and schema through AppSearchImpl. + * documents and has its own database so that its data doesn't interfere with any clients' data. It + * persists the document and schema through AppSearchImpl. * - *

These visibility settings are used to ensure AppSearch queries respect the clients' - * settings on who their data is visible to. + *

These visibility settings are used to ensure AppSearch queries respect the clients' settings + * on who their data is visible to. * *

This class doesn't handle any locking itself. Its callers should handle the locking at a * higher level. @@ -51,16 +52,13 @@ import java.util.Set; */ class VisibilityStore { // Schema type for documents that hold AppSearch's metadata, e.g. visibility settings - @VisibleForTesting - static final String SCHEMA_TYPE = "Visibility"; + @VisibleForTesting static final String SCHEMA_TYPE = "Visibility"; // Property that holds the list of platform-hidden schemas, as part of the visibility // settings. - @VisibleForTesting - static final String PLATFORM_HIDDEN_PROPERTY = "platformHidden"; + @VisibleForTesting static final String PLATFORM_HIDDEN_PROPERTY = "platformHidden"; // Database name to prefix all visibility schemas and documents with. Special-cased to // minimize the chance of collision with a client-supplied database. - @VisibleForTesting - static final String DATABASE_NAME = "$$__AppSearch__Database"; + @VisibleForTesting static final String DATABASE_NAME = "$$__AppSearch__Database"; // Namespace of documents that contain visibility settings private static final String NAMESPACE = "namespace"; private final AppSearchImpl mAppSearchImpl; @@ -92,15 +90,21 @@ class VisibilityStore { public void initialize() throws AppSearchException { if (!mAppSearchImpl.hasSchemaTypeLocked(DATABASE_NAME, SCHEMA_TYPE)) { // Schema type doesn't exist yet. Add it. - mAppSearchImpl.setSchema(DATABASE_NAME, - Collections.singleton(new AppSearchSchema.Builder(SCHEMA_TYPE) - .addProperty(new AppSearchSchema.PropertyConfig.Builder( - PLATFORM_HIDDEN_PROPERTY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) - .setCardinality( - AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .build()) - .build()), + mAppSearchImpl.setSchema( + DATABASE_NAME, + Collections.singleton( + new AppSearchSchema.Builder(SCHEMA_TYPE) + .addProperty( + new AppSearchSchema.PropertyConfig.Builder( + PLATFORM_HIDDEN_PROPERTY) + .setDataType( + AppSearchSchema.PropertyConfig + .DATA_TYPE_STRING) + .setCardinality( + AppSearchSchema.PropertyConfig + .CARDINALITY_REPEATED) + .build()) + .build()), /*forceOverride=*/ false); } @@ -113,8 +117,8 @@ class VisibilityStore { try { // Note: We use the other clients' database names as uris - GenericDocument document = mAppSearchImpl.getDocument( - DATABASE_NAME, NAMESPACE, /*uri=*/ database); + GenericDocument document = + mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ database); String[] schemas = document.getPropertyStringArray(PLATFORM_HIDDEN_PROPERTY); mPlatformHiddenMap.put(database, new ArraySet<>(Arrays.asList(schemas))); @@ -136,22 +140,24 @@ class VisibilityStore { * * @param schemasToRemove Database-prefixed schemas that should be removed */ - public void updateSchemas(@NonNull String databaseName, - @NonNull Set schemasToRemove) throws AppSearchException { + public void updateSchemas(@NonNull String databaseName, @NonNull Set schemasToRemove) + throws AppSearchException { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(schemasToRemove); GenericDocument visibilityDocument; try { - visibilityDocument = mAppSearchImpl.getDocument( - DATABASE_NAME, NAMESPACE, /*uri=*/ databaseName); + visibilityDocument = + mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ databaseName); } catch (AppSearchException e) { if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) { // This might be the first time we're seeing visibility changes for a database. // Create a new visibility document. - mAppSearchImpl.putDocument(DATABASE_NAME, new GenericDocument.Builder( - /*uri=*/ databaseName, SCHEMA_TYPE) - .setNamespace(NAMESPACE).build()); + mAppSearchImpl.putDocument( + DATABASE_NAME, + new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE) + .setNamespace(NAMESPACE) + .build()); // Since we know there was nothing that existed before, we don't need to remove // anything either. Return early. @@ -178,12 +184,12 @@ class VisibilityStore { // Update our persisted document // TODO(b/171882200): Switch to a .toBuilder API when it's available. - GenericDocument.Builder newVisibilityDocument = new GenericDocument.Builder( - /*uri=*/ databaseName, SCHEMA_TYPE) - .setNamespace(NAMESPACE); + GenericDocument.Builder newVisibilityDocument = + new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE) + .setNamespace(NAMESPACE); if (!remainingSchemas.isEmpty()) { - newVisibilityDocument.setPropertyString(PLATFORM_HIDDEN_PROPERTY, - remainingSchemas.toArray(new String[0])); + newVisibilityDocument.setPropertyString( + PLATFORM_HIDDEN_PROPERTY, remainingSchemas.toArray(new String[0])); } mAppSearchImpl.putDocument(DATABASE_NAME, newVisibilityDocument.build()); @@ -195,23 +201,24 @@ class VisibilityStore { * Sets visibility settings for {@code databaseName}. Any previous visibility settings will be * overwritten. * - * @param databaseName Database name that owns the {@code platformHiddenSchemas}. - * @param platformHiddenSchemas Set of database-qualified schemas that should be hidden from - * the platform. + * @param databaseName Database name that owns the {@code platformHiddenSchemas}. + * @param platformHiddenSchemas Set of database-qualified schemas that should be hidden from the + * platform. * @throws AppSearchException on AppSearchImpl error. */ - public void setVisibility(@NonNull String databaseName, - @NonNull Set platformHiddenSchemas) throws AppSearchException { + public void setVisibility( + @NonNull String databaseName, @NonNull Set platformHiddenSchemas) + throws AppSearchException { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(platformHiddenSchemas); // Persist the document - GenericDocument.Builder visibilityDocument = new GenericDocument.Builder( - /*uri=*/ databaseName, SCHEMA_TYPE) - .setNamespace(NAMESPACE); + GenericDocument.Builder visibilityDocument = + new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE) + .setNamespace(NAMESPACE); if (!platformHiddenSchemas.isEmpty()) { - visibilityDocument.setPropertyString(PLATFORM_HIDDEN_PROPERTY, - platformHiddenSchemas.toArray(new String[0])); + visibilityDocument.setPropertyString( + PLATFORM_HIDDEN_PROPERTY, platformHiddenSchemas.toArray(new String[0])); } mAppSearchImpl.putDocument(DATABASE_NAME, visibilityDocument.build()); @@ -225,7 +232,7 @@ class VisibilityStore { * * @param databaseName Database name to retrieve schemas for * @return Set of database-qualified schemas that are hidden from the platform. Empty set if - * none exist. + * none exist. */ @NonNull public Set getPlatformHiddenSchemas(@NonNull String databaseName) { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java index 60684f09a2022..8f4e7ff69d7c6 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java @@ -17,8 +17,8 @@ package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; - import android.app.appsearch.GenericDocument; + import com.android.internal.util.Preconditions; import com.google.android.icing.proto.DocumentProto; @@ -30,9 +30,9 @@ import java.util.Collections; /** * Translates a {@link GenericDocument} into a {@link DocumentProto}. + * * @hide */ - public final class GenericDocumentToProtoConverter { private GenericDocumentToProtoConverter() {} @@ -42,7 +42,8 @@ public final class GenericDocumentToProtoConverter { public static DocumentProto convert(@NonNull GenericDocument document) { Preconditions.checkNotNull(document); DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder(); - mProtoBuilder.setUri(document.getUri()) + mProtoBuilder + .setUri(document.getUri()) .setSchema(document.getSchemaType()) .setNamespace(document.getNamespace()) .setScore(document.getScore()) 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 1ecf2ca7554e5..642c2a7139304 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 @@ -17,8 +17,8 @@ package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; - import android.app.appsearch.AppSearchSchema; + import com.android.internal.util.Preconditions; import com.google.android.icing.proto.PropertyConfigProto; @@ -30,15 +30,15 @@ import java.util.List; /** * Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}. + * * @hide */ - public final class SchemaToProtoConverter { private SchemaToProtoConverter() {} /** - * Converts an {@link android.app.appsearch.AppSearchSchema} into a - * {@link SchemaTypeConfigProto}. + * Converts an {@link android.app.appsearch.AppSearchSchema} into a {@link + * SchemaTypeConfigProto}. */ @NonNull public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) { @@ -57,8 +57,8 @@ public final class SchemaToProtoConverter { private static PropertyConfigProto convertProperty( @NonNull AppSearchSchema.PropertyConfig property) { Preconditions.checkNotNull(property); - PropertyConfigProto.Builder propertyConfigProto = PropertyConfigProto.newBuilder() - .setPropertyName(property.getName()); + PropertyConfigProto.Builder propertyConfigProto = + PropertyConfigProto.newBuilder().setPropertyName(property.getName()); StringIndexingConfig.Builder indexingConfig = StringIndexingConfig.newBuilder(); // Set dataType @@ -104,8 +104,8 @@ public final class SchemaToProtoConverter { indexingConfig.setTermMatchType(termMatchTypeProto); // Set tokenizerType - @AppSearchSchema.PropertyConfig.TokenizerType int tokenizerType = - property.getTokenizerType(); + @AppSearchSchema.PropertyConfig.TokenizerType + int tokenizerType = property.getTokenizerType(); StringIndexingConfig.TokenizerType.Code tokenizerTypeProto = StringIndexingConfig.TokenizerType.Code.forNumber(tokenizerType); if (tokenizerTypeProto == null) { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java index 5b5258db3ba8a..b91a393cab4a3 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java @@ -16,13 +16,11 @@ package com.android.server.appsearch.external.localstorage.converter; -import android.os.Bundle; - import android.annotation.NonNull; - import android.app.appsearch.GenericDocument; import android.app.appsearch.SearchResult; import android.app.appsearch.SearchResultPage; +import android.os.Bundle; import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SearchResultProtoOrBuilder; @@ -36,7 +34,6 @@ import java.util.ArrayList; * * @hide */ - public class SearchResultToProtoConverter { private SearchResultToProtoConverter() {} @@ -67,8 +64,9 @@ public class SearchResultToProtoConverter { for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) { SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i); for (int j = 0; j < entry.getSnippetMatchesCount(); j++) { - Bundle matchInfoBundle = convertToMatchInfoBundle( - entry.getSnippetMatches(j), entry.getPropertyName()); + Bundle matchInfoBundle = + convertToMatchInfoBundle( + entry.getSnippetMatches(j), entry.getPropertyName()); matchList.add(matchInfoBundle); } } 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 37f64578151f6..814ee4f7636aa 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 @@ -17,8 +17,8 @@ package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; - import android.app.appsearch.SearchSpec; + import com.android.internal.util.Preconditions; import com.google.android.icing.proto.ResultSpecProto; @@ -28,9 +28,9 @@ import com.google.android.icing.proto.TermMatchType; /** * Translates a {@link SearchSpec} into icing search protos. + * * @hide */ - public final class SearchSpecToProtoConverter { private SearchSpecToProtoConverter() {} @@ -38,9 +38,10 @@ public final class SearchSpecToProtoConverter { @NonNull public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) { Preconditions.checkNotNull(spec); - SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder() - .addAllSchemaTypeFilters(spec.getSchemaTypes()) - .addAllNamespaceFilters(spec.getNamespaces()); + SearchSpecProto.Builder protoBuilder = + SearchSpecProto.newBuilder() + .addAllSchemaTypeFilters(spec.getSchemaTypes()) + .addAllNamespaceFilters(spec.getNamespaces()); @SearchSpec.TermMatch int termMatchCode = spec.getTermMatch(); TermMatchType.Code termMatchCodeProto = TermMatchType.Code.forNumber(termMatchCode); @@ -84,8 +85,8 @@ public final class SearchSpecToProtoConverter { ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto = ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode); if (rankingStrategyCodeProto == null) { - throw new IllegalArgumentException("Invalid result ranking strategy: " - + rankingStrategyCode); + throw new IllegalArgumentException( + "Invalid result ranking strategy: " + rankingStrategyCode); } protoBuilder.setRankBy(rankingStrategyCodeProto); diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java index 2f2bef8bc5cc3..119b70ab04398 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java @@ -24,16 +24,18 @@ public class AppSearchEmailTest { @Test public void testBuildEmailAndGetValue() { - AppSearchEmail email = new AppSearchEmail.Builder("uri") - .setFrom("FakeFromAddress") - .setCc("CC1", "CC2") - // Score and Property are mixed into the middle to make sure DocumentBuilder's - // methods can be interleaved with EmailBuilder's methods. - .setScore(1) - .setPropertyString("propertyKey", "propertyValue1", "propertyValue2") - .setSubject("subject") - .setBody("EmailBody") - .build(); + AppSearchEmail email = + new AppSearchEmail.Builder("uri") + .setFrom("FakeFromAddress") + .setCc("CC1", "CC2") + // Score and Property are mixed into the middle to make sure + // DocumentBuilder's + // methods can be interleaved with EmailBuilder's methods. + .setScore(1) + .setPropertyString("propertyKey", "propertyValue1", "propertyValue2") + .setSubject("subject") + .setBody("EmailBody") + .build(); assertThat(email.getUri()).isEqualTo("uri"); assertThat(email.getFrom()).isEqualTo("FakeFromAddress"); @@ -42,8 +44,9 @@ public class AppSearchEmailTest { assertThat(email.getBcc()).isNull(); assertThat(email.getScore()).isEqualTo(1); assertThat(email.getPropertyString("propertyKey")).isEqualTo("propertyValue1"); - assertThat(email.getPropertyStringArray("propertyKey")).asList().containsExactly( - "propertyValue1", "propertyValue2"); + assertThat(email.getPropertyStringArray("propertyKey")) + .asList() + .containsExactly("propertyValue1", "propertyValue2"); assertThat(email.getSubject()).isEqualTo("subject"); assertThat(email.getBody()).isEqualTo("EmailBody"); } diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java index 4bfb4a1fb3af4..9fd480d9e22ae 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java @@ -25,25 +25,26 @@ import org.junit.Test; public class SearchSpecTest { @Test public void testGetBundle() { - SearchSpec searchSpec = new SearchSpec.Builder() - .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) - .addNamespace("namespace1", "namespace2") - .addSchemaType("schemaTypes1", "schemaTypes2") - .setSnippetCount(5) - .setSnippetCountPerProperty(10) - .setMaxSnippetSize(15) - .setResultCountPerPage(42) - .setOrder(SearchSpec.ORDER_ASCENDING) - .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE) - .build(); + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) + .addNamespace("namespace1", "namespace2") + .addSchemaType("schemaTypes1", "schemaTypes2") + .setSnippetCount(5) + .setSnippetCountPerProperty(10) + .setMaxSnippetSize(15) + .setResultCountPerPage(42) + .setOrder(SearchSpec.ORDER_ASCENDING) + .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE) + .build(); Bundle bundle = searchSpec.getBundle(); assertThat(bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD)) .isEqualTo(SearchSpec.TERM_MATCH_PREFIX); - assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD)).containsExactly( - "namespace1", "namespace2"); - assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD)).containsExactly( - "schemaTypes1", "schemaTypes2"); + assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD)) + .containsExactly("namespace1", "namespace2"); + assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD)) + .containsExactly("schemaTypes1", "schemaTypes2"); assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)).isEqualTo(5); assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)).isEqualTo(10); assertThat(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)).isEqualTo(15); diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java index 154779f7e5b62..9c34b172e1ff5 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java @@ -33,11 +33,11 @@ public class AppSearchResultCtsTest { assertThat(result1.hashCode()).isEqualTo(result2.hashCode()); AppSearchResult result3 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, - "errorMessage"); + AppSearchResult.newFailedResult( + AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); AppSearchResult result4 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, - "errorMessage"); + AppSearchResult.newFailedResult( + AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); assertThat(result3).isEqualTo(result4); assertThat(result3.hashCode()).isEqualTo(result4.hashCode()); @@ -47,7 +47,7 @@ public class AppSearchResultCtsTest { public void testResultEquals_failure() { AppSearchResult result1 = AppSearchResult.newSuccessfulResult("String"); AppSearchResult result2 = AppSearchResult.newSuccessfulResult("Wrong"); - AppSearchResult resultNull = AppSearchResult.newSuccessfulResult(/*value=*/null); + AppSearchResult resultNull = AppSearchResult.newSuccessfulResult(/*value=*/ null); assertThat(result1).isNotEqualTo(result2); assertThat(result1.hashCode()).isNotEqualTo(result2.hashCode()); @@ -55,26 +55,23 @@ public class AppSearchResultCtsTest { assertThat(result1.hashCode()).isNotEqualTo(resultNull.hashCode()); AppSearchResult result3 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, - "errorMessage"); + AppSearchResult.newFailedResult( + AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); AppSearchResult result4 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, - "errorMessage"); + AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, "errorMessage"); assertThat(result3).isNotEqualTo(result4); assertThat(result3.hashCode()).isNotEqualTo(result4.hashCode()); - AppSearchResult result5 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, - "Wrong"); + AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, "Wrong"); assertThat(result3).isNotEqualTo(result5); assertThat(result3.hashCode()).isNotEqualTo(result5.hashCode()); AppSearchResult result6 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, - /*errorMessage=*/null); + AppSearchResult.newFailedResult( + AppSearchResult.RESULT_INTERNAL_ERROR, /*errorMessage=*/ null); assertThat(result3).isNotEqualTo(result6); assertThat(result3.hashCode()).isNotEqualTo(result6.hashCode()); diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java index dc39f46cf01b3..2eaebd6e7b938 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java @@ -16,7 +16,6 @@ package android.app.appsearch.cts; - import static com.google.common.truth.Truth.assertThat; import static org.testng.Assert.expectThrows; @@ -55,21 +54,28 @@ public class AppSearchSchemaCtsTest { @Test public void testDuplicateProperties() { - AppSearchSchema.Builder builder = new AppSearchSchema.Builder("Email") - .addProperty(new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build() - ); - IllegalSchemaException e = expectThrows(IllegalSchemaException.class, - () -> builder.addProperty(new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build())); + AppSearchSchema.Builder builder = + new AppSearchSchema.Builder("Email") + .addProperty( + new PropertyConfig.Builder("subject") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build()); + IllegalSchemaException e = + expectThrows( + IllegalSchemaException.class, + () -> + builder.addProperty( + new PropertyConfig.Builder("subject") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType( + PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType( + PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build())); assertThat(e).hasMessageThat().contains("Property defined more than once: subject"); } } diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java index 0b9c3d2b42596..657d55696f1fe 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java @@ -25,114 +25,131 @@ import android.app.appsearch.GenericDocument; import org.junit.Test; public class GenericDocumentCtsTest { - private static final byte[] sByteArray1 = new byte[]{(byte) 1, (byte) 2, (byte) 3}; - private static final byte[] sByteArray2 = new byte[]{(byte) 4, (byte) 5, (byte) 6, (byte) 7}; - private static final GenericDocument sDocumentProperties1 = new GenericDocument - .Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") - .setCreationTimestampMillis(12345L) - .build(); - private static final GenericDocument sDocumentProperties2 = new GenericDocument - .Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") - .setCreationTimestampMillis(6789L) - .build(); + private static final byte[] sByteArray1 = new byte[] {(byte) 1, (byte) 2, (byte) 3}; + private static final byte[] sByteArray2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7}; + private static final GenericDocument sDocumentProperties1 = + new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") + .setCreationTimestampMillis(12345L) + .build(); + private static final GenericDocument sDocumentProperties2 = + new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") + .setCreationTimestampMillis(6789L) + .build(); @Test public void testDocumentEquals_identical() { - GenericDocument document1 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - GenericDocument document2 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); + GenericDocument document1 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setTtlMillis(1L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .build(); + GenericDocument document2 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setTtlMillis(1L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .build(); assertThat(document1).isEqualTo(document2); assertThat(document1.hashCode()).isEqualTo(document2.hashCode()); } @Test public void testDocumentEquals_differentOrder() { - GenericDocument document1 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .build(); + GenericDocument document1 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .build(); // Create second document with same parameter but different order. - GenericDocument document2 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .build(); + GenericDocument document2 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .build(); assertThat(document1).isEqualTo(document2); assertThat(document1.hashCode()).isEqualTo(document2.hashCode()); } @Test public void testDocumentEquals_failure() { - GenericDocument document1 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .build(); + GenericDocument document1 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .build(); // Create second document with same order but different value. - GenericDocument document2 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 4L) // Different - .build(); + GenericDocument document2 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyLong("longKey1", 1L, 2L, 4L) // Different + .build(); assertThat(document1).isNotEqualTo(document2); assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); } @Test public void testDocumentEquals_repeatedFieldOrder_failure() { - GenericDocument document1 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, false, true) - .build(); + GenericDocument document1 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyBoolean("booleanKey1", true, false, true) + .build(); // Create second document with same order but different value. - GenericDocument document2 = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, true, false) // Different - .build(); + GenericDocument document2 = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyBoolean("booleanKey1", true, true, false) // Different + .build(); assertThat(document1).isNotEqualTo(document2); assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); } @Test public void testDocumentGetSingleValue() { - GenericDocument document = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setScore(1) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L) - .setPropertyDouble("doubleKey1", 1.0) - .setPropertyBoolean("booleanKey1", true) - .setPropertyString("stringKey1", "test-value1") - .setPropertyBytes("byteKey1", sByteArray1) - .setPropertyDocument("documentKey1", sDocumentProperties1) - .build(); + GenericDocument document = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setScore(1) + .setTtlMillis(1L) + .setPropertyLong("longKey1", 1L) + .setPropertyDouble("doubleKey1", 1.0) + .setPropertyBoolean("booleanKey1", true) + .setPropertyString("stringKey1", "test-value1") + .setPropertyBytes("byteKey1", sByteArray1) + .setPropertyDocument("documentKey1", sDocumentProperties1) + .build(); assertThat(document.getUri()).isEqualTo("uri1"); assertThat(document.getTtlMillis()).isEqualTo(1L); assertThat(document.getSchemaType()).isEqualTo("schemaType1"); @@ -143,88 +160,102 @@ public class GenericDocumentCtsTest { assertThat(document.getPropertyBoolean("booleanKey1")).isTrue(); assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1"); assertThat(document.getPropertyBytes("byteKey1")) - .asList().containsExactly((byte) 1, (byte) 2, (byte) 3); + .asList() + .containsExactly((byte) 1, (byte) 2, (byte) 3); assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1); } @Test public void testDocumentGetArrayValues() { - GenericDocument document = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); + GenericDocument document = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .build(); assertThat(document.getUri()).isEqualTo("uri1"); assertThat(document.getSchemaType()).isEqualTo("schemaType1"); assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L); - assertThat(document.getPropertyDoubleArray("doubleKey1")).usingExactEquality() + assertThat(document.getPropertyDoubleArray("doubleKey1")) + .usingExactEquality() .containsExactly(1.0, 2.0, 3.0); - assertThat(document.getPropertyBooleanArray("booleanKey1")).asList() + assertThat(document.getPropertyBooleanArray("booleanKey1")) + .asList() .containsExactly(true, false, true); - assertThat(document.getPropertyStringArray("stringKey1")).asList() + assertThat(document.getPropertyStringArray("stringKey1")) + .asList() .containsExactly("test-value1", "test-value2", "test-value3"); - assertThat(document.getPropertyBytesArray("byteKey1")).asList() + assertThat(document.getPropertyBytesArray("byteKey1")) + .asList() .containsExactly(sByteArray1, sByteArray2); - assertThat(document.getPropertyDocumentArray("documentKey1")).asList() + assertThat(document.getPropertyDocumentArray("documentKey1")) + .asList() .containsExactly(sDocumentProperties1, sDocumentProperties2); } @Test public void testDocument_toString() { - GenericDocument document = new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "String1", "String2", "String3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - String exceptedString = "{ key: 'creationTimestampMillis' value: 5 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: " - + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } " - + "{ key: 'byteKey1' value: " - + "{ key: 'byteArray' value: [ '1' '2' '3' ] } " - + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } " - + "{ key: 'documentKey1' value: [ '" - + "{ key: 'creationTimestampMillis' value: 12345 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: } " - + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: sDocumentProperties1 } ' '" - + "{ key: 'creationTimestampMillis' value: 6789 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: } " - + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: sDocumentProperties2 } ' ] } " - + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } " - + "{ key: 'longKey1' value: [ '1' '2' '3' ] } " - + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } " - + "{ key: 'schemaType' value: schemaType1 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: uri1 } "; + GenericDocument document = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString("stringKey1", "String1", "String2", "String3") + .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) + .setPropertyDocument( + "documentKey1", sDocumentProperties1, sDocumentProperties2) + .build(); + String exceptedString = + "{ key: 'creationTimestampMillis' value: 5 } " + + "{ key: 'namespace' value: } " + + "{ key: 'properties' value: " + + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } " + + "{ key: 'byteKey1' value: " + + "{ key: 'byteArray' value: [ '1' '2' '3' ] } " + + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } " + + "{ key: 'documentKey1' value: [ '" + + "{ key: 'creationTimestampMillis' value: 12345 } " + + "{ key: 'namespace' value: } " + + "{ key: 'properties' value: } " + + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } " + + "{ key: 'score' value: 0 } " + + "{ key: 'ttlMillis' value: 0 } " + + "{ key: 'uri' value: sDocumentProperties1 } ' '" + + "{ key: 'creationTimestampMillis' value: 6789 } " + + "{ key: 'namespace' value: } " + + "{ key: 'properties' value: } " + + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } " + + "{ key: 'score' value: 0 } " + + "{ key: 'ttlMillis' value: 0 } " + + "{ key: 'uri' value: sDocumentProperties2 } ' ] } " + + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } " + + "{ key: 'longKey1' value: [ '1' '2' '3' ] } " + + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } " + + "{ key: 'schemaType' value: schemaType1 } " + + "{ key: 'score' value: 0 } " + + "{ key: 'ttlMillis' value: 0 } " + + "{ key: 'uri' value: uri1 } "; assertThat(document.toString()).isEqualTo(exceptedString); } @Test public void testDocumentGetValues_differentTypes() { - GenericDocument document = new GenericDocument.Builder<>("uri1", "schemaType1") - .setScore(1) - .setPropertyLong("longKey1", 1L) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .build(); + GenericDocument document = + new GenericDocument.Builder<>("uri1", "schemaType1") + .setScore(1) + .setPropertyLong("longKey1", 1L) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .build(); // Get a value for a key that doesn't exist assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0); @@ -236,7 +267,8 @@ public class GenericDocumentCtsTest { // Get a value with multiple elements as an array and as a single value assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1"); - assertThat(document.getPropertyStringArray("stringKey1")).asList() + assertThat(document.getPropertyStringArray("stringKey1")) + .asList() .containsExactly("test-value1", "test-value2", "test-value3"); // Get a value of the wrong type @@ -249,6 +281,6 @@ public class GenericDocumentCtsTest { GenericDocument.Builder builder = new GenericDocument.Builder<>("uri1", "schemaType1"); expectThrows( IllegalArgumentException.class, - () -> builder.setPropertyBoolean("test", new boolean[]{})); + () -> builder.setPropertyBoolean("test", new boolean[] {})); } } diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java index e50694585975e..50bca278534ef 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java @@ -27,31 +27,35 @@ import org.junit.Test; public class SearchSpecCtsTest { @Test public void buildSearchSpecWithoutTermMatchType() { - RuntimeException e = expectThrows(RuntimeException.class, () -> new SearchSpec.Builder() - .addSchemaType("testSchemaType") - .build()); + RuntimeException e = + expectThrows( + RuntimeException.class, + () -> new SearchSpec.Builder().addSchemaType("testSchemaType").build()); assertThat(e).hasMessageThat().contains("Missing termMatchType field"); } @Test public void testBuildSearchSpec() { - SearchSpec searchSpec = new SearchSpec.Builder() - .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) - .addNamespace("namespace1", "namespace2") - .addSchemaType("schemaTypes1", "schemaTypes2") - .setSnippetCount(5) - .setSnippetCountPerProperty(10) - .setMaxSnippetSize(15) - .setResultCountPerPage(42) - .setOrder(SearchSpec.ORDER_ASCENDING) - .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE) - .build(); + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) + .addNamespace("namespace1", "namespace2") + .addSchemaType("schemaTypes1", "schemaTypes2") + .setSnippetCount(5) + .setSnippetCountPerProperty(10) + .setMaxSnippetSize(15) + .setResultCountPerPage(42) + .setOrder(SearchSpec.ORDER_ASCENDING) + .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE) + .build(); assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX); assertThat(searchSpec.getNamespaces()) - .containsExactly("namespace1", "namespace2").inOrder(); + .containsExactly("namespace1", "namespace2") + .inOrder(); assertThat(searchSpec.getSchemaTypes()) - .containsExactly("schemaTypes1", "schemaTypes2").inOrder(); + .containsExactly("schemaTypes1", "schemaTypes2") + .inOrder(); assertThat(searchSpec.getSnippetCount()).isEqualTo(5); assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10); assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15); diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java index ac24dbf1a47dd..29b5754da5203 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java @@ -32,50 +32,58 @@ import org.junit.Test; */ public class CustomerDocumentTest { - private static final byte[] BYTE_ARRAY1 = new byte[]{(byte) 1, (byte) 2, (byte) 3}; - private static final byte[] BYTE_ARRAY2 = new byte[]{(byte) 4, (byte) 5, (byte) 6}; - private static final GenericDocument DOCUMENT_PROPERTIES1 = new GenericDocument - .Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") - .build(); - private static final GenericDocument DOCUMENT_PROPERTIES2 = new GenericDocument - .Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") - .build(); + private static final byte[] BYTE_ARRAY1 = new byte[] {(byte) 1, (byte) 2, (byte) 3}; + private static final byte[] BYTE_ARRAY2 = new byte[] {(byte) 4, (byte) 5, (byte) 6}; + private static final GenericDocument DOCUMENT_PROPERTIES1 = + new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") + .build(); + private static final GenericDocument DOCUMENT_PROPERTIES2 = + new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") + .build(); @Test public void testBuildCustomerDocument() { - CustomerDocument customerDocument = new CustomerDocument.Builder("uri1") - .setScore(1) - .setCreationTimestampMillis(0) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2) - .setPropertyDocument("documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2) - .build(); + CustomerDocument customerDocument = + new CustomerDocument.Builder("uri1") + .setScore(1) + .setCreationTimestampMillis(0) + .setPropertyLong("longKey1", 1L, 2L, 3L) + .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) + .setPropertyBoolean("booleanKey1", true, false, true) + .setPropertyString( + "stringKey1", "test-value1", "test-value2", "test-value3") + .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2) + .setPropertyDocument( + "documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2) + .build(); assertThat(customerDocument.getUri()).isEqualTo("uri1"); assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument"); assertThat(customerDocument.getScore()).isEqualTo(1); assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L); - assertThat(customerDocument.getPropertyLongArray("longKey1")).asList() + assertThat(customerDocument.getPropertyLongArray("longKey1")) + .asList() .containsExactly(1L, 2L, 3L); - assertThat(customerDocument.getPropertyDoubleArray("doubleKey1")).usingExactEquality() + assertThat(customerDocument.getPropertyDoubleArray("doubleKey1")) + .usingExactEquality() .containsExactly(1.0, 2.0, 3.0); - assertThat(customerDocument.getPropertyBooleanArray("booleanKey1")).asList() + assertThat(customerDocument.getPropertyBooleanArray("booleanKey1")) + .asList() .containsExactly(true, false, true); - assertThat(customerDocument.getPropertyStringArray("stringKey1")).asList() + assertThat(customerDocument.getPropertyStringArray("stringKey1")) + .asList() .containsExactly("test-value1", "test-value2", "test-value3"); - assertThat(customerDocument.getPropertyBytesArray("byteKey1")).asList() + assertThat(customerDocument.getPropertyBytesArray("byteKey1")) + .asList() .containsExactly(BYTE_ARRAY1, BYTE_ARRAY2); - assertThat(customerDocument.getPropertyDocumentArray("documentKey1")).asList() + assertThat(customerDocument.getPropertyDocumentArray("documentKey1")) + .asList() .containsExactly(DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2); } /** - * An example document type for test purposes, defined outside of - * {@link GenericDocument} (the way an external developer would define - * it). + * An example document type for test purposes, defined outside of {@link GenericDocument} (the + * way an external developer would define it). */ private static class CustomerDocument extends GenericDocument { private CustomerDocument(GenericDocument document) { diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index bc7df550f3163..b929061a967e7 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -25,8 +25,8 @@ import android.app.appsearch.GenericDocument; import android.app.appsearch.SearchResultPage; import android.app.appsearch.SearchSpec; import android.app.appsearch.exceptions.AppSearchException; -import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter; +import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter; import com.android.server.appsearch.proto.DocumentProto; import com.android.server.appsearch.proto.GetOptimizeInfoResultProto; import com.android.server.appsearch.proto.PropertyConfigProto; @@ -36,6 +36,7 @@ import com.android.server.appsearch.proto.SchemaTypeConfigProto; import com.android.server.appsearch.proto.SearchSpecProto; import com.android.server.appsearch.proto.StringIndexingConfig; import com.android.server.appsearch.proto.TermMatchType; + import com.google.common.collect.ImmutableSet; import org.junit.Before; @@ -50,8 +51,7 @@ import java.util.List; import java.util.Set; public class AppSearchImplTest { - @Rule - public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); + @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private AppSearchImpl mAppSearchImpl; private SchemaTypeConfigProto mVisibilitySchemaProto; @@ -61,13 +61,17 @@ public class AppSearchImplTest { AppSearchSchema visibilityAppSearchSchema = new AppSearchSchema.Builder( - VisibilityStore.DATABASE_NAME + AppSearchImpl.DATABASE_DELIMITER - + VisibilityStore.SCHEMA_TYPE) - .addProperty(new AppSearchSchema.PropertyConfig.Builder( - VisibilityStore.PLATFORM_HIDDEN_PROPERTY) - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) - .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .build()) + VisibilityStore.DATABASE_NAME + + AppSearchImpl.DATABASE_DELIMITER + + VisibilityStore.SCHEMA_TYPE) + .addProperty( + new AppSearchSchema.PropertyConfig.Builder( + VisibilityStore.PLATFORM_HIDDEN_PROPERTY) + .setDataType( + AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .setCardinality( + AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) + .build()) .build(); mVisibilitySchemaProto = SchemaToProtoConverter.convert(visibilityAppSearchSchema); } @@ -79,92 +83,132 @@ public class AppSearchImplTest { */ @Test public void testRewriteSchema_addType() throws Exception { - SchemaProto.Builder existingSchemaBuilder = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("existingDatabase/Foo").build()); + SchemaProto.Builder existingSchemaBuilder = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("existingDatabase/Foo") + .build()); // Create a copy so we can modify it. List existingTypes = new ArrayList<>(existingSchemaBuilder.getTypesList()); - SchemaProto newSchema = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("Foo").build()) - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("TestType") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("subject") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig(StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - .build() - ).build() - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("link") - .setDataType(PropertyConfigProto.DataType.Code.DOCUMENT) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setSchemaType("RefType") - .build() - ).build() - ).build(); + SchemaProto newSchema = + SchemaProto.newBuilder() + .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build()) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("TestType") + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("subject") + .setDataType( + PropertyConfigProto.DataType.Code + .STRING) + .setCardinality( + PropertyConfigProto.Cardinality.Code + .OPTIONAL) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig + .TokenizerType + .Code.PLAIN) + .setTermMatchType( + TermMatchType.Code + .PREFIX) + .build()) + .build()) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("link") + .setDataType( + PropertyConfigProto.DataType.Code + .DOCUMENT) + .setCardinality( + PropertyConfigProto.Cardinality.Code + .OPTIONAL) + .setSchemaType("RefType") + .build()) + .build()) + .build(); - AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = mAppSearchImpl.rewriteSchema( - "newDatabase", existingSchemaBuilder, - newSchema); + AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = + mAppSearchImpl.rewriteSchema("newDatabase", existingSchemaBuilder, newSchema); // We rewrote all the new types that were added. And nothing was removed. assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes) .containsExactly("newDatabase/Foo", "newDatabase/TestType"); assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty(); - SchemaProto expectedSchema = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("newDatabase/Foo").build()) - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("newDatabase/TestType") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("subject") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig(StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - .build() - ).build() - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("link") - .setDataType(PropertyConfigProto.DataType.Code.DOCUMENT) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setSchemaType("newDatabase/RefType") - .build() - ).build()) - .build(); + SchemaProto expectedSchema = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("newDatabase/Foo") + .build()) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("newDatabase/TestType") + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("subject") + .setDataType( + PropertyConfigProto.DataType.Code + .STRING) + .setCardinality( + PropertyConfigProto.Cardinality.Code + .OPTIONAL) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig + .TokenizerType + .Code.PLAIN) + .setTermMatchType( + TermMatchType.Code + .PREFIX) + .build()) + .build()) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("link") + .setDataType( + PropertyConfigProto.DataType.Code + .DOCUMENT) + .setCardinality( + PropertyConfigProto.Cardinality.Code + .OPTIONAL) + .setSchemaType("newDatabase/RefType") + .build()) + .build()) + .build(); existingTypes.addAll(expectedSchema.getTypesList()); assertThat(existingSchemaBuilder.getTypesList()).containsExactlyElementsIn(existingTypes); } /** - * Ensure that we track all types that were rewritten in the input schema. Even if they were - * not technically "added" to the existing schema. + * Ensure that we track all types that were rewritten in the input schema. Even if they were not + * technically "added" to the existing schema. */ @Test public void testRewriteSchema_rewriteType() throws Exception { - SchemaProto.Builder existingSchemaBuilder = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("existingDatabase/Foo").build()); + SchemaProto.Builder existingSchemaBuilder = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("existingDatabase/Foo") + .build()); - SchemaProto newSchema = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("Foo").build()) - .build(); + SchemaProto newSchema = + SchemaProto.newBuilder() + .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build()) + .build(); - AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = mAppSearchImpl.rewriteSchema( - "existingDatabase", existingSchemaBuilder, newSchema); + AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = + mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema); // Nothing was removed, but the method did rewrite the type name. assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes) @@ -183,17 +227,20 @@ public class AppSearchImplTest { */ @Test public void testRewriteSchema_deleteType() throws Exception { - SchemaProto.Builder existingSchemaBuilder = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("existingDatabase/Foo").build()); + SchemaProto.Builder existingSchemaBuilder = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("existingDatabase/Foo") + .build()); - SchemaProto newSchema = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("Bar").build()) - .build(); + SchemaProto newSchema = + SchemaProto.newBuilder() + .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Bar").build()) + .build(); - AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = mAppSearchImpl.rewriteSchema( - "existingDatabase", existingSchemaBuilder, newSchema); + AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults = + mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema); // Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the // new schema. @@ -203,10 +250,13 @@ public class AppSearchImplTest { .containsExactly("existingDatabase/Foo"); // Same schema since nothing was added. - SchemaProto expectedSchema = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("existingDatabase/Bar").build()) - .build(); + SchemaProto expectedSchema = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("existingDatabase/Bar") + .build()) + .build(); assertThat(existingSchemaBuilder.getTypesList()) .containsExactlyElementsIn(expectedSchema.getTypesList()); @@ -214,29 +264,35 @@ public class AppSearchImplTest { @Test public void testAddDocumentTypePrefix() { - DocumentProto insideDocument = DocumentProto.newBuilder() - .setUri("inside-uri") - .setSchema("type") - .setNamespace("namespace") - .build(); - DocumentProto documentProto = DocumentProto.newBuilder() - .setUri("uri") - .setSchema("type") - .setNamespace("namespace") - .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument)) - .build(); + DocumentProto insideDocument = + DocumentProto.newBuilder() + .setUri("inside-uri") + .setSchema("type") + .setNamespace("namespace") + .build(); + DocumentProto documentProto = + DocumentProto.newBuilder() + .setUri("uri") + .setSchema("type") + .setNamespace("namespace") + .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument)) + .build(); - DocumentProto expectedInsideDocument = DocumentProto.newBuilder() - .setUri("inside-uri") - .setSchema("databaseName/type") - .setNamespace("databaseName/namespace") - .build(); - DocumentProto expectedDocumentProto = DocumentProto.newBuilder() - .setUri("uri") - .setSchema("databaseName/type") - .setNamespace("databaseName/namespace") - .addProperties(PropertyProto.newBuilder().addDocumentValues(expectedInsideDocument)) - .build(); + DocumentProto expectedInsideDocument = + DocumentProto.newBuilder() + .setUri("inside-uri") + .setSchema("databaseName/type") + .setNamespace("databaseName/namespace") + .build(); + DocumentProto expectedDocumentProto = + DocumentProto.newBuilder() + .setUri("uri") + .setSchema("databaseName/type") + .setNamespace("databaseName/namespace") + .addProperties( + PropertyProto.newBuilder() + .addDocumentValues(expectedInsideDocument)) + .build(); DocumentProto.Builder actualDocument = documentProto.toBuilder(); mAppSearchImpl.addPrefixToDocument(actualDocument, "databaseName/"); @@ -245,30 +301,36 @@ public class AppSearchImplTest { @Test public void testRemoveDocumentTypePrefixes() throws Exception { - DocumentProto insideDocument = DocumentProto.newBuilder() - .setUri("inside-uri") - .setSchema("databaseName1/type") - .setNamespace("databaseName2/namespace") - .build(); - DocumentProto documentProto = DocumentProto.newBuilder() - .setUri("uri") - .setSchema("databaseName2/type") - .setNamespace("databaseName3/namespace") - .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument)) - .build(); + DocumentProto insideDocument = + DocumentProto.newBuilder() + .setUri("inside-uri") + .setSchema("databaseName1/type") + .setNamespace("databaseName2/namespace") + .build(); + DocumentProto documentProto = + DocumentProto.newBuilder() + .setUri("uri") + .setSchema("databaseName2/type") + .setNamespace("databaseName3/namespace") + .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument)) + .build(); - DocumentProto expectedInsideDocument = DocumentProto.newBuilder() - .setUri("inside-uri") - .setSchema("type") - .setNamespace("namespace") - .build(); + DocumentProto expectedInsideDocument = + DocumentProto.newBuilder() + .setUri("inside-uri") + .setSchema("type") + .setNamespace("namespace") + .build(); // Since we don't pass in "databaseName3/" as a prefix to remove, it stays on the Document. - DocumentProto expectedDocumentProto = DocumentProto.newBuilder() - .setUri("uri") - .setSchema("type") - .setNamespace("namespace") - .addProperties(PropertyProto.newBuilder().addDocumentValues(expectedInsideDocument)) - .build(); + DocumentProto expectedDocumentProto = + DocumentProto.newBuilder() + .setUri("uri") + .setSchema("type") + .setNamespace("namespace") + .addProperties( + PropertyProto.newBuilder() + .addDocumentValues(expectedInsideDocument)) + .build(); DocumentProto.Builder actualDocument = documentProto.toBuilder(); mAppSearchImpl.removeDatabasesFromDocument(actualDocument); @@ -280,14 +342,18 @@ public class AppSearchImplTest { // Insert schema Set schemas = Collections.singleton(new AppSearchSchema.Builder("type").build()); - mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/false); + mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false); // Insert enough documents. - for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; i++) { + for (int i = 0; + i + < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT + + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; + i++) { GenericDocument document = - new GenericDocument.Builder("uri" + i, "type").setNamespace( - "namespace").build(); + new GenericDocument.Builder("uri" + i, "type") + .setNamespace("namespace") + .build(); mAppSearchImpl.putDocument("database", document); } @@ -308,8 +374,10 @@ public class AppSearchImplTest { // Keep delete docs, will reach the interval this time and trigger optimize(). for (int i = AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT; - i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; i++) { + i + < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT + + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; + i++) { mAppSearchImpl.remove("database", "namespace", "uri" + i); } @@ -321,64 +389,61 @@ public class AppSearchImplTest { @Test public void testRewriteSearchSpec_oneInstance() throws Exception { - SearchSpecProto.Builder searchSpecProto = - SearchSpecProto.newBuilder().setQuery(""); + SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery(""); // Insert schema Set schemas = Collections.singleton(new AppSearchSchema.Builder("type").build()); - mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/false); + mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false); // Insert document - GenericDocument document = new GenericDocument.Builder("uri", "type").setNamespace( - "namespace").build(); + GenericDocument document = + new GenericDocument.Builder("uri", "type").setNamespace("namespace").build(); mAppSearchImpl.putDocument("database", document); // Rewrite SearchSpec - mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(searchSpecProto, - Collections.singleton( - "database")); + mAppSearchImpl.rewriteSearchSpecForDatabasesLocked( + searchSpecProto, Collections.singleton("database")); assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly("database/type"); assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly("database/namespace"); } @Test public void testRewriteSearchSpec_twoInstances() throws Exception { - SearchSpecProto.Builder searchSpecProto = - SearchSpecProto.newBuilder().setQuery(""); + SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery(""); // Insert schema - Set schemas = Set.of( - new AppSearchSchema.Builder("typeA").build(), - new AppSearchSchema.Builder("typeB").build()); - mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false); - mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/false); + Set schemas = + Set.of( + new AppSearchSchema.Builder("typeA").build(), + new AppSearchSchema.Builder("typeB").build()); + mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false); + mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false); // Insert documents - GenericDocument document1 = new GenericDocument.Builder("uri", "typeA").setNamespace( - "namespace").build(); + GenericDocument document1 = + new GenericDocument.Builder("uri", "typeA").setNamespace("namespace").build(); mAppSearchImpl.putDocument("database1", document1); - GenericDocument document2 = new GenericDocument.Builder("uri", "typeB").setNamespace( - "namespace").build(); + GenericDocument document2 = + new GenericDocument.Builder("uri", "typeB").setNamespace("namespace").build(); mAppSearchImpl.putDocument("database2", document2); // Rewrite SearchSpec - mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(searchSpecProto, - ImmutableSet.of("database1", "database2")); - assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly( - "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB"); - assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly( - "database1/namespace", "database2/namespace"); + mAppSearchImpl.rewriteSearchSpecForDatabasesLocked( + searchSpecProto, ImmutableSet.of("database1", "database2")); + assertThat(searchSpecProto.getSchemaTypeFiltersList()) + .containsExactly( + "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB"); + assertThat(searchSpecProto.getNamespaceFiltersList()) + .containsExactly("database1/namespace", "database2/namespace"); } @Test public void testQueryEmptyDatabase() throws Exception { SearchSpec searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build(); - SearchResultPage searchResultPage = mAppSearchImpl.query( - "EmptyDatabase", - "", searchSpec); + SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec); assertThat(searchResultPage.getResults()).isEmpty(); } @@ -386,25 +451,25 @@ public class AppSearchImplTest { public void testGlobalQueryEmptyDatabase() throws Exception { SearchSpec searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build(); - SearchResultPage searchResultPage = mAppSearchImpl.query( - "EmptyDatabase", - "", searchSpec); + SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec); assertThat(searchResultPage.getResults()).isEmpty(); } @Test public void testRemoveEmptyDatabase_noExceptionThrown() throws Exception { SearchSpec searchSpec = - new SearchSpec.Builder().addSchemaType("FakeType").setTermMatch( - TermMatchType.Code.PREFIX_VALUE).build(); - mAppSearchImpl.removeByQuery("EmptyDatabase", - "", searchSpec); + new SearchSpec.Builder() + .addSchemaType("FakeType") + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .build(); + mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec); searchSpec = - new SearchSpec.Builder().addNamespace("FakeNamespace").setTermMatch( - TermMatchType.Code.PREFIX_VALUE).build(); - mAppSearchImpl.removeByQuery("EmptyDatabase", - "", searchSpec); + new SearchSpec.Builder() + .addNamespace("FakeNamespace") + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .build(); + mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec); searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build(); mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec); @@ -415,12 +480,14 @@ public class AppSearchImplTest { Set schemas = Collections.singleton(new AppSearchSchema.Builder("Email").build()); // Set schema Email to AppSearch database1 - mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false); + mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false); // Create expected schemaType proto. - SchemaProto expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) - .build(); + SchemaProto expectedProto = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) + .build(); List expectedTypes = new ArrayList<>(); expectedTypes.add(mVisibilitySchemaProto); @@ -431,23 +498,28 @@ public class AppSearchImplTest { @Test public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception { - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "schema1").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("schema1").build()), + /*forceOverride=*/ false); mAppSearchImpl.setVisibility("database", Set.of("schema1")); // "schema1" is platform hidden now - assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).containsExactly("database/schema1"); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .containsExactly("database/schema1"); // Add a new schema, and include the already-existing "schema1" - mAppSearchImpl.setSchema("database", Set.of(new AppSearchSchema.Builder( - "schema1").build(), new AppSearchSchema.Builder( - "schema2").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Set.of( + new AppSearchSchema.Builder("schema1").build(), + new AppSearchSchema.Builder("schema2").build()), + /*forceOverride=*/ false); // Check that "schema1" is still platform hidden, but "schema2" is the default platform // visible. - assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).containsExactly("database/schema1"); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .containsExactly("database/schema1"); } @Test @@ -456,13 +528,17 @@ public class AppSearchImplTest { schemas.add(new AppSearchSchema.Builder("Email").build()); schemas.add(new AppSearchSchema.Builder("Document").build()); // Set schema Email and Document to AppSearch database1 - mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false); + mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false); // Create expected schemaType proto. - SchemaProto expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Document")) - .build(); + SchemaProto expectedProto = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("database1/Document")) + .build(); // Check both schema Email and Document saved correctly. List expectedTypes = new ArrayList<>(); @@ -471,21 +547,27 @@ public class AppSearchImplTest { assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList()) .containsExactlyElementsIn(expectedTypes); - final Set finalSchemas = Collections.singleton(new AppSearchSchema.Builder( - "Email").build()); + final Set finalSchemas = + Collections.singleton(new AppSearchSchema.Builder("Email").build()); // Check the incompatible error has been thrown. - AppSearchException e = expectThrows(AppSearchException.class, () -> - mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/false)); + AppSearchException e = + expectThrows( + AppSearchException.class, + () -> + mAppSearchImpl.setSchema( + "database1", finalSchemas, /*forceOverride=*/ false)); assertThat(e).hasMessageThat().contains("Schema is incompatible"); assertThat(e).hasMessageThat().contains("Deleted types: [database1/Document]"); // ForceOverride to delete. - mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/true); + mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/ true); // Check Document schema is removed. - expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) - .build(); + expectedProto = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) + .build(); expectedTypes = new ArrayList<>(); expectedTypes.add(mVisibilitySchemaProto); @@ -502,16 +584,23 @@ public class AppSearchImplTest { schemas.add(new AppSearchSchema.Builder("Document").build()); // Set schema Email and Document to AppSearch database1 and 2 - mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false); - mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/false); + mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false); + mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false); // Create expected schemaType proto. - SchemaProto expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Document")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Document")) - .build(); + SchemaProto expectedProto = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("database1/Document")) + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email")) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("database2/Document")) + .build(); // Check Email and Document is saved in database 1 and 2 correctly. List expectedTypes = new ArrayList<>(); @@ -522,15 +611,20 @@ public class AppSearchImplTest { // Save only Email to database1 this time. schemas = Collections.singleton(new AppSearchSchema.Builder("Email").build()); - mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/true); + mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ true); // Create expected schemaType list, database 1 should only contain Email but database 2 // remains in same. - expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email")) - .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Document")) - .build(); + expectedProto = + SchemaProto.newBuilder() + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email")) + .addTypes( + SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email")) + .addTypes( + SchemaTypeConfigProto.newBuilder() + .setSchemaType("database2/Document")) + .build(); // Check nothing changed in database2. expectedTypes = new ArrayList<>(); @@ -540,61 +634,69 @@ public class AppSearchImplTest { .containsExactlyElementsIn(expectedTypes); } - @Test public void testRemoveSchema_removedFromVisibilityStore() throws Exception { - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "schema1").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("schema1").build()), + /*forceOverride=*/ false); mAppSearchImpl.setVisibility("database", Set.of("schema1")); // "schema1" is platform hidden now - assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).containsExactly("database/schema1"); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .containsExactly("database/schema1"); // Remove "schema1" by force overriding - mAppSearchImpl.setSchema("database", Collections.emptySet(), /*forceOverride=*/true); + mAppSearchImpl.setSchema("database", Collections.emptySet(), /*forceOverride=*/ true); // Check that "schema1" is no longer considered platform hidden - assertThat( - mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).isEmpty(); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .isEmpty(); // Add "schema1" back, it gets default visibility settings which means it's not platform // hidden. - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "schema1").build()), /*forceOverride=*/false); - assertThat( - mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).isEmpty(); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("schema1").build()), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .isEmpty(); } @Test public void testSetVisibility_defaultPlatformVisible() throws Exception { - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "Schema").build()), /*forceOverride=*/false); - assertThat( - mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).isEmpty(); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("Schema").build()), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .isEmpty(); } @Test public void testSetVisibility_platformHidden() throws Exception { - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "Schema").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("Schema").build()), + /*forceOverride=*/ false); mAppSearchImpl.setVisibility("database", Set.of("Schema")); - assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas( - "database")).containsExactly("database/Schema"); + assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database")) + .containsExactly("database/Schema"); } @Test public void testSetVisibility_unknownSchema() throws Exception { - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "Schema").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("Schema").build()), + /*forceOverride=*/ false); // We'll throw an exception if a client tries to set visibility on a schema we don't know // about. - AppSearchException e = expectThrows(AppSearchException.class, - () -> mAppSearchImpl.setVisibility("database", Set.of("UnknownSchema"))); + AppSearchException e = + expectThrows( + AppSearchException.class, + () -> mAppSearchImpl.setVisibility("database", Set.of("UnknownSchema"))); assertThat(e).hasMessageThat().contains("Unknown schema(s)"); } @@ -603,8 +705,10 @@ public class AppSearchImplTest { // Nothing exists yet assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isFalse(); - mAppSearchImpl.setSchema("database", Collections.singleton(new AppSearchSchema.Builder( - "Schema").build()), /*forceOverride=*/false); + mAppSearchImpl.setSchema( + "database", + Collections.singleton(new AppSearchSchema.Builder("Schema").build()), + /*forceOverride=*/ false); assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isTrue(); assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "UnknownSchema")).isFalse(); @@ -613,19 +717,23 @@ public class AppSearchImplTest { @Test public void testGetDatabases() throws Exception { // No client databases exist yet, but the VisibilityStore's does - assertThat(mAppSearchImpl.getDatabasesLocked()).containsExactly( - VisibilityStore.DATABASE_NAME); + assertThat(mAppSearchImpl.getDatabasesLocked()) + .containsExactly(VisibilityStore.DATABASE_NAME); // Has database1 - mAppSearchImpl.setSchema("database1", Collections.singleton(new AppSearchSchema.Builder( - "schema").build()), /*forceOverride=*/false); - assertThat(mAppSearchImpl.getDatabasesLocked()).containsExactly( - VisibilityStore.DATABASE_NAME, "database1"); + mAppSearchImpl.setSchema( + "database1", + Collections.singleton(new AppSearchSchema.Builder("schema").build()), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getDatabasesLocked()) + .containsExactly(VisibilityStore.DATABASE_NAME, "database1"); // Has both databases - mAppSearchImpl.setSchema("database2", Collections.singleton(new AppSearchSchema.Builder( - "schema").build()), /*forceOverride=*/false); - assertThat(mAppSearchImpl.getDatabasesLocked()).containsExactly( - VisibilityStore.DATABASE_NAME, "database1", "database2"); + mAppSearchImpl.setSchema( + "database2", + Collections.singleton(new AppSearchSchema.Builder("schema").build()), + /*forceOverride=*/ false); + assertThat(mAppSearchImpl.getDatabasesLocked()) + .containsExactly(VisibilityStore.DATABASE_NAME, "database1", "database2"); } } diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java index 29619feb03c23..dfe2de6538a49 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java @@ -28,8 +28,7 @@ import java.util.Set; public class VisibilityStoreTest { - @Rule - public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); + @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private AppSearchImpl mAppSearchImpl; private VisibilityStore mVisibilityStore; @@ -72,5 +71,4 @@ public class VisibilityStoreTest { mVisibilityStore.updateSchemas("database", /*schemasToRemove=*/ Set.of("schema2")); assertThat(mVisibilityStore.getPlatformHiddenSchemas("database")).isEmpty(); } - } diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java index 85d4f01f8d41f..98392a71be589 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java @@ -32,18 +32,18 @@ import java.util.HashMap; import java.util.List; public class GenericDocumentToProtoConverterTest { - private static final byte[] BYTE_ARRAY_1 = new byte[]{(byte) 1, (byte) 2, (byte) 3}; - private static final byte[] BYTE_ARRAY_2 = new byte[]{(byte) 4, (byte) 5, (byte) 6, (byte) 7}; + private static final byte[] BYTE_ARRAY_1 = new byte[] {(byte) 1, (byte) 2, (byte) 3}; + private static final byte[] BYTE_ARRAY_2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7}; private static final GenericDocument DOCUMENT_PROPERTIES_1 = new GenericDocument.Builder>( - "sDocumentProperties1", "sDocumentPropertiesSchemaType1") - .setCreationTimestampMillis(12345L) - .build(); + "sDocumentProperties1", "sDocumentPropertiesSchemaType1") + .setCreationTimestampMillis(12345L) + .build(); private static final GenericDocument DOCUMENT_PROPERTIES_2 = new GenericDocument.Builder>( - "sDocumentProperties2", "sDocumentPropertiesSchemaType2") - .setCreationTimestampMillis(6789L) - .build(); + "sDocumentProperties2", "sDocumentPropertiesSchemaType2") + .setCreationTimestampMillis(6789L) + .build(); @Test public void testDocumentProtoConvert() { @@ -63,32 +63,42 @@ public class GenericDocumentToProtoConverterTest { .build(); // Create the Document proto. Need to sort the property order by key. - DocumentProto.Builder documentProtoBuilder = DocumentProto.newBuilder() - .setUri("uri1") - .setSchema("schemaType1") - .setCreationTimestampMs(5L) - .setScore(1) - .setTtlMs(1L) - .setNamespace("namespace"); + DocumentProto.Builder documentProtoBuilder = + DocumentProto.newBuilder() + .setUri("uri1") + .setSchema("schemaType1") + .setCreationTimestampMs(5L) + .setScore(1) + .setTtlMs(1L) + .setNamespace("namespace"); HashMap propertyProtoMap = new HashMap<>(); - propertyProtoMap.put("longKey1", - PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L)); - propertyProtoMap.put("doubleKey1", + propertyProtoMap.put( + "longKey1", PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L)); + propertyProtoMap.put( + "doubleKey1", PropertyProto.newBuilder().setName("doubleKey1").addDoubleValues(1.0)); - propertyProtoMap.put("booleanKey1", + propertyProtoMap.put( + "booleanKey1", PropertyProto.newBuilder().setName("booleanKey1").addBooleanValues(true)); - propertyProtoMap.put("stringKey1", + propertyProtoMap.put( + "stringKey1", PropertyProto.newBuilder().setName("stringKey1").addStringValues("test-value1")); - propertyProtoMap.put("byteKey1", - PropertyProto.newBuilder().setName("byteKey1") + propertyProtoMap.put( + "byteKey1", + PropertyProto.newBuilder() + .setName("byteKey1") .addBytesValues(ByteString.copyFrom(BYTE_ARRAY_1)) .addBytesValues(ByteString.copyFrom(BYTE_ARRAY_2))); - propertyProtoMap.put("documentKey1", - PropertyProto.newBuilder().setName("documentKey1") + propertyProtoMap.put( + "documentKey1", + PropertyProto.newBuilder() + .setName("documentKey1") .addDocumentValues( GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1))); - propertyProtoMap.put("documentKey2", - PropertyProto.newBuilder().setName("documentKey2") + propertyProtoMap.put( + "documentKey2", + PropertyProto.newBuilder() + .setName("documentKey2") .addDocumentValues( GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2))); List sortedKey = new ArrayList<>(propertyProtoMap.keySet()); @@ -97,8 +107,7 @@ public class GenericDocumentToProtoConverterTest { documentProtoBuilder.addProperties(propertyProtoMap.get(key)); } DocumentProto documentProto = documentProtoBuilder.build(); - assertThat(GenericDocumentToProtoConverter.convert(document)) - .isEqualTo(documentProto); + assertThat(GenericDocumentToProtoConverter.convert(document)).isEqualTo(documentProto); assertThat(document).isEqualTo(GenericDocumentToProtoConverter.convert(documentProto)); } } 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 5ad8350b926db..dedfca42ff90f 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 @@ -30,88 +30,126 @@ import org.junit.Test; public class SchemaToProtoConverterTest { @Test public void testGetProto_Email() { - AppSearchSchema emailSchema = new AppSearchSchema.Builder("Email") - .addProperty(new AppSearchSchema.PropertyConfig.Builder("subject") - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) - .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder("body") - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) - .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build() - ).build(); + AppSearchSchema emailSchema = + new AppSearchSchema.Builder("Email") + .addProperty( + new AppSearchSchema.PropertyConfig.Builder("subject") + .setDataType( + AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .setCardinality( + AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType( + AppSearchSchema.PropertyConfig + .INDEXING_TYPE_PREFIXES) + .setTokenizerType( + AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build()) + .addProperty( + new AppSearchSchema.PropertyConfig.Builder("body") + .setDataType( + AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .setCardinality( + AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType( + AppSearchSchema.PropertyConfig + .INDEXING_TYPE_PREFIXES) + .setTokenizerType( + AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build()) + .build(); - SchemaTypeConfigProto expectedEmailProto = SchemaTypeConfigProto.newBuilder() - .setSchemaType("Email") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("subject") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig( - StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("body") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig( - StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) - ).build(); + SchemaTypeConfigProto expectedEmailProto = + SchemaTypeConfigProto.newBuilder() + .setSchemaType("Email") + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("subject") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality( + PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig.TokenizerType + .Code.PLAIN) + .setTermMatchType( + TermMatchType.Code.PREFIX))) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("body") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality( + PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig.TokenizerType + .Code.PLAIN) + .setTermMatchType( + TermMatchType.Code.PREFIX))) + .build(); assertThat(SchemaToProtoConverter.convert(emailSchema)).isEqualTo(expectedEmailProto); } @Test public void testGetProto_MusicRecording() { - AppSearchSchema musicRecordingSchema = new AppSearchSchema.Builder("MusicRecording") - .addProperty(new AppSearchSchema.PropertyConfig.Builder("artist") - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) - .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build() - ).addProperty(new AppSearchSchema.PropertyConfig.Builder("pubDate") - .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) - .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) - .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) - .build() - ).build(); + AppSearchSchema musicRecordingSchema = + new AppSearchSchema.Builder("MusicRecording") + .addProperty( + new AppSearchSchema.PropertyConfig.Builder("artist") + .setDataType( + AppSearchSchema.PropertyConfig.DATA_TYPE_STRING) + .setCardinality( + AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) + .setIndexingType( + AppSearchSchema.PropertyConfig + .INDEXING_TYPE_PREFIXES) + .setTokenizerType( + AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build()) + .addProperty( + new AppSearchSchema.PropertyConfig.Builder("pubDate") + .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64) + .setCardinality( + AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType( + AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType( + AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE) + .build()) + .build(); - SchemaTypeConfigProto expectedMusicRecordingProto = SchemaTypeConfigProto.newBuilder() - .setSchemaType("MusicRecording") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("artist") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED) - .setStringIndexingConfig( - StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("pubDate") - .setDataType(PropertyConfigProto.DataType.Code.INT64) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setStringIndexingConfig( - StringIndexingConfig.newBuilder() - .setTokenizerType( - StringIndexingConfig.TokenizerType.Code.NONE) - .setTermMatchType(TermMatchType.Code.UNKNOWN) - ) - ).build(); + SchemaTypeConfigProto expectedMusicRecordingProto = + SchemaTypeConfigProto.newBuilder() + .setSchemaType("MusicRecording") + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("artist") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality( + PropertyConfigProto.Cardinality.Code.REPEATED) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig.TokenizerType + .Code.PLAIN) + .setTermMatchType( + TermMatchType.Code.PREFIX))) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("pubDate") + .setDataType(PropertyConfigProto.DataType.Code.INT64) + .setCardinality( + PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setStringIndexingConfig( + StringIndexingConfig.newBuilder() + .setTokenizerType( + StringIndexingConfig.TokenizerType + .Code.NONE) + .setTermMatchType( + TermMatchType.Code.UNKNOWN))) + .build(); assertThat(SchemaToProtoConverter.convert(musicRecordingSchema)) .isEqualTo(expectedMusicRecordingProto); diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java index 2e9286c6b2ad2..518f53205588a 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java @@ -36,9 +36,10 @@ public class SnippetTest { public void testSingleStringSnippet() { final String propertyKeyString = "content"; - final String propertyValueString = "A commonly used fake word is foo.\n" - + " Another nonsense word that’s used a lot\n" - + " is bar.\n"; + final String propertyValueString = + "A commonly used fake word is foo.\n" + + " Another nonsense word that’s used a lot\n" + + " is bar.\n"; final String uri = "uri1"; final String schemaType = "schema1"; final String searchWord = "foo"; @@ -46,34 +47,39 @@ public class SnippetTest { final String window = "is foo"; // Building the SearchResult received from query. - PropertyProto property = PropertyProto.newBuilder() - .setName(propertyKeyString) - .addStringValues(propertyValueString) - .build(); - DocumentProto documentProto = DocumentProto.newBuilder() - .setUri(uri) - .setSchema(schemaType) - .addProperties(property) - .build(); - SnippetProto snippetProto = SnippetProto.newBuilder() - .addEntries(SnippetProto.EntryProto.newBuilder() - .setPropertyName(propertyKeyString) - .addSnippetMatches(SnippetMatchProto.newBuilder() - .setValuesIndex(0) - .setExactMatchPosition(29) - .setExactMatchBytes(3) - .setWindowPosition(26) - .setWindowBytes(6) - .build()) - .build()) - .build(); - SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder() - .setDocument(documentProto) - .setSnippet(snippetProto) - .build(); - SearchResultProto searchResultProto = SearchResultProto.newBuilder() - .addResults(resultProto) - .build(); + PropertyProto property = + PropertyProto.newBuilder() + .setName(propertyKeyString) + .addStringValues(propertyValueString) + .build(); + DocumentProto documentProto = + DocumentProto.newBuilder() + .setUri(uri) + .setSchema(schemaType) + .addProperties(property) + .build(); + SnippetProto snippetProto = + SnippetProto.newBuilder() + .addEntries( + SnippetProto.EntryProto.newBuilder() + .setPropertyName(propertyKeyString) + .addSnippetMatches( + SnippetMatchProto.newBuilder() + .setValuesIndex(0) + .setExactMatchPosition(29) + .setExactMatchBytes(3) + .setWindowPosition(26) + .setWindowBytes(6) + .build()) + .build()) + .build(); + SearchResultProto.ResultProto resultProto = + SearchResultProto.ResultProto.newBuilder() + .setDocument(documentProto) + .setSnippet(snippetProto) + .build(); + SearchResultProto searchResultProto = + SearchResultProto.newBuilder().addResults(resultProto).build(); // Making ResultReader and getting Snippet values. SearchResultPage searchResultPage = @@ -83,11 +89,11 @@ public class SnippetTest { assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString); assertThat(match.getFullText()).isEqualTo(propertyValueString); assertThat(match.getExactMatch()).isEqualTo(exactMatch); - assertThat(match.getExactMatchPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/29, /*upper=*/32)); + assertThat(match.getExactMatchPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 29, /*upper=*/ 32)); assertThat(match.getFullText()).isEqualTo(propertyValueString); - assertThat(match.getSnippetPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/26, /*upper=*/32)); + assertThat(match.getSnippetPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 26, /*upper=*/ 32)); assertThat(match.getSnippet()).isEqualTo(window); } } @@ -97,9 +103,10 @@ public class SnippetTest { public void testNoSnippets() throws Exception { final String propertyKeyString = "content"; - final String propertyValueString = "A commonly used fake word is foo.\n" - + " Another nonsense word that’s used a lot\n" - + " is bar.\n"; + final String propertyValueString = + "A commonly used fake word is foo.\n" + + " Another nonsense word that’s used a lot\n" + + " is bar.\n"; final String uri = "uri1"; final String schemaType = "schema1"; final String searchWord = "foo"; @@ -107,21 +114,21 @@ public class SnippetTest { final String window = "is foo"; // Building the SearchResult received from query. - PropertyProto property = PropertyProto.newBuilder() - .setName(propertyKeyString) - .addStringValues(propertyValueString) - .build(); - DocumentProto documentProto = DocumentProto.newBuilder() - .setUri(uri) - .setSchema(schemaType) - .addProperties(property) - .build(); - SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder() - .setDocument(documentProto) - .build(); - SearchResultProto searchResultProto = SearchResultProto.newBuilder() - .addResults(resultProto) - .build(); + PropertyProto property = + PropertyProto.newBuilder() + .setName(propertyKeyString) + .addStringValues(propertyValueString) + .build(); + DocumentProto documentProto = + DocumentProto.newBuilder() + .setUri(uri) + .setSchema(schemaType) + .addProperties(property) + .build(); + SearchResultProto.ResultProto resultProto = + SearchResultProto.ResultProto.newBuilder().setDocument(documentProto).build(); + SearchResultProto searchResultProto = + SearchResultProto.newBuilder().addResults(resultProto).build(); SearchResultPage searchResultPage = SearchResultToProtoConverter.convertToSearchResultPage(searchResultProto); @@ -135,54 +142,57 @@ public class SnippetTest { final String searchWord = "Test"; // Building the SearchResult received from query. - PropertyProto property1 = PropertyProto.newBuilder() - .setName("sender.name") - .addStringValues("Test Name Jr.") - .build(); - PropertyProto property2 = PropertyProto.newBuilder() - .setName("sender.email") - .addStringValues("TestNameJr@gmail.com") - .build(); - DocumentProto documentProto = DocumentProto.newBuilder() - .setUri("uri1") - .setSchema("schema1") - .addProperties(property1) - .addProperties(property2) - .build(); - SnippetProto snippetProto = SnippetProto.newBuilder() - .addEntries( - SnippetProto.EntryProto.newBuilder() - .setPropertyName("sender.name") - .addSnippetMatches( - SnippetMatchProto.newBuilder() - .setValuesIndex(0) - .setExactMatchPosition(0) - .setExactMatchBytes(4) - .setWindowPosition(0) - .setWindowBytes(9) - .build()) - .build()) - .addEntries( - SnippetProto.EntryProto.newBuilder() - .setPropertyName("sender.email") - .addSnippetMatches( - SnippetMatchProto.newBuilder() - .setValuesIndex(0) - .setExactMatchPosition(0) - .setExactMatchBytes(20) - .setWindowPosition(0) - .setWindowBytes(20) - .build()) - .build() - ) - .build(); - SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder() - .setDocument(documentProto) - .setSnippet(snippetProto) - .build(); - SearchResultProto searchResultProto = SearchResultProto.newBuilder() - .addResults(resultProto) - .build(); + PropertyProto property1 = + PropertyProto.newBuilder() + .setName("sender.name") + .addStringValues("Test Name Jr.") + .build(); + PropertyProto property2 = + PropertyProto.newBuilder() + .setName("sender.email") + .addStringValues("TestNameJr@gmail.com") + .build(); + DocumentProto documentProto = + DocumentProto.newBuilder() + .setUri("uri1") + .setSchema("schema1") + .addProperties(property1) + .addProperties(property2) + .build(); + SnippetProto snippetProto = + SnippetProto.newBuilder() + .addEntries( + SnippetProto.EntryProto.newBuilder() + .setPropertyName("sender.name") + .addSnippetMatches( + SnippetMatchProto.newBuilder() + .setValuesIndex(0) + .setExactMatchPosition(0) + .setExactMatchBytes(4) + .setWindowPosition(0) + .setWindowBytes(9) + .build()) + .build()) + .addEntries( + SnippetProto.EntryProto.newBuilder() + .setPropertyName("sender.email") + .addSnippetMatches( + SnippetMatchProto.newBuilder() + .setValuesIndex(0) + .setExactMatchPosition(0) + .setExactMatchBytes(20) + .setWindowPosition(0) + .setWindowBytes(20) + .build()) + .build()) + .build(); + SearchResultProto.ResultProto resultProto = + SearchResultProto.ResultProto.newBuilder() + .setDocument(documentProto) + .setSnippet(snippetProto) + .build(); + SearchResultProto searchResultProto = + SearchResultProto.newBuilder().addResults(resultProto).build(); // Making ResultReader and getting Snippet values. SearchResultPage searchResultPage = @@ -192,21 +202,21 @@ public class SnippetTest { SearchResult.MatchInfo match1 = result.getMatches().get(0); assertThat(match1.getPropertyPath()).isEqualTo("sender.name"); assertThat(match1.getFullText()).isEqualTo("Test Name Jr."); - assertThat(match1.getExactMatchPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/0, /*upper=*/4)); + assertThat(match1.getExactMatchPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4)); assertThat(match1.getExactMatch()).isEqualTo("Test"); - assertThat(match1.getSnippetPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/0, /*upper=*/9)); + assertThat(match1.getSnippetPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9)); assertThat(match1.getSnippet()).isEqualTo("Test Name"); SearchResult.MatchInfo match2 = result.getMatches().get(1); assertThat(match2.getPropertyPath()).isEqualTo("sender.email"); assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com"); - assertThat(match2.getExactMatchPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/0, /*upper=*/20)); + assertThat(match2.getExactMatchPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20)); assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com"); - assertThat(match2.getSnippetPosition()).isEqualTo( - new SearchResult.MatchRange(/*lower=*/0, /*upper=*/20)); + assertThat(match2.getSnippetPosition()) + .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20)); assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com"); } }