From 7ab38de4a7110d93331e8cd59dd669fc90f57adc Mon Sep 17 00:00:00 2001 From: Alexander Dorokhine Date: Thu, 29 Oct 2020 22:37:00 -0700 Subject: [PATCH] Merge frontend changes from Jetpack into Framework. Includes new APIs to comply with MissingGetterForSetter. Bug: 162450968 Test: AppSearchManagerTest Change-Id: I14fb2c815f2393968a06155c326f68562d066361 --- .../android/app/appsearch/AppSearchEmail.java | 59 +++-- .../app/appsearch/AppSearchSchema.java | 130 +++++++---- .../app/appsearch/GenericDocument.java | 79 ++++--- .../app/appsearch/GetByUriRequest.java | 16 +- .../app/appsearch/PutDocumentsRequest.java | 12 +- .../app/appsearch/RemoveByUriRequest.java | 16 +- .../android/app/appsearch/SearchResult.java | 38 +-- .../android/app/appsearch/SearchSpec.java | 220 ++++++++++++------ .../app/appsearch/SetSchemaRequest.java | 14 +- .../exceptions/AppSearchException.java | 1 + .../appsearch/AppSearchManagerService.java | 18 +- .../server/appsearch/ImplInstanceManager.java | 2 +- .../AppSearchImpl.java | 2 +- .../GenericDocumentToProtoConverter.java | 80 +++---- .../converter/SchemaToProtoConverter.java | 45 ++-- .../SearchResultToProtoConverter.java | 23 +- .../converter/SearchSpecToProtoConverter.java | 43 ++-- .../external/app/AppSearchEmailTest.java | 2 +- .../external/app/GenericDocumentTest.java | 101 ++++---- .../external/app/SearchResultsTest.java | 30 --- .../external/app/SearchSpecTest.java | 92 ++++++++ .../app/customer/CustomerDocumentTest.java | 12 +- .../AppSearchImplTest.java | 2 +- .../GenericDocumentToProtoConverterTest.java | 20 +- .../converter/SchemaToProtoConverterTest.java | 6 +- .../converter/SnippetTest.java | 4 +- 26 files changed, 614 insertions(+), 453 deletions(-) rename apex/appsearch/service/java/com/android/server/appsearch/external/{localbackend => localstorage}/AppSearchImpl.java (99%) rename apex/appsearch/service/java/com/android/server/appsearch/external/{localbackend => localstorage}/converter/GenericDocumentToProtoConverter.java (69%) rename apex/appsearch/service/java/com/android/server/appsearch/external/{localbackend => localstorage}/converter/SchemaToProtoConverter.java (73%) rename apex/appsearch/service/java/com/android/server/appsearch/external/{localbackend => localstorage}/converter/SearchResultToProtoConverter.java (80%) rename apex/appsearch/service/java/com/android/server/appsearch/external/{localbackend => localstorage}/converter/SearchSpecToProtoConverter.java (67%) delete mode 100644 core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java create mode 100644 core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java rename services/tests/servicestests/src/com/android/server/appsearch/external/{localbackend => localstorage}/AppSearchImplTest.java (99%) rename services/tests/servicestests/src/com/android/server/appsearch/external/{localbackend => localstorage}/converter/GenericDocumentToProtoConverterTest.java (86%) rename services/tests/servicestests/src/com/android/server/appsearch/external/{localbackend => localstorage}/converter/SchemaToProtoConverterTest.java (96%) rename services/tests/servicestests/src/com/android/server/appsearch/external/{localbackend => localstorage}/converter/SnippetTest.java (98%) diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java index 5f2fabe529293..beb9ad3d27ea4 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java @@ -27,8 +27,6 @@ import android.app.appsearch.AppSearchSchema.PropertyConfig; * *

This class is a higher level implement of {@link GenericDocument}. * - *

This class will eventually migrate to Jetpack, where it will become public API. - * * @hide */ @@ -99,10 +97,9 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the from address of {@link AppSearchEmail}. + * Gets the from address of {@link AppSearchEmail}. * - * @return Returns the subject of {@link AppSearchEmail} or {@code null} if it's not been set - * yet. + * @return The subject of {@link AppSearchEmail} or {@code null} if it's not been set yet. */ @Nullable public String getFrom() { @@ -110,10 +107,10 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the destination addresses of {@link AppSearchEmail}. + * Gets the destination addresses of {@link AppSearchEmail}. * - * @return Returns 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() { @@ -121,10 +118,9 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the CC list of {@link AppSearchEmail}. + * Gets the CC list of {@link AppSearchEmail}. * - * @return Returns the CC list of {@link AppSearchEmail} or {@code null} if it's not been set - * yet. + * @return The CC list of {@link AppSearchEmail} or {@code null} if it's not been set yet. */ @Nullable public String[] getCc() { @@ -132,10 +128,9 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the BCC list of {@link AppSearchEmail}. + * Gets the BCC list of {@link AppSearchEmail}. * - * @return Returns the BCC list of {@link AppSearchEmail} or {@code null} if it's not been set - * yet. + * @return The BCC list of {@link AppSearchEmail} or {@code null} if it's not been set yet. */ @Nullable public String[] getBcc() { @@ -143,10 +138,9 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the subject of {@link AppSearchEmail}. + * Gets the subject of {@link AppSearchEmail}. * - * @return Returns the value subject of {@link AppSearchEmail} or {@code null} if it's not been - * set yet. + * @return The value subject of {@link AppSearchEmail} or {@code null} if it's not been set yet. */ @Nullable public String getSubject() { @@ -154,9 +148,9 @@ public class AppSearchEmail extends GenericDocument { } /** - * Get the body of {@link AppSearchEmail}. + * Gets the body of {@link AppSearchEmail}. * - * @return Returns the body of {@link AppSearchEmail} or {@code null} if it's not been set yet. + * @return The body of {@link AppSearchEmail} or {@code null} if it's not been set yet. */ @Nullable public String getBody() { @@ -169,7 +163,8 @@ public class AppSearchEmail extends GenericDocument { public static class Builder extends GenericDocument.Builder { /** - * Create a new {@link AppSearchEmail.Builder} + * Creates a new {@link AppSearchEmail.Builder} + * * @param uri The Uri of the Email. */ public Builder(@NonNull String uri) { @@ -177,56 +172,56 @@ public class AppSearchEmail extends GenericDocument { } /** - * Set the from address of {@link AppSearchEmail} + * Sets the from address of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setFrom(@NonNull String from) { - setProperty(KEY_FROM, from); + setPropertyString(KEY_FROM, from); return this; } /** - * Set the destination address of {@link AppSearchEmail} + * Sets the destination address of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setTo(@NonNull String... to) { - setProperty(KEY_TO, to); + setPropertyString(KEY_TO, to); return this; } /** - * Set the CC list of {@link AppSearchEmail} + * Sets the CC list of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setCc(@NonNull String... cc) { - setProperty(KEY_CC, cc); + setPropertyString(KEY_CC, cc); return this; } /** - * Set the BCC list of {@link AppSearchEmail} + * Sets the BCC list of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setBcc(@NonNull String... bcc) { - setProperty(KEY_BCC, bcc); + setPropertyString(KEY_BCC, bcc); return this; } /** - * Set the subject of {@link AppSearchEmail} + * Sets the subject of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setSubject(@NonNull String subject) { - setProperty(KEY_SUBJECT, subject); + setPropertyString(KEY_SUBJECT, subject); return this; } /** - * Set the body of {@link AppSearchEmail} + * Sets the body of {@link AppSearchEmail} */ @NonNull public AppSearchEmail.Builder setBody(@NonNull String body) { - setProperty(KEY_BODY, body); + setPropertyString(KEY_BODY, body); return this; } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java index 90e4df68f734f..3933726d67296 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java @@ -16,10 +16,12 @@ 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.app.appsearch.exceptions.IllegalSchemaException; import android.util.ArraySet; @@ -28,6 +30,8 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Set; /** @@ -39,13 +43,8 @@ import java.util.Set; * @hide */ public final class AppSearchSchema { - /** @hide */ - - public static final String SCHEMA_TYPE_FIELD = "schemaType"; - - /** @hide */ - - public static final String PROPERTIES_FIELD = "properties"; + private static final String SCHEMA_TYPE_FIELD = "schemaType"; + private static final String PROPERTIES_FIELD = "properties"; private final Bundle mBundle; @@ -71,10 +70,35 @@ public final class AppSearchSchema { return mBundle.toString(); } + /** Returns the name of this schema type, e.g. Email. */ + @NonNull + public String getSchemaTypeName() { + return mBundle.getString(SCHEMA_TYPE_FIELD, ""); + } + + /** + * Returns the list of {@link PropertyConfig}s that are part of this schema. + * + *

This method creates a new list when called. + */ + @NonNull + public List getProperties() { + ArrayList propertyBundles = + mBundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD); + if (propertyBundles.isEmpty()) { + return Collections.emptyList(); + } + List ret = new ArrayList<>(propertyBundles.size()); + for (int i = 0; i < propertyBundles.size(); i++) { + ret.add(new PropertyConfig(propertyBundles.get(i))); + } + return ret; + } + /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { private final String mTypeName; - private final ArrayList mProperties = new ArrayList<>(); + private final ArrayList mPropertyBundles = new ArrayList<>(); private final Set mPropertyNames = new ArraySet<>(); private boolean mBuilt = false; @@ -85,15 +109,19 @@ public final class AppSearchSchema { } /** Adds a property to the given type. */ + // TODO(b/171360120): MissingGetterMatchingBuilder expects a method called getPropertys, but + // we provide the (correct) method getProperties. Once the bug referenced in this TODO is + // fixed, remove this SuppressLint. + @SuppressLint("MissingGetterMatchingBuilder") @NonNull public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(propertyConfig); - if (!mPropertyNames.add(propertyConfig.mName)) { - throw new IllegalSchemaException( - "Property defined more than once: " + propertyConfig.mName); + String name = propertyConfig.getName(); + if (!mPropertyNames.add(name)) { + throw new IllegalSchemaException("Property defined more than once: " + name); } - mProperties.add(propertyConfig.mBundle); + mPropertyBundles.add(propertyConfig.mBundle); return this; } @@ -107,7 +135,7 @@ public final class AppSearchSchema { Preconditions.checkState(!mBuilt, "Builder has already been used"); Bundle bundle = new Bundle(); bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName); - bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mProperties); + bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles); mBuilt = true; return new AppSearchSchema(bundle); } @@ -120,29 +148,12 @@ public final class AppSearchSchema { * a property. */ public static final class PropertyConfig { - /** @hide */ - - public static final String NAME_FIELD = "name"; - - /** @hide */ - - public static final String DATA_TYPE_FIELD = "dataType"; - - /** @hide */ - - public static final String SCHEMA_TYPE_FIELD = "schemaType"; - - /** @hide */ - - public static final String CARDINALITY_FIELD = "cardinality"; - - /** @hide */ - - public static final String INDEXING_TYPE_FIELD = "indexingType"; - - /** @hide */ - - public static final String TOKENIZER_TYPE_FIELD = "tokenizerType"; + private static final String NAME_FIELD = "name"; + private static final String DATA_TYPE_FIELD = "dataType"; + private static final String SCHEMA_TYPE_FIELD = "schemaType"; + private static final String CARDINALITY_FIELD = "cardinality"; + private static final String INDEXING_TYPE_FIELD = "indexingType"; + private static final String TOKENIZER_TYPE_FIELD = "tokenizerType"; /** * Physical data-types of the contents of the property. @@ -259,11 +270,9 @@ public final class AppSearchSchema { /** Tokenization for plain text. */ public static final int TOKENIZER_TYPE_PLAIN = 1; - final String mName; final Bundle mBundle; - PropertyConfig(@NonNull String name, @NonNull Bundle bundle) { - mName = Preconditions.checkNotNull(name); + PropertyConfig(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); } @@ -272,6 +281,45 @@ public final class AppSearchSchema { return mBundle.toString(); } + /** Returns the name of this property. */ + @NonNull + public String getName() { + return mBundle.getString(NAME_FIELD, ""); + } + + /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */ + public @DataType int getDataType() { + return mBundle.getInt(DATA_TYPE_FIELD, -1); + } + + /** + * Returns the logical schema-type of the contents of this property. + * + *

Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. + * Otherwise, it is {@code null}. + */ + @Nullable + public String getSchemaType() { + return mBundle.getString(SCHEMA_TYPE_FIELD); + } + + /** + * Returns the cardinality of the property (whether it is optional, required or repeated). + */ + public @Cardinality int getCardinality() { + return mBundle.getInt(CARDINALITY_FIELD, -1); + } + + /** Returns how the property is indexed. */ + public @IndexingType int getIndexingType() { + return mBundle.getInt(INDEXING_TYPE_FIELD); + } + + /** Returns how this property is tokenized (split into words). */ + public @TokenizerType int getTokenizerType() { + return mBundle.getInt(TOKENIZER_TYPE_FIELD); + } + /** * Builder for {@link PropertyConfig}. * @@ -286,13 +334,11 @@ public final class AppSearchSchema { * is also required. */ public static final class Builder { - private final String mName; private final Bundle mBundle = new Bundle(); private boolean mBuilt = false; /** Creates a new {@link PropertyConfig.Builder}. */ public Builder(@NonNull String propertyName) { - mName = Preconditions.checkNotNull(propertyName); mBundle.putString(NAME_FIELD, propertyName); } @@ -386,7 +432,7 @@ public final class AppSearchSchema { throw new IllegalSchemaException("Missing field: cardinality"); } mBuilt = true; - return new PropertyConfig(mName, mBundle); + return new PropertyConfig(mBundle); } } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java index 9fe2c67d00f27..48d3ac09d9979 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java @@ -30,6 +30,7 @@ import com.android.internal.util.Preconditions; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Set; /** @@ -65,20 +66,14 @@ public class GenericDocument { /** The default time-to-live in millisecond of a document, which is infinity. */ private static final long DEFAULT_TTL_MILLIS = 0L; - /** @hide */ - - public static final String PROPERTIES_FIELD = "properties"; - - /** @hide */ - - public static final String BYTE_ARRAY_FIELD = "byteArray"; - - static final String SCHEMA_TYPE_FIELD = "schemaType"; - static final String URI_FIELD = "uri"; - static final String SCORE_FIELD = "score"; - static final String TTL_MILLIS_FIELD = "ttlMillis"; - static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis"; - static final String NAMESPACE_FIELD = "namespace"; + private static final String PROPERTIES_FIELD = "properties"; + private static final String BYTE_ARRAY_FIELD = "byteArray"; + private static final String SCHEMA_TYPE_FIELD = "schemaType"; + private static final String URI_FIELD = "uri"; + private static final String SCORE_FIELD = "score"; + private static final String TTL_MILLIS_FIELD = "ttlMillis"; + private static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis"; + private static final String NAMESPACE_FIELD = "namespace"; /** * The maximum number of indexed properties a document can have. @@ -190,6 +185,12 @@ public class GenericDocument { return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE); } + /** Returns the names of all properties defined in this document. */ + @NonNull + public Set getPropertyNames() { + return Collections.unmodifiableSet(mProperties.keySet()); + } + /** * Retrieves a {@link String} value by key. * @@ -437,8 +438,6 @@ public class GenericDocument { @Override public boolean equals(@Nullable Object other) { - // Check only proto's equality is sufficient here since all properties in - // mProperties are ordered by keys and stored in proto. if (this == other) { return true; } @@ -450,8 +449,8 @@ public class GenericDocument { } /** - * Deeply checks two bundle is equally or not. - *

Two bundle will be considered equally if they contains same content. + * Deeply checks two bundles are equally or not. + *

Two bundles will be considered equally if they contain same content. */ @SuppressWarnings("unchecked") private static boolean bundleEquals(Bundle one, Bundle two) { @@ -472,7 +471,7 @@ public class GenericDocument { return false; } else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) { // If we call bundle.get(key) when the 'key' doesn't actually exist in the - // bundle, we'll get back a null. So make sure that both values are null and + // bundle, we'll get back a null. So make sure that both values are null and // both keys exist in the bundle. return false; } else if (valueOne instanceof boolean[]) { @@ -538,8 +537,8 @@ public class GenericDocument { /** * Calculates the hash code for a bundle. - *

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

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) { @@ -648,8 +647,11 @@ public class GenericDocument { /** * The builder class for {@link GenericDocument}. * - * @param Type of subclass who extend this. + * @param Type of subclass who extends this. */ + // This builder is specifically designed to be extended by classes deriving from + // GenericDocument. + @SuppressLint("StaticFinalBuilder") public static class Builder { private final Bundle mProperties = new Bundle(); @@ -662,12 +664,11 @@ public class GenericDocument { * * @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 {@code AppSearchManager#setSchema} prior + * {@code schemaType} must be defined using {@link AppSearchSession#setSchema} prior * to inserting a document of this {@code schemaType} into the AppSearch index using - * {@code AppSearchManager#putDocuments}. Otherwise, the document will be - * rejected by {@code AppSearchManager#putDocuments}. + * {@link AppSearchSession#putDocuments}. Otherwise, the document will be + * rejected by {@link AppSearchSession#putDocuments}. */ - //TODO(b/157082794) Linkify AppSearchManager once that API is public. @SuppressWarnings("unchecked") public Builder(@NonNull String uri, @NonNull String schemaType) { Preconditions.checkNotNull(uri); @@ -685,9 +686,12 @@ public class GenericDocument { } /** - * Set the app-defined namespace this Document resides in. No special values are - * reserved or understood by the infrastructure. URIs are unique within a namespace. The - * number of namespaces per app should be kept small for efficiency reasons. + * 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. + * + *

The number of namespaces per app should be kept small for efficiency reasons. */ @NonNull public BuilderType setNamespace(@NonNull String namespace) { @@ -714,7 +718,7 @@ public class GenericDocument { } /** - * Set the creation timestamp in milliseconds of the {@link GenericDocument}. Should be + * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds. Should be * set using a value obtained from the {@link System#currentTimeMillis()} time base. */ @NonNull @@ -726,7 +730,7 @@ public class GenericDocument { } /** - * Set the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds. + * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds. * *

After this many milliseconds since the {@link #setCreationTimestampMillis creation * timestamp}, the document is deleted. @@ -752,7 +756,7 @@ public class GenericDocument { * @param values The {@code String} values of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull String... values) { + public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); @@ -768,7 +772,7 @@ public class GenericDocument { * @param values The {@code boolean} values of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull boolean... values) { + public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); @@ -784,7 +788,7 @@ public class GenericDocument { * @param values The {@code long} values of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull long... values) { + public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); @@ -800,7 +804,7 @@ public class GenericDocument { * @param values The {@code double} values of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull double... values) { + public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); @@ -815,7 +819,7 @@ public class GenericDocument { * @param values The {@code byte[]} of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull byte[]... values) { + public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); @@ -831,7 +835,8 @@ public class GenericDocument { * @param values The {@link GenericDocument} values of the property. */ @NonNull - public BuilderType setProperty(@NonNull String key, @NonNull GenericDocument... values) { + public BuilderType setPropertyDocument( + @NonNull String key, @NonNull GenericDocument... values) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(key); Preconditions.checkNotNull(values); diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java index 3c0e746f92ab3..e1e0eda7558c6 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java @@ -17,12 +17,12 @@ package android.app.appsearch; import android.annotation.NonNull; - import android.util.ArraySet; import com.android.internal.util.Preconditions; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Set; /** @@ -40,18 +40,16 @@ public final class GetByUriRequest { mUris = uris; } - /** @hide */ - + /** Returns the namespace to get documents from. */ @NonNull public String getNamespace() { return mNamespace; } - /** @hide */ - + /** Returns the URIs to get from the namespace. */ @NonNull public Set getUris() { - return mUris; + return Collections.unmodifiableSet(mUris); } /** Builder for {@link GetByUriRequest} objects. */ @@ -75,14 +73,14 @@ public final class GetByUriRequest { /** Adds one or more URIs to the request. */ @NonNull - public Builder addUris(@NonNull String... uris) { + public Builder addUri(@NonNull String... uris) { Preconditions.checkNotNull(uris); - return addUris(Arrays.asList(uris)); + return addUri(Arrays.asList(uris)); } /** Adds one or more URIs to the request. */ @NonNull - public Builder addUris(@NonNull Collection uris) { + public Builder addUri(@NonNull Collection uris) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(uris); mUris.addAll(uris); diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java index 7e97542c6f02c..1f90bc184f6f8 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java @@ -16,13 +16,16 @@ package android.app.appsearch; -import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.annotation.NonNull; +import android.app.appsearch.exceptions.AppSearchException; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -38,11 +41,10 @@ public final class PutDocumentsRequest { mDocuments = documents; } - /** @hide */ - + /** Returns the documents that are part of this request. */ @NonNull public List getDocuments() { - return mDocuments; + return Collections.unmodifiableList(mDocuments); } /** Builder for {@link PutDocumentsRequest} objects. */ @@ -51,6 +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() @NonNull public Builder addGenericDocument(@NonNull GenericDocument... documents) { Preconditions.checkNotNull(documents); @@ -58,6 +61,7 @@ public final class PutDocumentsRequest { } /** Adds one or more documents to the request. */ + @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 a047041a3082e..486857fba1dea 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java @@ -17,12 +17,12 @@ package android.app.appsearch; import android.annotation.NonNull; - import android.util.ArraySet; import com.android.internal.util.Preconditions; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Set; /** @@ -40,18 +40,16 @@ public final class RemoveByUriRequest { mUris = uris; } - /** @hide */ - + /** Returns the namespace to remove documents from. */ @NonNull public String getNamespace() { return mNamespace; } - /** @hide */ - + /** Returns the URIs to remove from the namespace. */ @NonNull public Set getUris() { - return mUris; + return Collections.unmodifiableSet(mUris); } /** Builder for {@link RemoveByUriRequest} objects. */ @@ -75,14 +73,14 @@ public final class RemoveByUriRequest { /** Adds one or more URIs to the request. */ @NonNull - public Builder addUris(@NonNull String... uris) { + public Builder addUri(@NonNull String... uris) { Preconditions.checkNotNull(uris); - return addUris(Arrays.asList(uris)); + return addUri(Arrays.asList(uris)); } /** Adds one or more URIs to the request. */ @NonNull - public Builder addUris(@NonNull Collection uris) { + public Builder addUri(@NonNull Collection uris) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(uris); mUris.addAll(uris); diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java index 758280bbc3227..99cb2f16ca4d7 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java @@ -49,19 +49,22 @@ public final class SearchResult { @NonNull private final Bundle mDocumentBundle; + /** Cache of the inflated document. Comes from inflating mDocumentBundle at first use. */ @Nullable private GenericDocument mDocument; - @Nullable - private final List mMatchBundles; - /** - * Contains a list of Snippets that matched the request. Only populated when requested in - * both {@link SearchSpec.Builder#setSnippetCount(int)} - * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}. + * Contains a list of MatchInfo bundles that matched the request. + * + * Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and + * {@link SearchSpec.Builder#setSnippetCountPerProperty}. * * @see #getMatches() */ + @NonNull + private final List mMatchBundles; + + /** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */ @Nullable private List mMatches; @@ -70,7 +73,7 @@ public final class SearchResult { public SearchResult(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); mDocumentBundle = Preconditions.checkNotNull(bundle.getBundle(DOCUMENT_FIELD)); - mMatchBundles = bundle.getParcelableArrayList(MATCHES_FIELD); + mMatchBundles = Preconditions.checkNotNull(bundle.getParcelableArrayList(MATCHES_FIELD)); } /** @hide */ @@ -93,19 +96,16 @@ public final class SearchResult { } /** - * Contains a list of Snippets that matched the request. Only populated when requested in - * both {@link SearchSpec.Builder#setSnippetCount(int)} - * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}. + * Contains a list of Snippets that matched the request. * - * @return List of matches based on {@link SearchSpec}, if snippeting is disabled and this - * method is called it will return {@code null}. Users can also restrict snippet population - * using {@link SearchSpec.Builder#setSnippetCount} and - * {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}, for all results after that - * value this method will return {@code null}. + * @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. */ - @Nullable + @NonNull public List getMatches() { - if (mMatchBundles != null && mMatches == null) { + if (mMatches == null) { mMatches = new ArrayList<>(mMatchBundles.size()); for (int i = 0; i < mMatchBundles.size(); i++) { MatchInfo matchInfo = new MatchInfo(getDocument(), mMatchBundles.get(i)); @@ -119,8 +119,8 @@ public final class SearchResult { * Snippet: It refers to a substring of text from the content of document that is returned as a * part of search result. * 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. + * {@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: diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java index c8719059fa8c0..15acf103f2e6b 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java @@ -16,16 +16,23 @@ package android.app.appsearch; +import android.annotation.SuppressLint; import android.os.Bundle; import android.annotation.IntDef; import android.annotation.NonNull; +import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.IllegalSearchSpecException; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; /** * This class represents the specification logic for AppSearch. It can be used to set the type of @@ -34,69 +41,26 @@ import java.lang.annotation.RetentionPolicy; */ // TODO(sidchhabra) : AddResultSpec fields for Snippets etc. public final class SearchSpec { - /** @hide */ - - public static final String TERM_MATCH_TYPE_FIELD = "termMatchType"; - - /** @hide */ - - public static final String SCHEMA_TYPES_FIELD = "schemaType"; - - /** @hide */ - - public static final String NAMESPACE_FIELD = "namespace"; - - /** @hide */ - - public static final String NUM_PER_PAGE_FIELD = "numPerPage"; - - /** @hide */ - - public static final String RANKING_STRATEGY_FIELD = "rankingStrategy"; - - /** @hide */ - - public static final String ORDER_FIELD = "order"; - - /** @hide */ - - public static final String SNIPPET_COUNT_FIELD = "snippetCount"; - - /** @hide */ - - public static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty"; - - /** @hide */ - - public static final String MAX_SNIPPET_FIELD = "maxSnippet"; + static final String TERM_MATCH_TYPE_FIELD = "termMatchType"; + static final String SCHEMA_TYPE_FIELD = "schemaType"; + static final String NAMESPACE_FIELD = "namespace"; + static final String NUM_PER_PAGE_FIELD = "numPerPage"; + static final String RANKING_STRATEGY_FIELD = "rankingStrategy"; + static final String ORDER_FIELD = "order"; + static final String SNIPPET_COUNT_FIELD = "snippetCount"; + static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty"; + 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 might be flag controlled. private static final int MAX_NUM_PER_PAGE = 10_000; private static final int MAX_SNIPPET_COUNT = 10_000; private static final int MAX_SNIPPET_PER_PROPERTY_COUNT = 10_000; private static final int MAX_SNIPPET_SIZE_LIMIT = 10_000; - private final Bundle mBundle; - - /** @hide */ - - public SearchSpec(@NonNull Bundle bundle) { - Preconditions.checkNotNull(bundle); - mBundle = bundle; - } - - /** - * Returns the {@link Bundle} populated by this builder. - * @hide - */ - @NonNull - public Bundle getBundle() { - return mBundle; - } - /** * Term Match Type for the query. * @hide @@ -108,7 +72,7 @@ public final class SearchSpec { TERM_MATCH_PREFIX }) @Retention(RetentionPolicy.SOURCE) - public @interface TermMatchCode {} + public @interface TermMatch {} /** * Query terms will only match exact tokens in the index. @@ -126,14 +90,14 @@ public final class SearchSpec { * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in - // {@link ScoringSpecProto.RankingStrategy.Code } + // {@link ScoringSpecProto.RankingStrategy.Code} @IntDef(value = { RANKING_STRATEGY_NONE, RANKING_STRATEGY_DOCUMENT_SCORE, RANKING_STRATEGY_CREATION_TIMESTAMP }) @Retention(RetentionPolicy.SOURCE) - public @interface RankingStrategyCode {} + public @interface RankingStrategy {} /** No Ranking, results are returned in arbitrary order.*/ public static final int RANKING_STRATEGY_NONE = 0; @@ -147,23 +111,109 @@ public final class SearchSpec { * @hide */ // NOTE: The integer values of these constants must match the proto enum constants in - // {@link ScoringSpecProto.Order.Code } + // {@link ScoringSpecProto.Order.Code} @IntDef(value = { ORDER_DESCENDING, ORDER_ASCENDING }) @Retention(RetentionPolicy.SOURCE) - public @interface OrderCode {} + public @interface Order {} /** Search results will be returned in a descending order. */ public static final int ORDER_DESCENDING = 0; /** Search results will be returned in an ascending order. */ public static final int ORDER_ASCENDING = 1; + private final Bundle mBundle; + + /** @hide */ + + public SearchSpec(@NonNull Bundle bundle) { + Preconditions.checkNotNull(bundle); + mBundle = bundle; + } + + /** + * Returns the {@link Bundle} populated by this builder. + * @hide + */ + + @NonNull + public Bundle getBundle() { + return mBundle; + } + + /** Returns how the query terms should match terms in the index. */ + public @TermMatch int getTermMatch() { + return mBundle.getInt(TERM_MATCH_TYPE_FIELD, -1); + } + + /** + * Returns the list of schema types to search for. + * + *

If empty, the query will search over all schema types. + */ + @NonNull + public List getSchemas() { + List schemas = mBundle.getStringArrayList(SCHEMA_TYPE_FIELD); + if (schemas == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(schemas); + } + + /** + * Returns the list of namespaces to search for. + * + *

If empty, the query will search over all namespaces. + */ + @NonNull + public List getNamespaces() { + List namespaces = mBundle.getStringArrayList(NAMESPACE_FIELD); + if (namespaces == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(namespaces); + } + + /** Returns the number of results per page in the returned object. */ + public int getNumPerPage() { + return mBundle.getInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE); + } + + /** Returns the ranking strategy. */ + public @RankingStrategy int getRankingStrategy() { + return mBundle.getInt(RANKING_STRATEGY_FIELD); + } + + /** Returns the order of returned search results (descending or ascending). */ + public @Order int getOrder() { + return mBundle.getInt(ORDER_FIELD); + } + + /** Returns how many documents to generate snippets for. */ + public int getSnippetCount() { + return mBundle.getInt(SNIPPET_COUNT_FIELD); + } + + /** + * Returns how many matches for each property of a matching document to generate snippets for. + */ + public int getSnippetCountPerProperty() { + return mBundle.getInt(SNIPPET_COUNT_PER_PROPERTY_FIELD); + } + + /** Returns the maximum size of a snippet in characters. */ + public int getMaxSnippetSize() { + return mBundle.getInt(MAX_SNIPPET_FIELD); + } + /** Builder for {@link SearchSpec objects}. */ public static final class Builder { private final Bundle mBundle; + private final ArrayList mSchemaTypes = new ArrayList<>(); + private final ArrayList mNamespaces = new ArrayList<>(); private boolean mBuilt = false; /** Creates a new {@link SearchSpec.Builder}. */ @@ -176,7 +226,7 @@ public final class SearchSpec { * Indicates how the query terms should match {@code TermMatchCode} in the index. */ @NonNull - public Builder setTermMatch(@TermMatchCode int termMatchTypeCode) { + 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"); @@ -187,13 +237,27 @@ public final class SearchSpec { /** * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that * have the specified schema types. + * *

If unset, the query will search over all schema types. */ @NonNull - public Builder setSchemaTypes(@NonNull String... schemaTypes) { + public Builder addSchema(@NonNull String... schemaTypes) { Preconditions.checkNotNull(schemaTypes); Preconditions.checkState(!mBuilt, "Builder has already been used"); - mBundle.putStringArray(SCHEMA_TYPES_FIELD, schemaTypes); + return addSchema(Arrays.asList(schemaTypes)); + } + + /** + * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that + * have the specified schema types. + * + *

If unset, the query will search over all schema types. + */ + @NonNull + public Builder addSchema(@NonNull Collection schemaTypes) { + Preconditions.checkNotNull(schemaTypes); + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mSchemaTypes.addAll(schemaTypes); return this; } @@ -203,10 +267,22 @@ public final class SearchSpec { *

If unset, the query will search over all namespaces. */ @NonNull - public Builder setNamespaces(@NonNull String... namespaces) { + public Builder addNamespace(@NonNull String... namespaces) { Preconditions.checkNotNull(namespaces); Preconditions.checkState(!mBuilt, "Builder has already been used"); - mBundle.putStringArray(NAMESPACE_FIELD, namespaces); + return addNamespace(Arrays.asList(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 + public Builder addNamespace(@NonNull Collection namespaces) { + Preconditions.checkNotNull(namespaces); + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mNamespaces.addAll(namespaces); return this; } @@ -224,7 +300,7 @@ public final class SearchSpec { /** Sets ranking strategy for AppSearch results.*/ @NonNull - public Builder setRankingStrategy(@RankingStrategyCode int rankingStrategy) { + 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"); @@ -238,7 +314,7 @@ public final class SearchSpec { *

This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}. */ @NonNull - public Builder setOrder(@OrderCode int order) { + public Builder setOrder(@Order int order) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkArgumentInRange(order, ORDER_DESCENDING, ORDER_ASCENDING, "Result ranking order"); @@ -264,11 +340,12 @@ public final class SearchSpec { } /** - * Only the first {@code matchesCountPerProperty} matches for a every property of - * {@link GenericDocument} will contain snippet information. + * Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty} + * snippets for a every 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. * *

The value should be set in range[0, 10k]. */ @@ -286,10 +363,13 @@ public final class SearchSpec { * {@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. + * *

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

The value should be in range[0, 10k]. */ @NonNull @@ -312,6 +392,8 @@ public final class SearchSpec { if (!mBundle.containsKey(TERM_MATCH_TYPE_FIELD)) { throw new IllegalSearchSpecException("Missing termMatchType field."); } + mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces); + mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes); mBuilt = true; return new SearchSpec(mBundle); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java index b2e9d469764d5..f2c81564908c0 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java @@ -16,13 +16,17 @@ package android.app.appsearch; -import android.annotation.NonNull; -import android.util.ArraySet; +import android.annotation.SuppressLint; +import android.annotation.NonNull; +import android.app.appsearch.exceptions.AppSearchException; +import android.util.ArraySet; import com.android.internal.util.Preconditions; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Set; /** @@ -40,15 +44,13 @@ public final class SetSchemaRequest { mForceOverride = forceOverride; } - /** @hide */ - + /** Returns the schemas that are part of this request. */ @NonNull public Set getSchemas() { return mSchemas; } - /** @hide */ - + /** Returns whether this request will force the schema to be overridden. */ public boolean isForceOverride() { return mForceOverride; } 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 d490469be3d60..15d0992cd0816 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java +++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java @@ -54,6 +54,7 @@ public class AppSearchException extends Exception { mResultCode = resultCode; } + /** Returns the result code this exception was constructed with. */ public @AppSearchResult.ResultCode int getResultCode() { return mResultCode; } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 7cd6ee24cb20f..f2830e5b8e6d3 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -33,11 +33,11 @@ import android.os.UserHandle; import com.android.internal.infra.AndroidFuture; import com.android.internal.util.Preconditions; import com.android.server.SystemService; -import com.android.server.appsearch.external.localbackend.AppSearchImpl; -import com.android.server.appsearch.external.localbackend.converter.GenericDocumentToProtoConverter; -import com.android.server.appsearch.external.localbackend.converter.SchemaToProtoConverter; -import com.android.server.appsearch.external.localbackend.converter.SearchResultToProtoConverter; -import com.android.server.appsearch.external.localbackend.converter.SearchSpecToProtoConverter; +import com.android.server.appsearch.external.localstorage.AppSearchImpl; +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 com.google.android.icing.proto.DocumentProto; import com.google.android.icing.proto.SchemaProto; @@ -46,6 +46,7 @@ import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SearchSpecProto; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -193,7 +194,12 @@ public class AppSearchManagerService extends SystemService { SearchSpecToProtoConverter.toResultSpecProto(searchSpec), SearchSpecToProtoConverter.toScoringSpecProto(searchSpec)); List searchResultList = - SearchResultToProtoConverter.convert(searchResultProto); + new ArrayList<>(searchResultProto.getResultsCount()); + for (int i = 0; i < searchResultProto.getResultsCount(); i++) { + SearchResult result = SearchResultToProtoConverter.convertSearchResult( + searchResultProto.getResults(i)); + searchResultList.add(result); + } SearchResults searchResults = new SearchResults(searchResultList, searchResultProto.getNextPageToken()); callback.complete(AppSearchResult.newSuccessfulResult(searchResults)); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java index 60f7005a7c0a8..2871eb622f114 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java @@ -24,7 +24,7 @@ import android.os.Environment; import android.os.storage.StorageManager; import android.util.SparseArray; -import com.android.server.appsearch.external.localbackend.AppSearchImpl; +import com.android.server.appsearch.external.localstorage.AppSearchImpl; import java.io.File; diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java similarity index 99% rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java index 642378d992ace..b1a79f84714dc 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend; +package com.android.server.appsearch.external.localstorage; import android.util.Log; diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java similarity index 69% rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java index fdeb90dc9b0e0..60684f09a2022 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; - -import android.os.Bundle; +package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; @@ -43,7 +41,6 @@ public final class GenericDocumentToProtoConverter { @SuppressWarnings("unchecked") public static DocumentProto convert(@NonNull GenericDocument document) { Preconditions.checkNotNull(document); - Bundle properties = document.getBundle().getBundle(GenericDocument.PROPERTIES_FIELD); DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder(); mProtoBuilder.setUri(document.getUri()) .setSchema(document.getSchemaType()) @@ -51,42 +48,45 @@ public final class GenericDocumentToProtoConverter { .setScore(document.getScore()) .setTtlMs(document.getTtlMillis()) .setCreationTimestampMs(document.getCreationTimestampMillis()); - ArrayList keys = new ArrayList<>(properties.keySet()); + ArrayList keys = new ArrayList<>(document.getPropertyNames()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { String name = keys.get(i); - Object values = properties.get(name); PropertyProto.Builder propertyProto = PropertyProto.newBuilder().setName(name); - if (values instanceof boolean[]) { - for (boolean value : (boolean[]) values) { - propertyProto.addBooleanValues(value); + String[] stringValues = document.getPropertyStringArray(name); + long[] longValues = document.getPropertyLongArray(name); + double[] doubleValues = document.getPropertyDoubleArray(name); + boolean[] booleanValues = document.getPropertyBooleanArray(name); + byte[][] bytesValues = document.getPropertyBytesArray(name); + GenericDocument[] documentValues = document.getPropertyDocumentArray(name); + if (stringValues != null) { + for (int j = 0; j < stringValues.length; j++) { + propertyProto.addStringValues(stringValues[j]); } - } else if (values instanceof long[]) { - for (long value : (long[]) values) { - propertyProto.addInt64Values(value); + } else if (longValues != null) { + for (int j = 0; j < longValues.length; j++) { + propertyProto.addInt64Values(longValues[j]); } - } else if (values instanceof double[]) { - for (double value : (double[]) values) { - propertyProto.addDoubleValues(value); + } else if (doubleValues != null) { + for (int j = 0; j < doubleValues.length; j++) { + propertyProto.addDoubleValues(doubleValues[j]); } - } else if (values instanceof String[]) { - for (String value : (String[]) values) { - propertyProto.addStringValues(value); + } else if (booleanValues != null) { + for (int j = 0; j < booleanValues.length; j++) { + propertyProto.addBooleanValues(booleanValues[j]); } - } else if (values instanceof ArrayList) { - for (Bundle bundle : (ArrayList) values) { - byte[] value = bundle.getByteArray(GenericDocument.BYTE_ARRAY_FIELD); - propertyProto.addBytesValues(ByteString.copyFrom(value)); + } else if (bytesValues != null) { + for (int j = 0; j < bytesValues.length; j++) { + propertyProto.addBytesValues(ByteString.copyFrom(bytesValues[j])); } - } else if (values instanceof Bundle[]) { - for (Bundle bundle : (Bundle[]) values) { - GenericDocument value = new GenericDocument(bundle); - propertyProto.addDocumentValues(convert(value)); + } else if (documentValues != null) { + for (int j = 0; j < documentValues.length; j++) { + DocumentProto proto = convert(documentValues[j]); + propertyProto.addDocumentValues(proto); } } else { throw new IllegalStateException( - "Property \"" + name + "\" has unsupported value type \"" - + values.getClass().getSimpleName() + "\""); + "Property \"" + name + "\" has unsupported value type"); } mProtoBuilder.addProperties(propertyProto); } @@ -107,42 +107,42 @@ public final class GenericDocumentToProtoConverter { for (int i = 0; i < proto.getPropertiesCount(); i++) { PropertyProto property = proto.getProperties(i); String name = property.getName(); - if (property.getBooleanValuesCount() > 0) { - boolean[] values = new boolean[property.getBooleanValuesCount()]; + if (property.getStringValuesCount() > 0) { + String[] values = new String[property.getStringValuesCount()]; for (int j = 0; j < values.length; j++) { - values[j] = property.getBooleanValues(j); + values[j] = property.getStringValues(j); } - documentBuilder.setProperty(name, values); + documentBuilder.setPropertyString(name, values); } else if (property.getInt64ValuesCount() > 0) { long[] values = new long[property.getInt64ValuesCount()]; for (int j = 0; j < values.length; j++) { values[j] = property.getInt64Values(j); } - documentBuilder.setProperty(name, values); + documentBuilder.setPropertyLong(name, values); } else if (property.getDoubleValuesCount() > 0) { double[] values = new double[property.getDoubleValuesCount()]; for (int j = 0; j < values.length; j++) { values[j] = property.getDoubleValues(j); } - documentBuilder.setProperty(name, values); - } else if (property.getStringValuesCount() > 0) { - String[] values = new String[property.getStringValuesCount()]; + documentBuilder.setPropertyDouble(name, values); + } else if (property.getBooleanValuesCount() > 0) { + boolean[] values = new boolean[property.getBooleanValuesCount()]; for (int j = 0; j < values.length; j++) { - values[j] = property.getStringValues(j); + values[j] = property.getBooleanValues(j); } - documentBuilder.setProperty(name, values); + documentBuilder.setPropertyBoolean(name, values); } else if (property.getBytesValuesCount() > 0) { byte[][] values = new byte[property.getBytesValuesCount()][]; for (int j = 0; j < values.length; j++) { values[j] = property.getBytesValues(j).toByteArray(); } - documentBuilder.setProperty(name, values); + documentBuilder.setPropertyBytes(name, values); } else if (property.getDocumentValuesCount() > 0) { GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()]; for (int j = 0; j < values.length; j++) { values[j] = convert(property.getDocumentValues(j)); } - documentBuilder.setProperty(name, values); + documentBuilder.setPropertyDocument(name, values); } else { throw new IllegalStateException("Unknown type of value: " + name); } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java similarity index 73% rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java index ca0d2ee970cb0..403711f29544c 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; - -import android.os.Bundle; +package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; @@ -28,7 +26,7 @@ import com.google.android.icing.proto.PropertyConfigProto; import com.google.android.icing.proto.SchemaTypeConfigProto; import com.google.android.icing.proto.TermMatchType; -import java.util.ArrayList; +import java.util.List; /** * Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}. @@ -45,31 +43,26 @@ public final class SchemaToProtoConverter { @NonNull public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) { Preconditions.checkNotNull(schema); - Bundle bundle = schema.getBundle(); SchemaTypeConfigProto.Builder protoBuilder = - SchemaTypeConfigProto.newBuilder() - .setSchemaType(bundle.getString(AppSearchSchema.SCHEMA_TYPE_FIELD, "")); - ArrayList properties = - bundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD); - if (properties != null) { - for (int i = 0; i < properties.size(); i++) { - PropertyConfigProto propertyProto = convertProperty(properties.get(i)); - protoBuilder.addProperties(propertyProto); - } + SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaTypeName()); + List properties = schema.getProperties(); + for (int i = 0; i < properties.size(); i++) { + PropertyConfigProto propertyProto = convertProperty(properties.get(i)); + protoBuilder.addProperties(propertyProto); } return protoBuilder.build(); } @NonNull - private static PropertyConfigProto convertProperty(@NonNull Bundle bundle) { - Preconditions.checkNotNull(bundle); + private static PropertyConfigProto convertProperty( + @NonNull AppSearchSchema.PropertyConfig property) { + Preconditions.checkNotNull(property); PropertyConfigProto.Builder propertyConfigProto = PropertyConfigProto.newBuilder() - .setPropertyName(bundle.getString(AppSearchSchema.PropertyConfig.NAME_FIELD, "")); + .setPropertyName(property.getName()); IndexingConfig.Builder indexingConfig = IndexingConfig.newBuilder(); // Set dataType - @AppSearchSchema.PropertyConfig.DataType int dataType = - bundle.getInt(AppSearchSchema.PropertyConfig.DATA_TYPE_FIELD); + @AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType(); PropertyConfigProto.DataType.Code dataTypeProto = PropertyConfigProto.DataType.Code.forNumber(dataType); if (dataTypeProto == null) { @@ -78,12 +71,13 @@ public final class SchemaToProtoConverter { propertyConfigProto.setDataType(dataTypeProto); // Set schemaType - propertyConfigProto.setSchemaType( - bundle.getString(AppSearchSchema.PropertyConfig.SCHEMA_TYPE_FIELD, "")); + String schemaType = property.getSchemaType(); + if (schemaType != null) { + propertyConfigProto.setSchemaType(schemaType); + } // Set cardinality - @AppSearchSchema.PropertyConfig.Cardinality int cardinality = - bundle.getInt(AppSearchSchema.PropertyConfig.CARDINALITY_FIELD); + @AppSearchSchema.PropertyConfig.Cardinality int cardinality = property.getCardinality(); PropertyConfigProto.Cardinality.Code cardinalityProto = PropertyConfigProto.Cardinality.Code.forNumber(cardinality); if (cardinalityProto == null) { @@ -92,8 +86,7 @@ public final class SchemaToProtoConverter { propertyConfigProto.setCardinality(cardinalityProto); // Set indexingType - @AppSearchSchema.PropertyConfig.IndexingType int indexingType = - bundle.getInt(AppSearchSchema.PropertyConfig.INDEXING_TYPE_FIELD); + @AppSearchSchema.PropertyConfig.IndexingType int indexingType = property.getIndexingType(); TermMatchType.Code termMatchTypeProto; switch (indexingType) { case AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE: @@ -112,7 +105,7 @@ public final class SchemaToProtoConverter { // Set tokenizerType @AppSearchSchema.PropertyConfig.TokenizerType int tokenizerType = - bundle.getInt(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_FIELD); + property.getTokenizerType(); IndexingConfig.TokenizerType.Code tokenizerTypeProto = IndexingConfig.TokenizerType.Code.forNumber(tokenizerType); if (tokenizerTypeProto == null) { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java similarity index 80% rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java index 524c80dd0609b..9f7c6968e993a 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; +package com.android.server.appsearch.external.localstorage.converter; import android.os.Bundle; @@ -22,43 +22,32 @@ import android.annotation.NonNull; import android.app.appsearch.GenericDocument; import android.app.appsearch.SearchResult; -import android.app.appsearch.SearchResults; import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SnippetMatchProto; import com.google.android.icing.proto.SnippetProto; import java.util.ArrayList; -import java.util.List; /** - * Translates a {@link SearchResultProto} into {@link SearchResults}. + * Translates a {@link SearchResultProto} into {@link SearchResult}s. + * * @hide */ public class SearchResultToProtoConverter { private SearchResultToProtoConverter() {} - /** Translates a {@link SearchResultProto} into a list of {@link SearchResult}. */ - @NonNull - public static List convert(@NonNull SearchResultProto searchResultProto) { - List results = new ArrayList<>(searchResultProto.getResultsCount()); - for (int i = 0; i < searchResultProto.getResultsCount(); i++) { - results.add(convertSearchResult(searchResultProto.getResults(i))); - } - return results; - } - /** Translate a {@link SearchResultProto.ResultProto} into {@link SearchResult}. */ @NonNull - static SearchResult convertSearchResult(@NonNull SearchResultProto.ResultProto proto) { + public static SearchResult convertSearchResult( + @NonNull SearchResultProto.ResultProtoOrBuilder proto) { Bundle bundle = new Bundle(); GenericDocument document = GenericDocumentToProtoConverter.convert(proto.getDocument()); bundle.putBundle(SearchResult.DOCUMENT_FIELD, document.getBundle()); - ArrayList matchList = null; + ArrayList matchList = new ArrayList<>(); if (proto.hasSnippet()) { - matchList = new ArrayList<>(); for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) { SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i); for (int j = 0; j < entry.getSnippetMatchesCount(); j++) { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java similarity index 67% rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java index a5d913a205901..14822dcdc7932 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; - -import android.os.Bundle; +package com.android.server.appsearch.external.localstorage.converter; import android.annotation.NonNull; @@ -28,8 +26,6 @@ import com.google.android.icing.proto.ScoringSpecProto; import com.google.android.icing.proto.SearchSpecProto; import com.google.android.icing.proto.TermMatchType; -import java.util.Arrays; - /** * Translates a {@link SearchSpec} into icing search protos. * @hide @@ -42,25 +38,17 @@ public final class SearchSpecToProtoConverter { @NonNull public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) { Preconditions.checkNotNull(spec); - Bundle bundle = spec.getBundle(); - SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder(); + SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder() + .addAllSchemaTypeFilters(spec.getSchemas()) + .addAllNamespaceFilters(spec.getNamespaces()); - @SearchSpec.TermMatchCode int termMatchCode = - bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD); + @SearchSpec.TermMatch int termMatchCode = spec.getTermMatch(); TermMatchType.Code termMatchCodeProto = TermMatchType.Code.forNumber(termMatchCode); if (termMatchCodeProto == null || termMatchCodeProto.equals(TermMatchType.Code.UNKNOWN)) { throw new IllegalArgumentException("Invalid term match type: " + termMatchCode); } protoBuilder.setTermMatchType(termMatchCodeProto); - String[] schemaTypes = bundle.getStringArray(SearchSpec.SCHEMA_TYPES_FIELD); - if (schemaTypes != null) { - protoBuilder.addAllSchemaTypeFilters(Arrays.asList(schemaTypes)); - } - String[] namespaces = bundle.getStringArray(SearchSpec.NAMESPACE_FIELD); - if (namespaces != null) { - protoBuilder.addAllNamespaceFilters(Arrays.asList(namespaces)); - } return protoBuilder.build(); } @@ -68,27 +56,23 @@ public final class SearchSpecToProtoConverter { @NonNull public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) { Preconditions.checkNotNull(spec); - Bundle bundle = spec.getBundle(); return ResultSpecProto.newBuilder() - .setNumPerPage(bundle.getInt( - SearchSpec.NUM_PER_PAGE_FIELD, SearchSpec.DEFAULT_NUM_PER_PAGE)) - .setSnippetSpec(ResultSpecProto.SnippetSpecProto.newBuilder() - .setNumToSnippet(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)) - .setNumMatchesPerProperty( - bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)) - .setMaxWindowBytes(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD))) + .setNumPerPage(spec.getNumPerPage()) + .setSnippetSpec( + ResultSpecProto.SnippetSpecProto.newBuilder() + .setNumToSnippet(spec.getSnippetCount()) + .setNumMatchesPerProperty(spec.getSnippetCountPerProperty()) + .setMaxWindowBytes(spec.getMaxSnippetSize())) .build(); - } /** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */ @NonNull public static ScoringSpecProto toScoringSpecProto(@NonNull SearchSpec spec) { Preconditions.checkNotNull(spec); - Bundle bundle = spec.getBundle(); ScoringSpecProto.Builder protoBuilder = ScoringSpecProto.newBuilder(); - @SearchSpec.OrderCode int orderCode = bundle.getInt(SearchSpec.ORDER_FIELD); + @SearchSpec.Order int orderCode = spec.getOrder(); ScoringSpecProto.Order.Code orderCodeProto = ScoringSpecProto.Order.Code.forNumber(orderCode); if (orderCodeProto == null) { @@ -96,8 +80,7 @@ public final class SearchSpecToProtoConverter { } protoBuilder.setOrderBy(orderCodeProto); - @SearchSpec.RankingStrategyCode int rankingStrategyCode = - bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD); + @SearchSpec.RankingStrategy int rankingStrategyCode = spec.getRankingStrategy(); ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto = ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode); if (rankingStrategyCodeProto == null) { 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 ac2d4b5c5f7dd..2f2bef8bc5cc3 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 @@ -30,7 +30,7 @@ public class AppSearchEmailTest { // Score and Property are mixed into the middle to make sure DocumentBuilder's // methods can be interleaved with EmailBuilder's methods. .setScore(1) - .setProperty("propertyKey", "propertyValue1", "propertyValue2") + .setPropertyString("propertyKey", "propertyValue1", "propertyValue2") .setSubject("subject") .setBody("EmailBody") .build(); diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java index 1f2c12bca0287..9c29943dbef42 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java @@ -39,22 +39,22 @@ public class GenericDocumentTest { GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) .setTtlMillis(1L) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) + .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) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) + .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()); @@ -64,23 +64,23 @@ public class GenericDocumentTest { public void testDocumentEquals_DifferentOrder() { GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") + .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) - .setProperty("booleanKey1", true, false, true) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("longKey1", 1L, 2L, 3L) + .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()); @@ -90,13 +90,13 @@ public class GenericDocumentTest { public void testDocumentEquals_Failure() { GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("longKey1", 1L, 2L, 3L) + .setPropertyLong("longKey1", 1L, 2L, 3L) .build(); // Create second document with same order but different value. GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("longKey1", 1L, 2L, 4L) // Different + .setPropertyLong("longKey1", 1L, 2L, 4L) // Different .build(); assertThat(document1).isNotEqualTo(document2); assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); @@ -106,13 +106,13 @@ public class GenericDocumentTest { public void testDocumentEquals_Failure_RepeatedFieldOrder() { GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("booleanKey1", true, false, true) + .setPropertyBoolean("booleanKey1", true, false, true) .build(); // Create second document with same order but different value. GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("booleanKey1", true, true, false) // Different + .setPropertyBoolean("booleanKey1", true, true, false) // Different .build(); assertThat(document1).isNotEqualTo(document2); assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); @@ -124,12 +124,12 @@ public class GenericDocumentTest { .setCreationTimestampMillis(5L) .setScore(1) .setTtlMillis(1L) - .setProperty("longKey1", 1L) - .setProperty("doubleKey1", 1.0) - .setProperty("booleanKey1", true) - .setProperty("stringKey1", "test-value1") - .setProperty("byteKey1", sByteArray1) - .setProperty("documentKey1", sDocumentProperties1) + .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); @@ -149,12 +149,12 @@ public class GenericDocumentTest { public void testDocumentGetArrayValues() { GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) + .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"); @@ -176,12 +176,12 @@ public class GenericDocumentTest { public void testDocument_ToString() throws Exception { GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1") .setCreationTimestampMillis(5L) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "String1", "String2", "String3") - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) + .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: } " @@ -219,9 +219,9 @@ public class GenericDocumentTest { public void testDocumentGetValues_DifferentTypes() { GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1") .setScore(1) - .setProperty("longKey1", 1L) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") + .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 @@ -246,6 +246,7 @@ public class GenericDocumentTest { public void testDocumentInvalid() { GenericDocument.Builder builder = new GenericDocument.Builder("uri1", "schemaType1"); expectThrows( - IllegalArgumentException.class, () -> builder.setProperty("test", new boolean[]{})); + IllegalArgumentException.class, + () -> builder.setPropertyBoolean("test", new boolean[]{})); } } diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java deleted file mode 100644 index acbf11ae86696..0000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.appsearch; - -import static org.testng.Assert.expectThrows; - -import org.junit.Test; - -public class SearchResultsTest { - @Test - public void buildSearchSpecWithoutTermMatchType() { - expectThrows(RuntimeException.class, () -> new SearchSpec.Builder() - .setSchemaTypes("testSchemaType") - .build()); - } -} 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 new file mode 100644 index 0000000000000..d4635fdda052c --- /dev/null +++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.appsearch; + +import static com.google.common.truth.Truth.assertThat; + +import static org.testng.Assert.expectThrows; + +import android.os.Bundle; + +import org.junit.Test; + +public class SearchSpecTest { + @Test + public void buildSearchSpecWithoutTermMatchType() { + expectThrows(RuntimeException.class, () -> new SearchSpec.Builder() + .addSchema("testSchemaType") + .build()); + } + + @Test + public void testBuildSearchSpec() { + SearchSpec searchSpec = new SearchSpec.Builder() + .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) + .addNamespace("namespace1", "namespace2") + .addSchema("schemaTypes1", "schemaTypes2") + .setSnippetCount(5) + .setSnippetCountPerProperty(10) + .setMaxSnippetSize(15) + .setNumPerPage(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(); + assertThat(searchSpec.getSchemas()) + .containsExactly("schemaTypes1", "schemaTypes2").inOrder(); + assertThat(searchSpec.getSnippetCount()).isEqualTo(5); + assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10); + assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15); + assertThat(searchSpec.getNumPerPage()).isEqualTo(42); + assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING); + assertThat(searchSpec.getRankingStrategy()) + .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE); + } + + @Test + public void testGetBundle() { + SearchSpec searchSpec = new SearchSpec.Builder() + .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) + .addNamespace("namespace1", "namespace2") + .addSchema("schemaTypes1", "schemaTypes2") + .setSnippetCount(5) + .setSnippetCountPerProperty(10) + .setMaxSnippetSize(15) + .setNumPerPage(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.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); + assertThat(bundle.getInt(SearchSpec.NUM_PER_PAGE_FIELD)).isEqualTo(42); + assertThat(bundle.getInt(SearchSpec.ORDER_FIELD)).isEqualTo(SearchSpec.ORDER_ASCENDING); + assertThat(bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD)) + .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE); + } +} diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java index 2c7c35feface3..d56d0c3c5c8ea 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java @@ -46,12 +46,12 @@ public class CustomerDocumentTest { CustomerDocument customerDocument = new CustomerDocument.Builder("uri1") .setScore(1) .setCreationTimestampMillis(0) - .setProperty("longKey1", 1L, 2L, 3L) - .setProperty("doubleKey1", 1.0, 2.0, 3.0) - .setProperty("booleanKey1", true, false, true) - .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") - .setProperty("byteKey1", sByteArray1, sByteArray2) - .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2) + .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(customerDocument.getUri()).isEqualTo("uri1"); diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java similarity index 99% rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index 081bfb5b2724d..0d0ac6d2794d2 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend; +package com.android.server.appsearch.external.localstorage; import static com.google.common.truth.Truth.assertThat; diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java similarity index 86% rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java index a95290d89b59a..85d4f01f8d41f 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; +package com.android.server.appsearch.external.localstorage.converter; import static com.google.common.truth.Truth.assertThat; @@ -53,13 +53,13 @@ public class GenericDocumentToProtoConverterTest { .setScore(1) .setTtlMillis(1L) .setNamespace("namespace") - .setProperty("longKey1", 1L) - .setProperty("doubleKey1", 1.0) - .setProperty("booleanKey1", true) - .setProperty("stringKey1", "test-value1") - .setProperty("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2) - .setProperty("documentKey1", DOCUMENT_PROPERTIES_1) - .setProperty(GenericDocument.PROPERTIES_FIELD, DOCUMENT_PROPERTIES_2) + .setPropertyLong("longKey1", 1L) + .setPropertyDouble("doubleKey1", 1.0) + .setPropertyBoolean("booleanKey1", true) + .setPropertyString("stringKey1", "test-value1") + .setPropertyBytes("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2) + .setPropertyDocument("documentKey1", DOCUMENT_PROPERTIES_1) + .setPropertyDocument("documentKey2", DOCUMENT_PROPERTIES_2) .build(); // Create the Document proto. Need to sort the property order by key. @@ -87,8 +87,8 @@ public class GenericDocumentToProtoConverterTest { PropertyProto.newBuilder().setName("documentKey1") .addDocumentValues( GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1))); - propertyProtoMap.put(GenericDocument.PROPERTIES_FIELD, - PropertyProto.newBuilder().setName(GenericDocument.PROPERTIES_FIELD) + propertyProtoMap.put("documentKey2", + PropertyProto.newBuilder().setName("documentKey2") .addDocumentValues( GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2))); List sortedKey = new ArrayList<>(propertyProtoMap.keySet()); diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java similarity index 96% rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java index 8b2fd1ce9feff..7336c3c364178 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; +package com.android.server.appsearch.external.localstorage.converter; import static com.google.common.truth.Truth.assertThat; @@ -50,7 +50,6 @@ public class SchemaToProtoConverterTest { .addProperties(PropertyConfigProto.newBuilder() .setPropertyName("subject") .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setSchemaType("") .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) .setIndexingConfig( com.android.server.appsearch.proto.IndexingConfig.newBuilder() @@ -60,7 +59,6 @@ public class SchemaToProtoConverterTest { ).addProperties(PropertyConfigProto.newBuilder() .setPropertyName("body") .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setSchemaType("") .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) .setIndexingConfig( com.android.server.appsearch.proto.IndexingConfig.newBuilder() @@ -94,7 +92,6 @@ public class SchemaToProtoConverterTest { .addProperties(PropertyConfigProto.newBuilder() .setPropertyName("artist") .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setSchemaType("") .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED) .setIndexingConfig( com.android.server.appsearch.proto.IndexingConfig.newBuilder() @@ -104,7 +101,6 @@ public class SchemaToProtoConverterTest { ).addProperties(PropertyConfigProto.newBuilder() .setPropertyName("pubDate") .setDataType(PropertyConfigProto.DataType.Code.INT64) - .setSchemaType("") .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) .setIndexingConfig( com.android.server.appsearch.proto.IndexingConfig.newBuilder() diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java similarity index 98% rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java index e9357aa606320..d5762a1317b50 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.appsearch.external.localbackend.converter; +package com.android.server.appsearch.external.localstorage.converter; import static com.google.common.truth.Truth.assertThat; @@ -123,7 +123,7 @@ public class SnippetTest { for (SearchResultProto.ResultProto proto : searchResultProto.getResultsList()) { SearchResult result = SearchResultToProtoConverter.convertSearchResult(proto); - assertThat(result.getMatches()).isEqualTo(null); + assertThat(result.getMatches()).isEmpty(); } }