Merge "Update framework from jetpack." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1e258ecf1d
@@ -37,6 +37,8 @@ import java.util.Objects;
|
|||||||
* @param <ValueType> The type of result object for successful calls.
|
* @param <ValueType> The type of result object for successful calls.
|
||||||
*/
|
*/
|
||||||
public final class AppSearchResult<ValueType> implements Parcelable {
|
public final class AppSearchResult<ValueType> implements Parcelable {
|
||||||
|
private static final String TAG = "AppSearchResult";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result codes from {@link AppSearchSession} methods.
|
* Result codes from {@link AppSearchSession} methods.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -246,14 +248,22 @@ public final class AppSearchResult<ValueType> implements Parcelable {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
|
public static <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
|
||||||
@NonNull Throwable t) {
|
@NonNull Throwable t) {
|
||||||
Log.d("AppSearchResult", "Converting throwable to failed result.", t);
|
// Log for traceability. NOT_FOUND is logged at VERBOSE because this error can occur during
|
||||||
|
// the regular operation of the system (b/183550974). Everything else is logged at DEBUG.
|
||||||
|
if (t instanceof AppSearchException
|
||||||
|
&& ((AppSearchException) t).getResultCode() == RESULT_NOT_FOUND) {
|
||||||
|
Log.v(TAG, "Converting throwable to failed result: " + t);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Converting throwable to failed result.", t);
|
||||||
|
}
|
||||||
|
|
||||||
if (t instanceof AppSearchException) {
|
if (t instanceof AppSearchException) {
|
||||||
return ((AppSearchException) t).toAppSearchResult();
|
return ((AppSearchException) t).toAppSearchResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String exceptionClass = t.getClass().getSimpleName();
|
||||||
@AppSearchResult.ResultCode int resultCode;
|
@AppSearchResult.ResultCode int resultCode;
|
||||||
if (t instanceof IllegalStateException) {
|
if (t instanceof IllegalStateException || t instanceof NullPointerException) {
|
||||||
resultCode = AppSearchResult.RESULT_INTERNAL_ERROR;
|
resultCode = AppSearchResult.RESULT_INTERNAL_ERROR;
|
||||||
} else if (t instanceof IllegalArgumentException) {
|
} else if (t instanceof IllegalArgumentException) {
|
||||||
resultCode = AppSearchResult.RESULT_INVALID_ARGUMENT;
|
resultCode = AppSearchResult.RESULT_INVALID_ARGUMENT;
|
||||||
@@ -262,6 +272,6 @@ public final class AppSearchResult<ValueType> implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
resultCode = AppSearchResult.RESULT_UNKNOWN_ERROR;
|
resultCode = AppSearchResult.RESULT_UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
return AppSearchResult.newFailedResult(resultCode, t.getMessage());
|
return AppSearchResult.newFailedResult(resultCode, exceptionClass + ": " + t.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public final class AppSearchSchema {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public AppSearchSchema(@NonNull Bundle bundle) {
|
public AppSearchSchema(@NonNull Bundle bundle) {
|
||||||
Preconditions.checkNotNull(bundle);
|
Objects.requireNonNull(bundle);
|
||||||
mBundle = bundle;
|
mBundle = bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ public final class AppSearchSchema {
|
|||||||
|
|
||||||
/** Creates a new {@link AppSearchSchema.Builder}. */
|
/** Creates a new {@link AppSearchSchema.Builder}. */
|
||||||
public Builder(@NonNull String schemaType) {
|
public Builder(@NonNull String schemaType) {
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
mSchemaType = schemaType;
|
mSchemaType = schemaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ public final class AppSearchSchema {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
|
public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(propertyConfig);
|
Objects.requireNonNull(propertyConfig);
|
||||||
String name = propertyConfig.getName();
|
String name = propertyConfig.getName();
|
||||||
if (!mPropertyNames.add(name)) {
|
if (!mPropertyNames.add(name)) {
|
||||||
throw new IllegalSchemaException("Property defined more than once: " + name);
|
throw new IllegalSchemaException("Property defined more than once: " + name);
|
||||||
@@ -246,7 +246,7 @@ public final class AppSearchSchema {
|
|||||||
@Nullable private Integer mHashCode;
|
@Nullable private Integer mHashCode;
|
||||||
|
|
||||||
PropertyConfig(@NonNull Bundle bundle) {
|
PropertyConfig(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -712,7 +712,7 @@ public final class AppSearchSchema {
|
|||||||
/** Returns the logical schema-type of the contents of this document property. */
|
/** Returns the logical schema-type of the contents of this document property. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getSchemaType() {
|
public String getSchemaType() {
|
||||||
return Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD));
|
return Objects.requireNonNull(mBundle.getString(SCHEMA_TYPE_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -755,7 +755,7 @@ public final class AppSearchSchema {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public DocumentPropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
|
public DocumentPropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
mBundle.putString(SCHEMA_TYPE_FIELD, schemaType);
|
mBundle.putString(SCHEMA_TYPE_FIELD, schemaType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import java.lang.reflect.Array;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,11 +102,11 @@ public class GenericDocument {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public GenericDocument(@NonNull Bundle bundle) {
|
public GenericDocument(@NonNull Bundle bundle) {
|
||||||
Preconditions.checkNotNull(bundle);
|
Objects.requireNonNull(bundle);
|
||||||
mBundle = bundle;
|
mBundle = bundle;
|
||||||
mProperties = Preconditions.checkNotNull(bundle.getParcelable(PROPERTIES_FIELD));
|
mProperties = Objects.requireNonNull(bundle.getParcelable(PROPERTIES_FIELD));
|
||||||
mUri = Preconditions.checkNotNull(mBundle.getString(URI_FIELD));
|
mUri = Objects.requireNonNull(mBundle.getString(URI_FIELD));
|
||||||
mSchemaType = Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD));
|
mSchemaType = Objects.requireNonNull(mBundle.getString(SCHEMA_TYPE_FIELD));
|
||||||
mCreationTimestampMillis =
|
mCreationTimestampMillis =
|
||||||
mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
|
mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
@@ -199,7 +200,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Object getProperty(@NonNull String key) {
|
public Object getProperty(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Object property = mProperties.get(key);
|
Object property = mProperties.get(key);
|
||||||
if (property instanceof ArrayList) {
|
if (property instanceof ArrayList) {
|
||||||
return getPropertyBytesArray(key);
|
return getPropertyBytesArray(key);
|
||||||
@@ -218,7 +219,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getPropertyString(@NonNull String key) {
|
public String getPropertyString(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
String[] propertyArray = getPropertyStringArray(key);
|
String[] propertyArray = getPropertyStringArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -235,7 +236,7 @@ public class GenericDocument {
|
|||||||
* there is no such key or the value is of a different type.
|
* there is no such key or the value is of a different type.
|
||||||
*/
|
*/
|
||||||
public long getPropertyLong(@NonNull String key) {
|
public long getPropertyLong(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
long[] propertyArray = getPropertyLongArray(key);
|
long[] propertyArray = getPropertyLongArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -252,7 +253,7 @@ public class GenericDocument {
|
|||||||
* if there is no such key or the value is of a different type.
|
* if there is no such key or the value is of a different type.
|
||||||
*/
|
*/
|
||||||
public double getPropertyDouble(@NonNull String key) {
|
public double getPropertyDouble(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
double[] propertyArray = getPropertyDoubleArray(key);
|
double[] propertyArray = getPropertyDoubleArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@@ -269,7 +270,7 @@ public class GenericDocument {
|
|||||||
* false} if there is no such key or the value is of a different type.
|
* false} if there is no such key or the value is of a different type.
|
||||||
*/
|
*/
|
||||||
public boolean getPropertyBoolean(@NonNull String key) {
|
public boolean getPropertyBoolean(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
boolean[] propertyArray = getPropertyBooleanArray(key);
|
boolean[] propertyArray = getPropertyBooleanArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -287,7 +288,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public byte[] getPropertyBytes(@NonNull String key) {
|
public byte[] getPropertyBytes(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
byte[][] propertyArray = getPropertyBytesArray(key);
|
byte[][] propertyArray = getPropertyBytesArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -305,7 +306,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public GenericDocument getPropertyDocument(@NonNull String key) {
|
public GenericDocument getPropertyDocument(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
GenericDocument[] propertyArray = getPropertyDocumentArray(key);
|
GenericDocument[] propertyArray = getPropertyDocumentArray(key);
|
||||||
if (propertyArray == null || propertyArray.length == 0) {
|
if (propertyArray == null || propertyArray.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -342,7 +343,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String[] getPropertyStringArray(@NonNull String key) {
|
public String[] getPropertyStringArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
return getAndCastPropertyArray(key, String[].class);
|
return getAndCastPropertyArray(key, String[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +356,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public long[] getPropertyLongArray(@NonNull String key) {
|
public long[] getPropertyLongArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
return getAndCastPropertyArray(key, long[].class);
|
return getAndCastPropertyArray(key, long[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +369,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public double[] getPropertyDoubleArray(@NonNull String key) {
|
public double[] getPropertyDoubleArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
return getAndCastPropertyArray(key, double[].class);
|
return getAndCastPropertyArray(key, double[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +382,7 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public boolean[] getPropertyBooleanArray(@NonNull String key) {
|
public boolean[] getPropertyBooleanArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
return getAndCastPropertyArray(key, boolean[].class);
|
return getAndCastPropertyArray(key, boolean[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +397,7 @@ public class GenericDocument {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public byte[][] getPropertyBytesArray(@NonNull String key) {
|
public byte[][] getPropertyBytesArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
ArrayList<Bundle> bundles = getAndCastPropertyArray(key, ArrayList.class);
|
ArrayList<Bundle> bundles = getAndCastPropertyArray(key, ArrayList.class);
|
||||||
if (bundles == null || bundles.size() == 0) {
|
if (bundles == null || bundles.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -428,7 +429,7 @@ public class GenericDocument {
|
|||||||
@SuppressLint("ArrayReturn")
|
@SuppressLint("ArrayReturn")
|
||||||
@Nullable
|
@Nullable
|
||||||
public GenericDocument[] getPropertyDocumentArray(@NonNull String key) {
|
public GenericDocument[] getPropertyDocumentArray(@NonNull String key) {
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Parcelable[] bundles = getAndCastPropertyArray(key, Parcelable[].class);
|
Parcelable[] bundles = getAndCastPropertyArray(key, Parcelable[].class);
|
||||||
if (bundles == null || bundles.length == 0) {
|
if (bundles == null || bundles.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -591,9 +592,9 @@ public class GenericDocument {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Builder(@NonNull String namespace, @NonNull String uri, @NonNull String schemaType) {
|
public Builder(@NonNull String namespace, @NonNull String uri, @NonNull String schemaType) {
|
||||||
Preconditions.checkNotNull(namespace);
|
Objects.requireNonNull(namespace);
|
||||||
Preconditions.checkNotNull(uri);
|
Objects.requireNonNull(uri);
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
mBuilderTypeInstance = (BuilderType) this;
|
mBuilderTypeInstance = (BuilderType) this;
|
||||||
mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
|
mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
|
||||||
mBundle.putString(GenericDocument.URI_FIELD, uri);
|
mBundle.putString(GenericDocument.URI_FIELD, uri);
|
||||||
@@ -682,8 +683,8 @@ public class GenericDocument {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
|
public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -694,15 +695,14 @@ public class GenericDocument {
|
|||||||
*
|
*
|
||||||
* @param key the key associated with the {@code values}.
|
* @param key the key associated with the {@code values}.
|
||||||
* @param values the {@code boolean} values of the property.
|
* @param values the {@code boolean} values of the property.
|
||||||
* @throws IllegalArgumentException if no values are provided or if values exceed maximum
|
* @throws IllegalArgumentException if values exceed maximum repeated property length.
|
||||||
* repeated property length.
|
|
||||||
* @throws IllegalStateException if the builder has already been used.
|
* @throws IllegalStateException if the builder has already been used.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
|
public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -712,15 +712,14 @@ public class GenericDocument {
|
|||||||
*
|
*
|
||||||
* @param key the key associated with the {@code values}.
|
* @param key the key associated with the {@code values}.
|
||||||
* @param values the {@code long} values of the property.
|
* @param values the {@code long} values of the property.
|
||||||
* @throws IllegalArgumentException if no values are provided or if values exceed maximum
|
* @throws IllegalArgumentException if values exceed maximum repeated property length.
|
||||||
* repeated property length.
|
|
||||||
* @throws IllegalStateException if the builder has already been used.
|
* @throws IllegalStateException if the builder has already been used.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
|
public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -730,15 +729,14 @@ public class GenericDocument {
|
|||||||
*
|
*
|
||||||
* @param key the key associated with the {@code values}.
|
* @param key the key associated with the {@code values}.
|
||||||
* @param values the {@code double} values of the property.
|
* @param values the {@code double} values of the property.
|
||||||
* @throws IllegalArgumentException if no values are provided or if values exceed maximum
|
* @throws IllegalArgumentException if values exceed maximum repeated property length.
|
||||||
* repeated property length.
|
|
||||||
* @throws IllegalStateException if the builder has already been used.
|
* @throws IllegalStateException if the builder has already been used.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
|
public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -755,8 +753,8 @@ public class GenericDocument {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
|
public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -776,8 +774,8 @@ public class GenericDocument {
|
|||||||
public BuilderType setPropertyDocument(
|
public BuilderType setPropertyDocument(
|
||||||
@NonNull String key, @NonNull GenericDocument... values) {
|
@NonNull String key, @NonNull GenericDocument... values) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(key);
|
Objects.requireNonNull(key);
|
||||||
Preconditions.checkNotNull(values);
|
Objects.requireNonNull(values);
|
||||||
putInPropertyBundle(key, values);
|
putInPropertyBundle(key, values);
|
||||||
return mBuilderTypeInstance;
|
return mBuilderTypeInstance;
|
||||||
}
|
}
|
||||||
@@ -850,9 +848,7 @@ public class GenericDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
|
private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
|
||||||
if (length == 0) {
|
if (length > MAX_REPEATED_PROPERTY_LENGTH) {
|
||||||
throw new IllegalArgumentException("The input array is empty.");
|
|
||||||
} else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Repeated property \""
|
"Repeated property \""
|
||||||
+ key
|
+ key
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,9 +53,9 @@ public final class GetByUriRequest {
|
|||||||
@NonNull String namespace,
|
@NonNull String namespace,
|
||||||
@NonNull Set<String> uris,
|
@NonNull Set<String> uris,
|
||||||
@NonNull Map<String, List<String>> typePropertyPathsMap) {
|
@NonNull Map<String, List<String>> typePropertyPathsMap) {
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
mUris = Preconditions.checkNotNull(uris);
|
mUris = Objects.requireNonNull(uris);
|
||||||
mTypePropertyPathsMap = Preconditions.checkNotNull(typePropertyPathsMap);
|
mTypePropertyPathsMap = Objects.requireNonNull(typePropertyPathsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the namespace attached to the request. */
|
/** Returns the namespace attached to the request. */
|
||||||
@@ -114,7 +115,7 @@ public final class GetByUriRequest {
|
|||||||
|
|
||||||
/** Creates a {@link GetByUriRequest.Builder} instance. */
|
/** Creates a {@link GetByUriRequest.Builder} instance. */
|
||||||
public Builder(@NonNull String namespace) {
|
public Builder(@NonNull String namespace) {
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +125,7 @@ public final class GetByUriRequest {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addUris(@NonNull String... uris) {
|
public Builder addUris(@NonNull String... uris) {
|
||||||
Preconditions.checkNotNull(uris);
|
Objects.requireNonNull(uris);
|
||||||
return addUris(Arrays.asList(uris));
|
return addUris(Arrays.asList(uris));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ public final class GetByUriRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addUris(@NonNull Collection<String> uris) {
|
public Builder addUris(@NonNull Collection<String> uris) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(uris);
|
Objects.requireNonNull(uris);
|
||||||
mUris.addAll(uris);
|
mUris.addAll(uris);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -161,11 +162,11 @@ public final class GetByUriRequest {
|
|||||||
public Builder addProjection(
|
public Builder addProjection(
|
||||||
@NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
|
@NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
Preconditions.checkNotNull(propertyPaths);
|
Objects.requireNonNull(propertyPaths);
|
||||||
List<String> propertyPathsList = new ArrayList<>(propertyPaths.size());
|
List<String> propertyPathsList = new ArrayList<>(propertyPaths.size());
|
||||||
for (String propertyPath : propertyPaths) {
|
for (String propertyPath : propertyPaths) {
|
||||||
Preconditions.checkNotNull(propertyPath);
|
Objects.requireNonNull(propertyPath);
|
||||||
propertyPathsList.add(propertyPath);
|
propertyPathsList.add(propertyPath);
|
||||||
}
|
}
|
||||||
mProjectionTypePropertyPaths.put(schemaType, propertyPathsList);
|
mProjectionTypePropertyPaths.put(schemaType, propertyPathsList);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.util.ArraySet;
|
|||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** The response class of {@link AppSearchSession#getSchema} */
|
/** The response class of {@link AppSearchSession#getSchema} */
|
||||||
@@ -34,7 +35,7 @@ public class GetSchemaResponse {
|
|||||||
private final Bundle mBundle;
|
private final Bundle mBundle;
|
||||||
|
|
||||||
GetSchemaResponse(@NonNull Bundle bundle) {
|
GetSchemaResponse(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import android.annotation.NonNull;
|
|||||||
import android.app.appsearch.util.BundleUtil;
|
import android.app.appsearch.util.BundleUtil;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import java.util.Objects;
|
||||||
|
|
||||||
/** This class represents a uniquely identifiable package. */
|
/** This class represents a uniquely identifiable package. */
|
||||||
public class PackageIdentifier {
|
public class PackageIdentifier {
|
||||||
@@ -43,7 +43,7 @@ public class PackageIdentifier {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public PackageIdentifier(@NonNull Bundle bundle) {
|
public PackageIdentifier(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -54,12 +54,12 @@ public class PackageIdentifier {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return Preconditions.checkNotNull(mBundle.getString(PACKAGE_NAME_FIELD));
|
return Objects.requireNonNull(mBundle.getString(PACKAGE_NAME_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public byte[] getSha256Certificate() {
|
public byte[] getSha256Certificate() {
|
||||||
return Preconditions.checkNotNull(mBundle.getByteArray(SHA256_CERTIFICATE_FIELD));
|
return Objects.requireNonNull(mBundle.getByteArray(SHA256_CERTIFICATE_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates a request to index documents into an {@link AppSearchSession} database.
|
* Encapsulates a request to index documents into an {@link AppSearchSession} database.
|
||||||
@@ -61,7 +62,7 @@ public final class PutDocumentsRequest {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addGenericDocuments(@NonNull GenericDocument... documents) {
|
public Builder addGenericDocuments(@NonNull GenericDocument... documents) {
|
||||||
Preconditions.checkNotNull(documents);
|
Objects.requireNonNull(documents);
|
||||||
return addGenericDocuments(Arrays.asList(documents));
|
return addGenericDocuments(Arrays.asList(documents));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ public final class PutDocumentsRequest {
|
|||||||
public Builder addGenericDocuments(
|
public Builder addGenericDocuments(
|
||||||
@NonNull Collection<? extends GenericDocument> documents) {
|
@NonNull Collection<? extends GenericDocument> documents) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(documents);
|
Objects.requireNonNull(documents);
|
||||||
mDocuments.addAll(documents);
|
mDocuments.addAll(documents);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.android.internal.util.Preconditions;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +66,7 @@ public final class RemoveByUriRequest {
|
|||||||
|
|
||||||
/** Creates a {@link RemoveByUriRequest.Builder} instance. */
|
/** Creates a {@link RemoveByUriRequest.Builder} instance. */
|
||||||
public Builder(@NonNull String namespace) {
|
public Builder(@NonNull String namespace) {
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +76,7 @@ public final class RemoveByUriRequest {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addUris(@NonNull String... uris) {
|
public Builder addUris(@NonNull String... uris) {
|
||||||
Preconditions.checkNotNull(uris);
|
Objects.requireNonNull(uris);
|
||||||
return addUris(Arrays.asList(uris));
|
return addUris(Arrays.asList(uris));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ public final class RemoveByUriRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addUris(@NonNull Collection<String> uris) {
|
public Builder addUris(@NonNull Collection<String> uris) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(uris);
|
Objects.requireNonNull(uris);
|
||||||
mUris.addAll(uris);
|
mUris.addAll(uris);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A request to report usage of a document owned by another app from a system UI surface.
|
* A request to report usage of a document owned by another app from a system UI surface.
|
||||||
*
|
*
|
||||||
@@ -42,10 +44,10 @@ public final class ReportSystemUsageRequest {
|
|||||||
@NonNull String namespace,
|
@NonNull String namespace,
|
||||||
@NonNull String uri,
|
@NonNull String uri,
|
||||||
long usageTimeMillis) {
|
long usageTimeMillis) {
|
||||||
mPackageName = Preconditions.checkNotNull(packageName);
|
mPackageName = Objects.requireNonNull(packageName);
|
||||||
mDatabase = Preconditions.checkNotNull(database);
|
mDatabase = Objects.requireNonNull(database);
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
mUri = Preconditions.checkNotNull(uri);
|
mUri = Objects.requireNonNull(uri);
|
||||||
mUsageTimeMillis = usageTimeMillis;
|
mUsageTimeMillis = usageTimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,9 +97,9 @@ public final class ReportSystemUsageRequest {
|
|||||||
/** Creates a {@link ReportSystemUsageRequest.Builder} instance. */
|
/** Creates a {@link ReportSystemUsageRequest.Builder} instance. */
|
||||||
public Builder(
|
public Builder(
|
||||||
@NonNull String packageName, @NonNull String database, @NonNull String namespace) {
|
@NonNull String packageName, @NonNull String database, @NonNull String namespace) {
|
||||||
mPackageName = Preconditions.checkNotNull(packageName);
|
mPackageName = Objects.requireNonNull(packageName);
|
||||||
mDatabase = Preconditions.checkNotNull(database);
|
mDatabase = Objects.requireNonNull(database);
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,7 +112,7 @@ public final class ReportSystemUsageRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public ReportSystemUsageRequest.Builder setUri(@NonNull String uri) {
|
public ReportSystemUsageRequest.Builder setUri(@NonNull String uri) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(uri);
|
Objects.requireNonNull(uri);
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,7 @@ public final class ReportSystemUsageRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public ReportSystemUsageRequest build() {
|
public ReportSystemUsageRequest build() {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(mUri, "ReportUsageRequest is missing a URI");
|
Objects.requireNonNull(mUri, "ReportUsageRequest is missing a URI");
|
||||||
if (mUsageTimeMillis == null) {
|
if (mUsageTimeMillis == null) {
|
||||||
mUsageTimeMillis = System.currentTimeMillis();
|
mUsageTimeMillis = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A request to report usage of a document.
|
* A request to report usage of a document.
|
||||||
*
|
*
|
||||||
@@ -33,8 +35,8 @@ public final class ReportUsageRequest {
|
|||||||
private final long mUsageTimeMillis;
|
private final long mUsageTimeMillis;
|
||||||
|
|
||||||
ReportUsageRequest(@NonNull String namespace, @NonNull String uri, long usageTimeMillis) {
|
ReportUsageRequest(@NonNull String namespace, @NonNull String uri, long usageTimeMillis) {
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
mUri = Preconditions.checkNotNull(uri);
|
mUri = Objects.requireNonNull(uri);
|
||||||
mUsageTimeMillis = usageTimeMillis;
|
mUsageTimeMillis = usageTimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +71,7 @@ public final class ReportUsageRequest {
|
|||||||
|
|
||||||
/** Creates a {@link ReportUsageRequest.Builder} instance. */
|
/** Creates a {@link ReportUsageRequest.Builder} instance. */
|
||||||
public Builder(@NonNull String namespace) {
|
public Builder(@NonNull String namespace) {
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,7 +84,7 @@ public final class ReportUsageRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public ReportUsageRequest.Builder setUri(@NonNull String uri) {
|
public ReportUsageRequest.Builder setUri(@NonNull String uri) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(uri);
|
Objects.requireNonNull(uri);
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -114,7 +116,7 @@ public final class ReportUsageRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public ReportUsageRequest build() {
|
public ReportUsageRequest build() {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(mUri, "ReportUsageRequest is missing a URI");
|
Objects.requireNonNull(mUri, "ReportUsageRequest is missing a URI");
|
||||||
if (mUsageTimeMillis == null) {
|
if (mUsageTimeMillis == null) {
|
||||||
mUsageTimeMillis = System.currentTimeMillis();
|
mUsageTimeMillis = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public final class SearchResult {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public SearchResult(@NonNull Bundle bundle) {
|
public SearchResult(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -77,8 +77,7 @@ public final class SearchResult {
|
|||||||
public GenericDocument getGenericDocument() {
|
public GenericDocument getGenericDocument() {
|
||||||
if (mDocument == null) {
|
if (mDocument == null) {
|
||||||
mDocument =
|
mDocument =
|
||||||
new GenericDocument(
|
new GenericDocument(Objects.requireNonNull(mBundle.getBundle(DOCUMENT_FIELD)));
|
||||||
Preconditions.checkNotNull(mBundle.getBundle(DOCUMENT_FIELD)));
|
|
||||||
}
|
}
|
||||||
return mDocument;
|
return mDocument;
|
||||||
}
|
}
|
||||||
@@ -95,7 +94,7 @@ public final class SearchResult {
|
|||||||
public List<MatchInfo> getMatches() {
|
public List<MatchInfo> getMatches() {
|
||||||
if (mMatches == null) {
|
if (mMatches == null) {
|
||||||
List<Bundle> matchBundles =
|
List<Bundle> matchBundles =
|
||||||
Preconditions.checkNotNull(mBundle.getParcelableArrayList(MATCHES_FIELD));
|
Objects.requireNonNull(mBundle.getParcelableArrayList(MATCHES_FIELD));
|
||||||
mMatches = new ArrayList<>(matchBundles.size());
|
mMatches = new ArrayList<>(matchBundles.size());
|
||||||
for (int i = 0; i < matchBundles.size(); i++) {
|
for (int i = 0; i < matchBundles.size(); i++) {
|
||||||
MatchInfo matchInfo = new MatchInfo(matchBundles.get(i), getGenericDocument());
|
MatchInfo matchInfo = new MatchInfo(matchBundles.get(i), getGenericDocument());
|
||||||
@@ -112,7 +111,7 @@ public final class SearchResult {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return Preconditions.checkNotNull(mBundle.getString(PACKAGE_NAME_FIELD));
|
return Objects.requireNonNull(mBundle.getString(PACKAGE_NAME_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,7 +121,7 @@ public final class SearchResult {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getDatabaseName() {
|
public String getDatabaseName() {
|
||||||
return Preconditions.checkNotNull(mBundle.getString(DATABASE_NAME_FIELD));
|
return Objects.requireNonNull(mBundle.getString(DATABASE_NAME_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,8 +168,8 @@ public final class SearchResult {
|
|||||||
* @param databaseName the database name the matched document belongs to.
|
* @param databaseName the database name the matched document belongs to.
|
||||||
*/
|
*/
|
||||||
public Builder(@NonNull String packageName, @NonNull String databaseName) {
|
public Builder(@NonNull String packageName, @NonNull String databaseName) {
|
||||||
mBundle.putString(PACKAGE_NAME_FIELD, Preconditions.checkNotNull(packageName));
|
mBundle.putString(PACKAGE_NAME_FIELD, Objects.requireNonNull(packageName));
|
||||||
mBundle.putString(DATABASE_NAME_FIELD, Preconditions.checkNotNull(databaseName));
|
mBundle.putString(DATABASE_NAME_FIELD, Objects.requireNonNull(databaseName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,9 +311,9 @@ public final class SearchResult {
|
|||||||
@Nullable private MatchRange mWindowRange;
|
@Nullable private MatchRange mWindowRange;
|
||||||
|
|
||||||
MatchInfo(@NonNull Bundle bundle, @Nullable GenericDocument document) {
|
MatchInfo(@NonNull Bundle bundle, @Nullable GenericDocument document) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
mDocument = document;
|
mDocument = document;
|
||||||
mPropertyPath = Preconditions.checkNotNull(bundle.getString(PROPERTY_PATH_FIELD));
|
mPropertyPath = Objects.requireNonNull(bundle.getString(PROPERTY_PATH_FIELD));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,7 +448,7 @@ public final class SearchResult {
|
|||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mBundle.putString(
|
mBundle.putString(
|
||||||
SearchResult.MatchInfo.PROPERTY_PATH_FIELD,
|
SearchResult.MatchInfo.PROPERTY_PATH_FIELD,
|
||||||
Preconditions.checkNotNull(propertyPath));
|
Objects.requireNonNull(propertyPath));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +460,7 @@ public final class SearchResult {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setExactMatchRange(@NonNull MatchRange matchRange) {
|
public Builder setExactMatchRange(@NonNull MatchRange matchRange) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(matchRange);
|
Objects.requireNonNull(matchRange);
|
||||||
mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_LOWER_FIELD, matchRange.getStart());
|
mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_LOWER_FIELD, matchRange.getStart());
|
||||||
mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_UPPER_FIELD, matchRange.getEnd());
|
mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_UPPER_FIELD, matchRange.getEnd());
|
||||||
return this;
|
return this;
|
||||||
@@ -475,7 +474,7 @@ public final class SearchResult {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setSnippetRange(@NonNull MatchRange matchRange) {
|
public Builder setSnippetRange(@NonNull MatchRange matchRange) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(matchRange);
|
Objects.requireNonNull(matchRange);
|
||||||
mBundle.putInt(MatchInfo.SNIPPET_RANGE_LOWER_FIELD, matchRange.getStart());
|
mBundle.putInt(MatchInfo.SNIPPET_RANGE_LOWER_FIELD, matchRange.getStart());
|
||||||
mBundle.putInt(MatchInfo.SNIPPET_RANGE_UPPER_FIELD, matchRange.getEnd());
|
mBundle.putInt(MatchInfo.SNIPPET_RANGE_UPPER_FIELD, matchRange.getEnd());
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -20,11 +20,10 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a page of {@link SearchResult}s
|
* This class represents a page of {@link SearchResult}s
|
||||||
@@ -41,7 +40,7 @@ public class SearchResultPage {
|
|||||||
@NonNull private final Bundle mBundle;
|
@NonNull private final Bundle mBundle;
|
||||||
|
|
||||||
public SearchResultPage(@NonNull Bundle bundle) {
|
public SearchResultPage(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
mNextPageToken = mBundle.getLong(NEXT_PAGE_TOKEN_FIELD);
|
mNextPageToken = mBundle.getLong(NEXT_PAGE_TOKEN_FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,7 +177,7 @@ public final class SearchSpec {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public SearchSpec(@NonNull Bundle bundle) {
|
public SearchSpec(@NonNull Bundle bundle) {
|
||||||
Preconditions.checkNotNull(bundle);
|
Objects.requireNonNull(bundle);
|
||||||
mBundle = bundle;
|
mBundle = bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +343,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterSchemas(@NonNull String... schemas) {
|
public Builder addFilterSchemas(@NonNull String... schemas) {
|
||||||
Preconditions.checkNotNull(schemas);
|
Objects.requireNonNull(schemas);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
return addFilterSchemas(Arrays.asList(schemas));
|
return addFilterSchemas(Arrays.asList(schemas));
|
||||||
}
|
}
|
||||||
@@ -355,7 +356,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterSchemas(@NonNull Collection<String> schemas) {
|
public Builder addFilterSchemas(@NonNull Collection<String> schemas) {
|
||||||
Preconditions.checkNotNull(schemas);
|
Objects.requireNonNull(schemas);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mSchemas.addAll(schemas);
|
mSchemas.addAll(schemas);
|
||||||
return this;
|
return this;
|
||||||
@@ -369,7 +370,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterNamespaces(@NonNull String... namespaces) {
|
public Builder addFilterNamespaces(@NonNull String... namespaces) {
|
||||||
Preconditions.checkNotNull(namespaces);
|
Objects.requireNonNull(namespaces);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
return addFilterNamespaces(Arrays.asList(namespaces));
|
return addFilterNamespaces(Arrays.asList(namespaces));
|
||||||
}
|
}
|
||||||
@@ -382,7 +383,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterNamespaces(@NonNull Collection<String> namespaces) {
|
public Builder addFilterNamespaces(@NonNull Collection<String> namespaces) {
|
||||||
Preconditions.checkNotNull(namespaces);
|
Objects.requireNonNull(namespaces);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mNamespaces.addAll(namespaces);
|
mNamespaces.addAll(namespaces);
|
||||||
return this;
|
return this;
|
||||||
@@ -398,7 +399,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterPackageNames(@NonNull String... packageNames) {
|
public Builder addFilterPackageNames(@NonNull String... packageNames) {
|
||||||
Preconditions.checkNotNull(packageNames);
|
Objects.requireNonNull(packageNames);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
return addFilterPackageNames(Arrays.asList(packageNames));
|
return addFilterPackageNames(Arrays.asList(packageNames));
|
||||||
}
|
}
|
||||||
@@ -413,7 +414,7 @@ public final class SearchSpec {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addFilterPackageNames(@NonNull Collection<String> packageNames) {
|
public Builder addFilterPackageNames(@NonNull Collection<String> packageNames) {
|
||||||
Preconditions.checkNotNull(packageNames);
|
Objects.requireNonNull(packageNames);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mPackageNames.addAll(packageNames);
|
mPackageNames.addAll(packageNames);
|
||||||
return this;
|
return this;
|
||||||
@@ -586,11 +587,11 @@ public final class SearchSpec {
|
|||||||
public SearchSpec.Builder addProjection(
|
public SearchSpec.Builder addProjection(
|
||||||
@NonNull String schema, @NonNull Collection<String> propertyPaths) {
|
@NonNull String schema, @NonNull Collection<String> propertyPaths) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(schema);
|
Objects.requireNonNull(schema);
|
||||||
Preconditions.checkNotNull(propertyPaths);
|
Objects.requireNonNull(propertyPaths);
|
||||||
ArrayList<String> propertyPathsArrayList = new ArrayList<>(propertyPaths.size());
|
ArrayList<String> propertyPathsArrayList = new ArrayList<>(propertyPaths.size());
|
||||||
for (String propertyPath : propertyPaths) {
|
for (String propertyPath : propertyPaths) {
|
||||||
Preconditions.checkNotNull(propertyPath);
|
Objects.requireNonNull(propertyPath);
|
||||||
propertyPathsArrayList.add(propertyPath);
|
propertyPathsArrayList.add(propertyPath);
|
||||||
}
|
}
|
||||||
mProjectionTypePropertyMasks.putStringArrayList(schema, propertyPathsArrayList);
|
mProjectionTypePropertyMasks.putStringArrayList(schema, propertyPathsArrayList);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,10 +95,10 @@ public final class SetSchemaRequest {
|
|||||||
@NonNull Map<String, Migrator> migrators,
|
@NonNull Map<String, Migrator> migrators,
|
||||||
boolean forceOverride,
|
boolean forceOverride,
|
||||||
int version) {
|
int version) {
|
||||||
mSchemas = Preconditions.checkNotNull(schemas);
|
mSchemas = Objects.requireNonNull(schemas);
|
||||||
mSchemasNotDisplayedBySystem = Preconditions.checkNotNull(schemasNotDisplayedBySystem);
|
mSchemasNotDisplayedBySystem = Objects.requireNonNull(schemasNotDisplayedBySystem);
|
||||||
mSchemasVisibleToPackages = Preconditions.checkNotNull(schemasVisibleToPackages);
|
mSchemasVisibleToPackages = Objects.requireNonNull(schemasVisibleToPackages);
|
||||||
mMigrators = Preconditions.checkNotNull(migrators);
|
mMigrators = Objects.requireNonNull(migrators);
|
||||||
mForceOverride = forceOverride;
|
mForceOverride = forceOverride;
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
}
|
}
|
||||||
@@ -192,7 +193,7 @@ public final class SetSchemaRequest {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addSchemas(@NonNull AppSearchSchema... schemas) {
|
public Builder addSchemas(@NonNull AppSearchSchema... schemas) {
|
||||||
Preconditions.checkNotNull(schemas);
|
Objects.requireNonNull(schemas);
|
||||||
return addSchemas(Arrays.asList(schemas));
|
return addSchemas(Arrays.asList(schemas));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ public final class SetSchemaRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) {
|
public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkNotNull(schemas);
|
Objects.requireNonNull(schemas);
|
||||||
mSchemas.addAll(schemas);
|
mSchemas.addAll(schemas);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -231,7 +232,7 @@ public final class SetSchemaRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setSchemaTypeDisplayedBySystem(
|
public Builder setSchemaTypeDisplayedBySystem(
|
||||||
@NonNull String schemaType, boolean displayed) {
|
@NonNull String schemaType, boolean displayed) {
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
|
|
||||||
if (displayed) {
|
if (displayed) {
|
||||||
@@ -270,8 +271,8 @@ public final class SetSchemaRequest {
|
|||||||
@NonNull String schemaType,
|
@NonNull String schemaType,
|
||||||
boolean visible,
|
boolean visible,
|
||||||
@NonNull PackageIdentifier packageIdentifier) {
|
@NonNull PackageIdentifier packageIdentifier) {
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
Preconditions.checkNotNull(packageIdentifier);
|
Objects.requireNonNull(packageIdentifier);
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
|
|
||||||
Set<PackageIdentifier> packageIdentifiers = mSchemasVisibleToPackages.get(schemaType);
|
Set<PackageIdentifier> packageIdentifiers = mSchemasVisibleToPackages.get(schemaType);
|
||||||
@@ -321,8 +322,8 @@ public final class SetSchemaRequest {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@SuppressLint("MissingGetterMatchingBuilder") // Getter return plural objects.
|
@SuppressLint("MissingGetterMatchingBuilder") // Getter return plural objects.
|
||||||
public Builder setMigrator(@NonNull String schemaType, @NonNull Migrator migrator) {
|
public Builder setMigrator(@NonNull String schemaType, @NonNull Migrator migrator) {
|
||||||
Preconditions.checkNotNull(schemaType);
|
Objects.requireNonNull(schemaType);
|
||||||
Preconditions.checkNotNull(migrator);
|
Objects.requireNonNull(migrator);
|
||||||
mMigrators.put(schemaType, migrator);
|
mMigrators.put(schemaType, migrator);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -350,7 +351,7 @@ public final class SetSchemaRequest {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder setMigrators(@NonNull Map<String, Migrator> migrators) {
|
public Builder setMigrators(@NonNull Map<String, Migrator> migrators) {
|
||||||
Preconditions.checkNotNull(migrators);
|
Objects.requireNonNull(migrators);
|
||||||
mMigrators.putAll(migrators);
|
mMigrators.putAll(migrators);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** The response class of {@link AppSearchSession#setSchema} */
|
/** The response class of {@link AppSearchSession#setSchema} */
|
||||||
@@ -61,8 +62,8 @@ public class SetSchemaResponse {
|
|||||||
@Nullable private Set<String> mIncompatibleTypes;
|
@Nullable private Set<String> mIncompatibleTypes;
|
||||||
|
|
||||||
SetSchemaResponse(@NonNull Bundle bundle, @NonNull List<MigrationFailure> migrationFailures) {
|
SetSchemaResponse(@NonNull Bundle bundle, @NonNull List<MigrationFailure> migrationFailures) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
mMigrationFailures = Preconditions.checkNotNull(migrationFailures);
|
mMigrationFailures = Objects.requireNonNull(migrationFailures);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetSchemaResponse(@NonNull Bundle bundle) {
|
SetSchemaResponse(@NonNull Bundle bundle) {
|
||||||
@@ -103,7 +104,7 @@ public class SetSchemaResponse {
|
|||||||
if (mDeletedTypes == null) {
|
if (mDeletedTypes == null) {
|
||||||
mDeletedTypes =
|
mDeletedTypes =
|
||||||
new ArraySet<>(
|
new ArraySet<>(
|
||||||
Preconditions.checkNotNull(
|
Objects.requireNonNull(
|
||||||
mBundle.getStringArrayList(DELETED_TYPES_FIELD)));
|
mBundle.getStringArrayList(DELETED_TYPES_FIELD)));
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableSet(mDeletedTypes);
|
return Collections.unmodifiableSet(mDeletedTypes);
|
||||||
@@ -118,7 +119,7 @@ public class SetSchemaResponse {
|
|||||||
if (mMigratedTypes == null) {
|
if (mMigratedTypes == null) {
|
||||||
mMigratedTypes =
|
mMigratedTypes =
|
||||||
new ArraySet<>(
|
new ArraySet<>(
|
||||||
Preconditions.checkNotNull(
|
Objects.requireNonNull(
|
||||||
mBundle.getStringArrayList(MIGRATED_TYPES_FIELD)));
|
mBundle.getStringArrayList(MIGRATED_TYPES_FIELD)));
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableSet(mMigratedTypes);
|
return Collections.unmodifiableSet(mMigratedTypes);
|
||||||
@@ -139,7 +140,7 @@ public class SetSchemaResponse {
|
|||||||
if (mIncompatibleTypes == null) {
|
if (mIncompatibleTypes == null) {
|
||||||
mIncompatibleTypes =
|
mIncompatibleTypes =
|
||||||
new ArraySet<>(
|
new ArraySet<>(
|
||||||
Preconditions.checkNotNull(
|
Objects.requireNonNull(
|
||||||
mBundle.getStringArrayList(INCOMPATIBLE_TYPES_FIELD)));
|
mBundle.getStringArrayList(INCOMPATIBLE_TYPES_FIELD)));
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableSet(mIncompatibleTypes);
|
return Collections.unmodifiableSet(mIncompatibleTypes);
|
||||||
@@ -173,7 +174,7 @@ public class SetSchemaResponse {
|
|||||||
public Builder addMigrationFailures(
|
public Builder addMigrationFailures(
|
||||||
@NonNull Collection<MigrationFailure> migrationFailures) {
|
@NonNull Collection<MigrationFailure> migrationFailures) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mMigrationFailures.addAll(Preconditions.checkNotNull(migrationFailures));
|
mMigrationFailures.addAll(Objects.requireNonNull(migrationFailures));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addMigrationFailure(@NonNull MigrationFailure migrationFailure) {
|
public Builder addMigrationFailure(@NonNull MigrationFailure migrationFailure) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mMigrationFailures.add(Preconditions.checkNotNull(migrationFailure));
|
mMigrationFailures.add(Objects.requireNonNull(migrationFailure));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +190,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addDeletedTypes(@NonNull Collection<String> deletedTypes) {
|
public Builder addDeletedTypes(@NonNull Collection<String> deletedTypes) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mDeletedTypes.addAll(Preconditions.checkNotNull(deletedTypes));
|
mDeletedTypes.addAll(Objects.requireNonNull(deletedTypes));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +198,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addDeletedType(@NonNull String deletedType) {
|
public Builder addDeletedType(@NonNull String deletedType) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mDeletedTypes.add(Preconditions.checkNotNull(deletedType));
|
mDeletedTypes.add(Objects.requireNonNull(deletedType));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +206,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addIncompatibleTypes(@NonNull Collection<String> incompatibleTypes) {
|
public Builder addIncompatibleTypes(@NonNull Collection<String> incompatibleTypes) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mIncompatibleTypes.addAll(Preconditions.checkNotNull(incompatibleTypes));
|
mIncompatibleTypes.addAll(Objects.requireNonNull(incompatibleTypes));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +214,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addIncompatibleType(@NonNull String incompatibleType) {
|
public Builder addIncompatibleType(@NonNull String incompatibleType) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mIncompatibleTypes.add(Preconditions.checkNotNull(incompatibleType));
|
mIncompatibleTypes.add(Objects.requireNonNull(incompatibleType));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +222,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addMigratedTypes(@NonNull Collection<String> migratedTypes) {
|
public Builder addMigratedTypes(@NonNull Collection<String> migratedTypes) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mMigratedTypes.addAll(Preconditions.checkNotNull(migratedTypes));
|
mMigratedTypes.addAll(Objects.requireNonNull(migratedTypes));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder addMigratedType(@NonNull String migratedType) {
|
public Builder addMigratedType(@NonNull String migratedType) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mMigratedTypes.add(Preconditions.checkNotNull(migratedType));
|
mMigratedTypes.add(Objects.requireNonNull(migratedType));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +319,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setSchemaType(@NonNull String schemaType) {
|
public Builder setSchemaType(@NonNull String schemaType) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mSchemaType = Preconditions.checkNotNull(schemaType);
|
mSchemaType = Objects.requireNonNull(schemaType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +327,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setNamespace(@NonNull String namespace) {
|
public Builder setNamespace(@NonNull String namespace) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mNamespace = Preconditions.checkNotNull(namespace);
|
mNamespace = Objects.requireNonNull(namespace);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +335,7 @@ public class SetSchemaResponse {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public Builder setUri(@NonNull String uri) {
|
public Builder setUri(@NonNull String uri) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
mUri = Preconditions.checkNotNull(uri);
|
mUri = Objects.requireNonNull(uri);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +344,7 @@ public class SetSchemaResponse {
|
|||||||
public Builder setAppSearchResult(@NonNull AppSearchResult<Void> appSearchResult) {
|
public Builder setAppSearchResult(@NonNull AppSearchResult<Void> appSearchResult) {
|
||||||
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
Preconditions.checkState(!mBuilt, "Builder has already been used");
|
||||||
Preconditions.checkState(!appSearchResult.isSuccess(), "Input a success result");
|
Preconditions.checkState(!appSearchResult.isSuccess(), "Input a success result");
|
||||||
mFailureResult = Preconditions.checkNotNull(appSearchResult);
|
mFailureResult = Objects.requireNonNull(appSearchResult);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import android.os.Bundle;
|
|||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/** The response class of {@code AppSearchSession#getStorageInfo}. */
|
/** The response class of {@code AppSearchSession#getStorageInfo}. */
|
||||||
public class StorageInfo {
|
public class StorageInfo {
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ public class StorageInfo {
|
|||||||
private final Bundle mBundle;
|
private final Bundle mBundle;
|
||||||
|
|
||||||
StorageInfo(@NonNull Bundle bundle) {
|
StorageInfo(@NonNull Bundle bundle) {
|
||||||
mBundle = Preconditions.checkNotNull(bundle);
|
mBundle = Objects.requireNonNull(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ import java.util.Set;
|
|||||||
public final class SchemaMigrationUtil {
|
public final class SchemaMigrationUtil {
|
||||||
private SchemaMigrationUtil() {}
|
private SchemaMigrationUtil() {}
|
||||||
|
|
||||||
/** Returns all active {@link Migrator}s that need to be triggered in this migration. */
|
/**
|
||||||
|
* Returns all active {@link Migrator}s that need to be triggered in this migration.
|
||||||
|
*
|
||||||
|
* <p>{@link Migrator#shouldMigrate} returns {@code true} will make the {@link Migrator} active.
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static Map<String, Migrator> getActiveMigrators(
|
public static Map<String, Migrator> getActiveMigrators(
|
||||||
@NonNull Set<AppSearchSchema> existingSchemas,
|
@NonNull Set<AppSearchSchema> existingSchemas,
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ import com.android.server.appsearch.external.localstorage.stats.CallStats;
|
|||||||
import com.android.server.appsearch.stats.LoggerInstanceManager;
|
import com.android.server.appsearch.stats.LoggerInstanceManager;
|
||||||
import com.android.server.appsearch.stats.PlatformLogger;
|
import com.android.server.appsearch.stats.PlatformLogger;
|
||||||
|
|
||||||
|
import com.google.android.icing.proto.PersistType;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
@@ -364,6 +366,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
++operationFailureCount;
|
++operationFailureCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
|
impl.persistToDisk(PersistType.Code.LITE);
|
||||||
invokeCallbackOnResult(callback, resultBuilder.build());
|
invokeCallbackOnResult(callback, resultBuilder.build());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
@@ -631,7 +635,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl.persistToDisk();
|
impl.persistToDisk(PersistType.Code.FULL);
|
||||||
invokeCallbackOnResult(callback,
|
invokeCallbackOnResult(callback,
|
||||||
AppSearchResult.newSuccessfulResult(migrationFailureBundles));
|
AppSearchResult.newSuccessfulResult(migrationFailureBundles));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@@ -708,6 +712,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
resultBuilder.setResult(uri, throwableToFailedResult(t));
|
resultBuilder.setResult(uri, throwableToFailedResult(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
|
impl.persistToDisk(PersistType.Code.LITE);
|
||||||
invokeCallbackOnResult(callback, resultBuilder.build());
|
invokeCallbackOnResult(callback, resultBuilder.build());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
@@ -741,6 +747,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
databaseName,
|
databaseName,
|
||||||
queryExpression,
|
queryExpression,
|
||||||
new SearchSpec(searchSpecBundle));
|
new SearchSpec(searchSpecBundle));
|
||||||
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
|
impl.persistToDisk(PersistType.Code.LITE);
|
||||||
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
@@ -785,7 +793,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
verifyUserUnlocked(callingUserId);
|
verifyUserUnlocked(callingUserId);
|
||||||
AppSearchImpl impl =
|
AppSearchImpl impl =
|
||||||
mImplInstanceManager.getAppSearchImpl(callingUserId);
|
mImplInstanceManager.getAppSearchImpl(callingUserId);
|
||||||
impl.persistToDisk();
|
impl.persistToDisk(PersistType.Code.FULL);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to persist the data to disk", t);
|
Log.e(TAG, "Unable to persist the data to disk", t);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.util.ArraySet;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -153,7 +154,7 @@ public class VisibilityStore {
|
|||||||
* AppSearchImpl.
|
* AppSearchImpl.
|
||||||
*/
|
*/
|
||||||
static final String VISIBILITY_STORE_PREFIX =
|
static final String VISIBILITY_STORE_PREFIX =
|
||||||
AppSearchImpl.createPrefix(PACKAGE_NAME, DATABASE_NAME);
|
PrefixUtil.createPrefix(PACKAGE_NAME, DATABASE_NAME);
|
||||||
|
|
||||||
/** Namespace of documents that contain visibility settings */
|
/** Namespace of documents that contain visibility settings */
|
||||||
private static final String NAMESPACE = "";
|
private static final String NAMESPACE = "";
|
||||||
|
|||||||
@@ -16,10 +16,18 @@
|
|||||||
|
|
||||||
package com.android.server.appsearch.external.localstorage;
|
package com.android.server.appsearch.external.localstorage;
|
||||||
|
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.addPrefixToDocument;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.createPackagePrefix;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.createPrefix;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.getDatabaseName;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.getPackageName;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.getPrefix;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.removePrefix;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.removePrefixesFromDocument;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.WorkerThread;
|
import android.annotation.WorkerThread;
|
||||||
import android.app.appsearch.AppSearchResult;
|
|
||||||
import android.app.appsearch.AppSearchSchema;
|
import android.app.appsearch.AppSearchSchema;
|
||||||
import android.app.appsearch.GenericDocument;
|
import android.app.appsearch.GenericDocument;
|
||||||
import android.app.appsearch.GetByUriRequest;
|
import android.app.appsearch.GetByUriRequest;
|
||||||
@@ -39,7 +47,6 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
|
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
|
||||||
import com.android.server.appsearch.external.localstorage.converter.ResultCodeToProtoConverter;
|
import com.android.server.appsearch.external.localstorage.converter.ResultCodeToProtoConverter;
|
||||||
import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
|
import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
|
||||||
@@ -66,7 +73,6 @@ import com.google.android.icing.proto.OptimizeResultProto;
|
|||||||
import com.google.android.icing.proto.PersistToDiskResultProto;
|
import com.google.android.icing.proto.PersistToDiskResultProto;
|
||||||
import com.google.android.icing.proto.PersistType;
|
import com.google.android.icing.proto.PersistType;
|
||||||
import com.google.android.icing.proto.PropertyConfigProto;
|
import com.google.android.icing.proto.PropertyConfigProto;
|
||||||
import com.google.android.icing.proto.PropertyProto;
|
|
||||||
import com.google.android.icing.proto.PutResultProto;
|
import com.google.android.icing.proto.PutResultProto;
|
||||||
import com.google.android.icing.proto.ReportUsageResultProto;
|
import com.google.android.icing.proto.ReportUsageResultProto;
|
||||||
import com.google.android.icing.proto.ResetResultProto;
|
import com.google.android.icing.proto.ResetResultProto;
|
||||||
@@ -89,6 +95,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
@@ -132,10 +139,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
public final class AppSearchImpl implements Closeable {
|
public final class AppSearchImpl implements Closeable {
|
||||||
private static final String TAG = "AppSearchImpl";
|
private static final String TAG = "AppSearchImpl";
|
||||||
|
|
||||||
@VisibleForTesting static final char DATABASE_DELIMITER = '/';
|
|
||||||
|
|
||||||
@VisibleForTesting static final char PACKAGE_DELIMITER = '$';
|
|
||||||
|
|
||||||
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
|
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
|
||||||
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
|
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
|
||||||
@VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
|
@VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
|
||||||
@@ -148,11 +151,12 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
@GuardedBy("mReadWriteLock")
|
@GuardedBy("mReadWriteLock")
|
||||||
private final VisibilityStore mVisibilityStoreLocked;
|
private final VisibilityStore mVisibilityStoreLocked;
|
||||||
|
|
||||||
// This map contains schemaTypes for all package-database prefixes. All values in the map are
|
// This map contains schema types and SchemaTypeConfigProtos for all package-database
|
||||||
// prefixed with the package-database prefix.
|
// prefixes. It maps each package-database prefix to an inner-map. The inner-map maps each
|
||||||
// TODO(b/172360376): Check if this can be replaced with an ArrayMap
|
// prefixed schema type to its respective SchemaTypeConfigProto.
|
||||||
@GuardedBy("mReadWriteLock")
|
@GuardedBy("mReadWriteLock")
|
||||||
private final Map<String, Set<String>> mSchemaMapLocked = new HashMap<>();
|
private final Map<String, Map<String, SchemaTypeConfigProto>> mSchemaMapLocked =
|
||||||
|
new ArrayMap<>();
|
||||||
|
|
||||||
// This map contains namespaces for all package-database prefixes. All values in the map are
|
// This map contains namespaces for all package-database prefixes. All values in the map are
|
||||||
// prefixed with the package-database prefix.
|
// prefixed with the package-database prefix.
|
||||||
@@ -182,9 +186,9 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
int userId,
|
int userId,
|
||||||
@NonNull String globalQuerierPackage)
|
@NonNull String globalQuerierPackage)
|
||||||
throws AppSearchException {
|
throws AppSearchException {
|
||||||
Preconditions.checkNotNull(icingDir);
|
Objects.requireNonNull(icingDir);
|
||||||
Preconditions.checkNotNull(context);
|
Objects.requireNonNull(context);
|
||||||
Preconditions.checkNotNull(globalQuerierPackage);
|
Objects.requireNonNull(globalQuerierPackage);
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
new AppSearchImpl(icingDir, context, userId, globalQuerierPackage);
|
new AppSearchImpl(icingDir, context, userId, globalQuerierPackage);
|
||||||
appSearchImpl.initializeVisibilityStore();
|
appSearchImpl.initializeVisibilityStore();
|
||||||
@@ -229,7 +233,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
// Populate schema map
|
// Populate schema map
|
||||||
for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
|
for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
|
||||||
String prefixedSchemaType = schema.getSchemaType();
|
String prefixedSchemaType = schema.getSchemaType();
|
||||||
addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), prefixedSchemaType);
|
addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate namespace map
|
// Populate namespace map
|
||||||
@@ -278,7 +282,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
persistToDisk();
|
persistToDisk(PersistType.Code.FULL);
|
||||||
mIcingSearchEngineLocked.close();
|
mIcingSearchEngineLocked.close();
|
||||||
mClosedLocked = true;
|
mClosedLocked = true;
|
||||||
} catch (AppSearchException e) {
|
} catch (AppSearchException e) {
|
||||||
@@ -364,7 +368,14 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update derived data structures.
|
// Update derived data structures.
|
||||||
mSchemaMapLocked.put(prefix, rewrittenSchemaResults.mRewrittenPrefixedTypes);
|
for (SchemaTypeConfigProto schemaTypeConfigProto :
|
||||||
|
rewrittenSchemaResults.mRewrittenPrefixedTypes.values()) {
|
||||||
|
addToMap(mSchemaMapLocked, prefix, schemaTypeConfigProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String schemaType : rewrittenSchemaResults.mDeletedPrefixedTypes) {
|
||||||
|
removeFromMap(mSchemaMapLocked, prefix, schemaType);
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> prefixedSchemasNotPlatformSurfaceable =
|
Set<String> prefixedSchemasNotPlatformSurfaceable =
|
||||||
new ArraySet<>(schemasNotPlatformSurfaceable.size());
|
new ArraySet<>(schemasNotPlatformSurfaceable.size());
|
||||||
@@ -586,7 +597,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
mReadWriteLock.readLock().lock();
|
mReadWriteLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
throwIfClosedLocked();
|
throwIfClosedLocked();
|
||||||
|
String prefix = createPrefix(packageName, databaseName);
|
||||||
List<TypePropertyMask> nonPrefixedPropertyMasks =
|
List<TypePropertyMask> nonPrefixedPropertyMasks =
|
||||||
TypePropertyPathToProtoConverter.toTypePropertyMaskList(typePropertyPaths);
|
TypePropertyPathToProtoConverter.toTypePropertyMaskList(typePropertyPaths);
|
||||||
List<TypePropertyMask> prefixedPropertyMasks =
|
List<TypePropertyMask> prefixedPropertyMasks =
|
||||||
@@ -597,7 +608,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
String prefixedType =
|
String prefixedType =
|
||||||
nonPrefixedType.equals(GetByUriRequest.PROJECTION_SCHEMA_TYPE_WILDCARD)
|
nonPrefixedType.equals(GetByUriRequest.PROJECTION_SCHEMA_TYPE_WILDCARD)
|
||||||
? nonPrefixedType
|
? nonPrefixedType
|
||||||
: createPrefix(packageName, databaseName) + nonPrefixedType;
|
: prefix + nonPrefixedType;
|
||||||
prefixedPropertyMasks.add(
|
prefixedPropertyMasks.add(
|
||||||
typePropertyMask.toBuilder().setSchemaType(prefixedType).build());
|
typePropertyMask.toBuilder().setSchemaType(prefixedType).build());
|
||||||
}
|
}
|
||||||
@@ -607,15 +618,17 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
GetResultProto getResultProto =
|
GetResultProto getResultProto =
|
||||||
mIcingSearchEngineLocked.get(
|
mIcingSearchEngineLocked.get(prefix + namespace, uri, getResultSpec);
|
||||||
createPrefix(packageName, databaseName) + namespace,
|
|
||||||
uri,
|
|
||||||
getResultSpec);
|
|
||||||
checkSuccess(getResultProto.getStatus());
|
checkSuccess(getResultProto.getStatus());
|
||||||
|
|
||||||
|
// The schema type map cannot be null at this point. It could only be null if no
|
||||||
|
// schema had ever been set for that prefix. Given we have retrieved a document from
|
||||||
|
// the index, we know a schema had to have been set.
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaTypeMap = mSchemaMapLocked.get(prefix);
|
||||||
DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
|
DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
|
||||||
removePrefixesFromDocument(documentBuilder);
|
removePrefixesFromDocument(documentBuilder);
|
||||||
return GenericDocumentToProtoConverter.toGenericDocument(documentBuilder.build());
|
return GenericDocumentToProtoConverter.toGenericDocument(
|
||||||
|
documentBuilder.build(), prefix, schemaTypeMap);
|
||||||
} finally {
|
} finally {
|
||||||
mReadWriteLock.readLock().unlock();
|
mReadWriteLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
@@ -726,7 +739,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Client didn't specify certain schemas to search over, check all schemas
|
// Client didn't specify certain schemas to search over, check all schemas
|
||||||
Set<String> prefixedSchemas = mSchemaMapLocked.get(prefix);
|
Set<String> prefixedSchemas = mSchemaMapLocked.get(prefix).keySet();
|
||||||
if (prefixedSchemas != null) {
|
if (prefixedSchemas != null) {
|
||||||
for (String prefixedSchema : prefixedSchemas) {
|
for (String prefixedSchema : prefixedSchemas) {
|
||||||
if (packageName.equals(callerPackageName)
|
if (packageName.equals(callerPackageName)
|
||||||
@@ -816,7 +829,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
searchSpecBuilder.build(), scoringSpec, resultSpecBuilder.build());
|
searchSpecBuilder.build(), scoringSpec, resultSpecBuilder.build());
|
||||||
checkSuccess(searchResultProto.getStatus());
|
checkSuccess(searchResultProto.getStatus());
|
||||||
|
|
||||||
return rewriteSearchResultProto(searchResultProto);
|
return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -838,7 +851,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
SearchResultProto searchResultProto =
|
SearchResultProto searchResultProto =
|
||||||
mIcingSearchEngineLocked.getNextPage(nextPageToken);
|
mIcingSearchEngineLocked.getNextPage(nextPageToken);
|
||||||
checkSuccess(searchResultProto.getStatus());
|
checkSuccess(searchResultProto.getStatus());
|
||||||
return rewriteSearchResultProto(searchResultProto);
|
return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
|
||||||
} finally {
|
} finally {
|
||||||
mReadWriteLock.readLock().unlock();
|
mReadWriteLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
@@ -1104,22 +1117,31 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* Persists all update/delete requests to the disk.
|
* Persists all update/delete requests to the disk.
|
||||||
*
|
*
|
||||||
* <p>If the app crashes after a call to PersistToDisk(), Icing would be able to fully recover
|
* <p>If the app crashes after a call to PersistToDisk with {@link PersistType.Code#FULL}, Icing
|
||||||
* all data written up to this point without a costly recovery process.
|
* would be able to fully recover all data written up to this point without a costly recovery
|
||||||
|
* process.
|
||||||
*
|
*
|
||||||
* <p>If the app crashes before a call to PersistToDisk(), Icing would trigger a costly recovery
|
* <p>If the app crashes after a call to PersistToDisk with {@link PersistType.Code#LITE}, Icing
|
||||||
* process in next initialization. After that, Icing would still be able to recover all written
|
* would trigger a costly recovery process in next initialization. After that, Icing would still
|
||||||
* data.
|
* be able to recover all written data - excepting Usage data. Usage data is only guaranteed to
|
||||||
|
* be safe after a call to PersistToDisk with {@link PersistType.Code#FULL}
|
||||||
*
|
*
|
||||||
|
* <p>If the app crashes after an update/delete request has been made, but before any call to
|
||||||
|
* PersistToDisk, then all data in Icing will be lost.
|
||||||
|
*
|
||||||
|
* @param persistType the amount of data to persist. {@link PersistType.Code#LITE} will only
|
||||||
|
* persist the minimal amount of data to ensure all data can be recovered. {@link
|
||||||
|
* PersistType.Code#FULL} will persist all data necessary to prevent data loss without
|
||||||
|
* needing data recovery.
|
||||||
* @throws AppSearchException on any error that AppSearch persist data to disk.
|
* @throws AppSearchException on any error that AppSearch persist data to disk.
|
||||||
*/
|
*/
|
||||||
public void persistToDisk() throws AppSearchException {
|
public void persistToDisk(@NonNull PersistType.Code persistType) throws AppSearchException {
|
||||||
mReadWriteLock.writeLock().lock();
|
mReadWriteLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
throwIfClosedLocked();
|
throwIfClosedLocked();
|
||||||
|
|
||||||
PersistToDiskResultProto persistToDiskResultProto =
|
PersistToDiskResultProto persistToDiskResultProto =
|
||||||
mIcingSearchEngineLocked.persistToDisk(PersistType.Code.FULL);
|
mIcingSearchEngineLocked.persistToDisk(persistType);
|
||||||
checkSuccess(persistToDiskResultProto.getStatus());
|
checkSuccess(persistToDiskResultProto.getStatus());
|
||||||
} finally {
|
} finally {
|
||||||
mReadWriteLock.writeLock().unlock();
|
mReadWriteLock.writeLock().unlock();
|
||||||
@@ -1189,8 +1211,8 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
// Any prefixed types that used to exist in the schema, but are deleted in the new one.
|
// Any prefixed types that used to exist in the schema, but are deleted in the new one.
|
||||||
final Set<String> mDeletedPrefixedTypes = new ArraySet<>();
|
final Set<String> mDeletedPrefixedTypes = new ArraySet<>();
|
||||||
|
|
||||||
// Prefixed types that were part of the new schema.
|
// Map of prefixed schema types to SchemaTypeConfigProtos that were part of the new schema.
|
||||||
final Set<String> mRewrittenPrefixedTypes = new ArraySet<>();
|
final Map<String, SchemaTypeConfigProto> mRewrittenPrefixedTypes = new ArrayMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1238,7 +1260,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
|
|
||||||
// newTypesToProto is modified below, so we need a copy first
|
// newTypesToProto is modified below, so we need a copy first
|
||||||
RewrittenSchemaResults rewrittenSchemaResults = new RewrittenSchemaResults();
|
RewrittenSchemaResults rewrittenSchemaResults = new RewrittenSchemaResults();
|
||||||
rewrittenSchemaResults.mRewrittenPrefixedTypes.addAll(newTypesToProto.keySet());
|
rewrittenSchemaResults.mRewrittenPrefixedTypes.putAll(newTypesToProto);
|
||||||
|
|
||||||
// Combine the existing schema (which may have types from other prefixes) with this
|
// Combine the existing schema (which may have types from other prefixes) with this
|
||||||
// prefix's new schema. Modifies the existingSchemaBuilder.
|
// prefix's new schema. Modifies the existingSchemaBuilder.
|
||||||
@@ -1263,99 +1285,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
return rewrittenSchemaResults;
|
return rewrittenSchemaResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepends {@code prefix} to all types and namespaces mentioned anywhere in {@code
|
|
||||||
* documentBuilder}.
|
|
||||||
*
|
|
||||||
* @param documentBuilder The document to mutate
|
|
||||||
* @param prefix The prefix to add
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
static void addPrefixToDocument(
|
|
||||||
@NonNull DocumentProto.Builder documentBuilder, @NonNull String prefix) {
|
|
||||||
// Rewrite the type name to include/remove the prefix.
|
|
||||||
String newSchema = prefix + documentBuilder.getSchema();
|
|
||||||
documentBuilder.setSchema(newSchema);
|
|
||||||
|
|
||||||
// Rewrite the namespace to include/remove the prefix.
|
|
||||||
documentBuilder.setNamespace(prefix + documentBuilder.getNamespace());
|
|
||||||
|
|
||||||
// Recurse into derived documents
|
|
||||||
for (int propertyIdx = 0;
|
|
||||||
propertyIdx < documentBuilder.getPropertiesCount();
|
|
||||||
propertyIdx++) {
|
|
||||||
int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount();
|
|
||||||
if (documentCount > 0) {
|
|
||||||
PropertyProto.Builder propertyBuilder =
|
|
||||||
documentBuilder.getProperties(propertyIdx).toBuilder();
|
|
||||||
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
|
|
||||||
DocumentProto.Builder derivedDocumentBuilder =
|
|
||||||
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
|
|
||||||
addPrefixToDocument(derivedDocumentBuilder, prefix);
|
|
||||||
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
|
|
||||||
}
|
|
||||||
documentBuilder.setProperties(propertyIdx, propertyBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes any prefixes from types and namespaces mentioned anywhere in {@code documentBuilder}.
|
|
||||||
*
|
|
||||||
* @param documentBuilder The document to mutate
|
|
||||||
* @return Prefix name that was removed from the document.
|
|
||||||
* @throws AppSearchException if there are unexpected database prefixing errors.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
@VisibleForTesting
|
|
||||||
static String removePrefixesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
|
|
||||||
throws AppSearchException {
|
|
||||||
// Rewrite the type name and namespace to remove the prefix.
|
|
||||||
String schemaPrefix = getPrefix(documentBuilder.getSchema());
|
|
||||||
String namespacePrefix = getPrefix(documentBuilder.getNamespace());
|
|
||||||
|
|
||||||
if (!schemaPrefix.equals(namespacePrefix)) {
|
|
||||||
throw new AppSearchException(
|
|
||||||
AppSearchResult.RESULT_INTERNAL_ERROR,
|
|
||||||
"Found unexpected"
|
|
||||||
+ " multiple prefix names in document: "
|
|
||||||
+ schemaPrefix
|
|
||||||
+ ", "
|
|
||||||
+ namespacePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
documentBuilder.setSchema(removePrefix(documentBuilder.getSchema()));
|
|
||||||
documentBuilder.setNamespace(removePrefix(documentBuilder.getNamespace()));
|
|
||||||
|
|
||||||
// Recurse into derived documents
|
|
||||||
for (int propertyIdx = 0;
|
|
||||||
propertyIdx < documentBuilder.getPropertiesCount();
|
|
||||||
propertyIdx++) {
|
|
||||||
int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount();
|
|
||||||
if (documentCount > 0) {
|
|
||||||
PropertyProto.Builder propertyBuilder =
|
|
||||||
documentBuilder.getProperties(propertyIdx).toBuilder();
|
|
||||||
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
|
|
||||||
DocumentProto.Builder derivedDocumentBuilder =
|
|
||||||
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
|
|
||||||
String nestedPrefix = removePrefixesFromDocument(derivedDocumentBuilder);
|
|
||||||
if (!nestedPrefix.equals(schemaPrefix)) {
|
|
||||||
throw new AppSearchException(
|
|
||||||
AppSearchResult.RESULT_INTERNAL_ERROR,
|
|
||||||
"Found unexpected multiple prefix names in document: "
|
|
||||||
+ schemaPrefix
|
|
||||||
+ ", "
|
|
||||||
+ nestedPrefix);
|
|
||||||
}
|
|
||||||
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
|
|
||||||
}
|
|
||||||
documentBuilder.setProperties(propertyIdx, propertyBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return schemaPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrites the search spec filters with {@code prefixes}.
|
* Rewrites the search spec filters with {@code prefixes}.
|
||||||
*
|
*
|
||||||
@@ -1443,9 +1372,9 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
|
|
||||||
if (allowedPrefixedSchemas.isEmpty()) {
|
if (allowedPrefixedSchemas.isEmpty()) {
|
||||||
// If the client didn't specify any schema filters, search over all of their schemas
|
// If the client didn't specify any schema filters, search over all of their schemas
|
||||||
Set<String> prefixedSchemas = mSchemaMapLocked.get(prefix);
|
Map<String, SchemaTypeConfigProto> prefixedSchemaMap = mSchemaMapLocked.get(prefix);
|
||||||
if (prefixedSchemas != null) {
|
if (prefixedSchemaMap != null) {
|
||||||
allowedPrefixedSchemas.addAll(prefixedSchemas);
|
allowedPrefixedSchemas.addAll(prefixedSchemaMap.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allowedPrefixedSchemas;
|
return allowedPrefixedSchemas;
|
||||||
@@ -1656,86 +1585,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
return mSchemaMapLocked.keySet();
|
return mSchemaMapLocked.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
static String createPrefix(@NonNull String packageName, @NonNull String databaseName) {
|
|
||||||
return createPackagePrefix(packageName) + databaseName + DATABASE_DELIMITER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static String createPackagePrefix(@NonNull String packageName) {
|
|
||||||
return packageName + PACKAGE_DELIMITER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the package name that's contained within the {@code prefix}.
|
|
||||||
*
|
|
||||||
* @param prefix Prefix string that contains the package name inside of it. The package name
|
|
||||||
* must be in the front of the string, and separated from the rest of the string by the
|
|
||||||
* {@link #PACKAGE_DELIMITER}.
|
|
||||||
* @return Valid package name.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private static String getPackageName(@NonNull String prefix) {
|
|
||||||
int delimiterIndex = prefix.indexOf(PACKAGE_DELIMITER);
|
|
||||||
if (delimiterIndex == -1) {
|
|
||||||
// This should never happen if we construct our prefixes properly
|
|
||||||
Log.wtf(TAG, "Malformed prefix doesn't contain package delimiter: " + prefix);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return prefix.substring(0, delimiterIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the database name that's contained within the {@code prefix}.
|
|
||||||
*
|
|
||||||
* @param prefix Prefix string that contains the database name inside of it. The database name
|
|
||||||
* must be between the {@link #PACKAGE_DELIMITER} and {@link #DATABASE_DELIMITER}
|
|
||||||
* @return Valid database name.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private static String getDatabaseName(@NonNull String prefix) {
|
|
||||||
int packageDelimiterIndex = prefix.indexOf(PACKAGE_DELIMITER);
|
|
||||||
int databaseDelimiterIndex = prefix.indexOf(DATABASE_DELIMITER);
|
|
||||||
if (packageDelimiterIndex == -1) {
|
|
||||||
// This should never happen if we construct our prefixes properly
|
|
||||||
Log.wtf(TAG, "Malformed prefix doesn't contain package delimiter: " + prefix);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (databaseDelimiterIndex == -1) {
|
|
||||||
// This should never happen if we construct our prefixes properly
|
|
||||||
Log.wtf(TAG, "Malformed prefix doesn't contain database delimiter: " + prefix);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return prefix.substring(packageDelimiterIndex + 1, databaseDelimiterIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static String removePrefix(@NonNull String prefixedString) throws AppSearchException {
|
|
||||||
// The prefix is made up of the package, then the database. So we only need to find the
|
|
||||||
// database cutoff.
|
|
||||||
int delimiterIndex;
|
|
||||||
if ((delimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER)) != -1) {
|
|
||||||
// Add 1 to include the char size of the DATABASE_DELIMITER
|
|
||||||
return prefixedString.substring(delimiterIndex + 1);
|
|
||||||
}
|
|
||||||
throw new AppSearchException(
|
|
||||||
AppSearchResult.RESULT_UNKNOWN_ERROR,
|
|
||||||
"The prefixed value doesn't contains a valid database name.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static String getPrefix(@NonNull String prefixedString) throws AppSearchException {
|
|
||||||
int databaseDelimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER);
|
|
||||||
if (databaseDelimiterIndex == -1) {
|
|
||||||
throw new AppSearchException(
|
|
||||||
AppSearchResult.RESULT_UNKNOWN_ERROR,
|
|
||||||
"The databaseName prefixed value doesn't contain a valid database name.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add 1 to include the char size of the DATABASE_DELIMITER
|
|
||||||
return prefixedString.substring(0, databaseDelimiterIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addToMap(
|
private static void addToMap(
|
||||||
Map<String, Set<String>> map, String prefix, String prefixedValue) {
|
Map<String, Set<String>> map, String prefix, String prefixedValue) {
|
||||||
Set<String> values = map.get(prefix);
|
Set<String> values = map.get(prefix);
|
||||||
@@ -1746,6 +1595,26 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
values.add(prefixedValue);
|
values.add(prefixedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addToMap(
|
||||||
|
Map<String, Map<String, SchemaTypeConfigProto>> map,
|
||||||
|
String prefix,
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto) {
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaTypeMap = map.get(prefix);
|
||||||
|
if (schemaTypeMap == null) {
|
||||||
|
schemaTypeMap = new ArrayMap<>();
|
||||||
|
map.put(prefix, schemaTypeMap);
|
||||||
|
}
|
||||||
|
schemaTypeMap.put(schemaTypeConfigProto.getSchemaType(), schemaTypeConfigProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void removeFromMap(
|
||||||
|
Map<String, Map<String, SchemaTypeConfigProto>> map, String prefix, String schemaType) {
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaTypeMap = map.get(prefix);
|
||||||
|
if (schemaTypeMap != null) {
|
||||||
|
schemaTypeMap.remove(schemaType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the given status code and throws an {@link AppSearchException} if code is an error.
|
* Checks the given status code and throws an {@link AppSearchException} if code is an error.
|
||||||
*
|
*
|
||||||
@@ -1853,7 +1722,9 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
/** Remove the rewritten schema types from any result documents. */
|
/** Remove the rewritten schema types from any result documents. */
|
||||||
@NonNull
|
@NonNull
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static SearchResultPage rewriteSearchResultProto(@NonNull SearchResultProto searchResultProto)
|
static SearchResultPage rewriteSearchResultProto(
|
||||||
|
@NonNull SearchResultProto searchResultProto,
|
||||||
|
@NonNull Map<String, Map<String, SchemaTypeConfigProto>> schemaMap)
|
||||||
throws AppSearchException {
|
throws AppSearchException {
|
||||||
// Parallel array of package names for each document search result.
|
// Parallel array of package names for each document search result.
|
||||||
List<String> packageNames = new ArrayList<>(searchResultProto.getResultsCount());
|
List<String> packageNames = new ArrayList<>(searchResultProto.getResultsCount());
|
||||||
@@ -1873,7 +1744,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
resultsBuilder.setResults(i, resultBuilder);
|
resultsBuilder.setResults(i, resultBuilder);
|
||||||
}
|
}
|
||||||
return SearchResultToProtoConverter.toSearchResultPage(
|
return SearchResultToProtoConverter.toSearchResultPage(
|
||||||
resultsBuilder, packageNames, databaseNames);
|
resultsBuilder, packageNames, databaseNames, schemaMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mReadWriteLock")
|
@GuardedBy("mReadWriteLock")
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ package com.android.server.appsearch.external.localstorage;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
|
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
|
||||||
|
|
||||||
import com.google.android.icing.proto.PutDocumentStatsProto;
|
import com.google.android.icing.proto.PutDocumentStatsProto;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class contains helper functions for logging.
|
* Class contains helper functions for logging.
|
||||||
*
|
*
|
||||||
@@ -42,8 +43,8 @@ public final class AppSearchLoggerHelper {
|
|||||||
static void copyNativeStats(
|
static void copyNativeStats(
|
||||||
@NonNull PutDocumentStatsProto fromNativeStats,
|
@NonNull PutDocumentStatsProto fromNativeStats,
|
||||||
@NonNull PutDocumentStats.Builder toStatsBuilder) {
|
@NonNull PutDocumentStats.Builder toStatsBuilder) {
|
||||||
Preconditions.checkNotNull(fromNativeStats);
|
Objects.requireNonNull(fromNativeStats);
|
||||||
Preconditions.checkNotNull(toStatsBuilder);
|
Objects.requireNonNull(toStatsBuilder);
|
||||||
toStatsBuilder
|
toStatsBuilder
|
||||||
.setNativeLatencyMillis(fromNativeStats.getLatencyMs())
|
.setNativeLatencyMillis(fromNativeStats.getLatencyMs())
|
||||||
.setNativeDocumentStoreLatencyMillis(fromNativeStats.getDocumentStoreLatencyMs())
|
.setNativeDocumentStoreLatencyMillis(fromNativeStats.getDocumentStoreLatencyMs())
|
||||||
|
|||||||
@@ -17,16 +17,18 @@
|
|||||||
package com.android.server.appsearch.external.localstorage.converter;
|
package com.android.server.appsearch.external.localstorage.converter;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.app.appsearch.AppSearchSchema;
|
||||||
import android.app.appsearch.GenericDocument;
|
import android.app.appsearch.GenericDocument;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import com.google.android.icing.proto.DocumentProto;
|
import com.google.android.icing.proto.DocumentProto;
|
||||||
import com.google.android.icing.proto.PropertyProto;
|
import com.google.android.icing.proto.PropertyProto;
|
||||||
|
import com.google.android.icing.proto.SchemaTypeConfigProto;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a {@link GenericDocument} into a {@link DocumentProto}.
|
* Translates a {@link GenericDocument} into a {@link DocumentProto}.
|
||||||
@@ -34,13 +36,20 @@ import java.util.Collections;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final class GenericDocumentToProtoConverter {
|
public final class GenericDocumentToProtoConverter {
|
||||||
|
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||||
|
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||||
|
private static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
|
||||||
|
private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
|
||||||
|
private static final byte[][] EMPTY_BYTES_ARRAY = new byte[0][0];
|
||||||
|
private static final GenericDocument[] EMPTY_DOCUMENT_ARRAY = new GenericDocument[0];
|
||||||
|
|
||||||
private GenericDocumentToProtoConverter() {}
|
private GenericDocumentToProtoConverter() {}
|
||||||
|
|
||||||
/** Converts a {@link GenericDocument} into a {@link DocumentProto}. */
|
/** Converts a {@link GenericDocument} into a {@link DocumentProto}. */
|
||||||
@NonNull
|
@NonNull
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static DocumentProto toDocumentProto(@NonNull GenericDocument document) {
|
public static DocumentProto toDocumentProto(@NonNull GenericDocument document) {
|
||||||
Preconditions.checkNotNull(document);
|
Objects.requireNonNull(document);
|
||||||
DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
|
DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
|
||||||
mProtoBuilder
|
mProtoBuilder
|
||||||
.setUri(document.getUri())
|
.setUri(document.getUri())
|
||||||
@@ -97,16 +106,34 @@ public final class GenericDocumentToProtoConverter {
|
|||||||
return mProtoBuilder.build();
|
return mProtoBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts a {@link DocumentProto} into a {@link GenericDocument}. */
|
/**
|
||||||
|
* Converts a {@link DocumentProto} into a {@link GenericDocument}.
|
||||||
|
*
|
||||||
|
* <p>In the case that the {@link DocumentProto} object proto has no values set, the converter
|
||||||
|
* searches for the matching property name in the {@link SchemaTypeConfigProto} object for the
|
||||||
|
* document, and infers the correct default value to set for the empty property based on the
|
||||||
|
* data type of the property defined by the schema type.
|
||||||
|
*
|
||||||
|
* @param proto the document to convert to a {@link GenericDocument} instance. The document
|
||||||
|
* proto should have its package + database prefix stripped from its fields.
|
||||||
|
* @param prefix the package + database prefix used searching the {@code schemaTypeMap}.
|
||||||
|
* @param schemaTypeMap map of prefixed schema type to {@link SchemaTypeConfigProto}, used for
|
||||||
|
* looking up the default empty value to set for a document property that has all empty
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static GenericDocument toGenericDocument(@NonNull DocumentProto proto) {
|
public static GenericDocument toGenericDocument(
|
||||||
Preconditions.checkNotNull(proto);
|
@NonNull DocumentProto proto,
|
||||||
|
@NonNull String prefix,
|
||||||
|
@NonNull Map<String, SchemaTypeConfigProto> schemaTypeMap) {
|
||||||
|
Objects.requireNonNull(proto);
|
||||||
GenericDocument.Builder<?> documentBuilder =
|
GenericDocument.Builder<?> documentBuilder =
|
||||||
new GenericDocument.Builder<>(
|
new GenericDocument.Builder<>(
|
||||||
proto.getNamespace(), proto.getUri(), proto.getSchema())
|
proto.getNamespace(), proto.getUri(), proto.getSchema())
|
||||||
.setScore(proto.getScore())
|
.setScore(proto.getScore())
|
||||||
.setTtlMillis(proto.getTtlMs())
|
.setTtlMillis(proto.getTtlMs())
|
||||||
.setCreationTimestampMillis(proto.getCreationTimestampMs());
|
.setCreationTimestampMillis(proto.getCreationTimestampMs());
|
||||||
|
String prefixedSchemaType = prefix + proto.getSchema();
|
||||||
|
|
||||||
for (int i = 0; i < proto.getPropertiesCount(); i++) {
|
for (int i = 0; i < proto.getPropertiesCount(); i++) {
|
||||||
PropertyProto property = proto.getProperties(i);
|
PropertyProto property = proto.getProperties(i);
|
||||||
@@ -144,13 +171,51 @@ public final class GenericDocumentToProtoConverter {
|
|||||||
} else if (property.getDocumentValuesCount() > 0) {
|
} else if (property.getDocumentValuesCount() > 0) {
|
||||||
GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()];
|
GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()];
|
||||||
for (int j = 0; j < values.length; j++) {
|
for (int j = 0; j < values.length; j++) {
|
||||||
values[j] = toGenericDocument(property.getDocumentValues(j));
|
values[j] =
|
||||||
|
toGenericDocument(property.getDocumentValues(j), prefix, schemaTypeMap);
|
||||||
}
|
}
|
||||||
documentBuilder.setPropertyDocument(name, values);
|
documentBuilder.setPropertyDocument(name, values);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Unknown type of value: " + name);
|
// TODO(b/184966497): Optimize by caching PropertyConfigProto
|
||||||
|
setEmptyProperty(name, documentBuilder, schemaTypeMap.get(prefixedSchemaType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return documentBuilder.build();
|
return documentBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setEmptyProperty(
|
||||||
|
@NonNull String propertyName,
|
||||||
|
@NonNull GenericDocument.Builder<?> documentBuilder,
|
||||||
|
@NonNull SchemaTypeConfigProto schema) {
|
||||||
|
@AppSearchSchema.PropertyConfig.DataType int dataType = 0;
|
||||||
|
for (int i = 0; i < schema.getPropertiesCount(); ++i) {
|
||||||
|
if (propertyName.equals(schema.getProperties(i).getPropertyName())) {
|
||||||
|
dataType = schema.getProperties(i).getDataType().getNumber();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dataType) {
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_STRING:
|
||||||
|
documentBuilder.setPropertyString(propertyName, EMPTY_STRING_ARRAY);
|
||||||
|
break;
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_INT64:
|
||||||
|
documentBuilder.setPropertyLong(propertyName, EMPTY_LONG_ARRAY);
|
||||||
|
break;
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_DOUBLE:
|
||||||
|
documentBuilder.setPropertyDouble(propertyName, EMPTY_DOUBLE_ARRAY);
|
||||||
|
break;
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_BOOLEAN:
|
||||||
|
documentBuilder.setPropertyBoolean(propertyName, EMPTY_BOOLEAN_ARRAY);
|
||||||
|
break;
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES:
|
||||||
|
documentBuilder.setPropertyBytes(propertyName, EMPTY_BYTES_ARRAY);
|
||||||
|
break;
|
||||||
|
case AppSearchSchema.PropertyConfig.DATA_TYPE_DOCUMENT:
|
||||||
|
documentBuilder.setPropertyDocument(propertyName, EMPTY_DOCUMENT_ARRAY);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Unknown type of value: " + propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import android.annotation.NonNull;
|
|||||||
import android.app.appsearch.AppSearchSchema;
|
import android.app.appsearch.AppSearchSchema;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import com.google.android.icing.proto.DocumentIndexingConfig;
|
import com.google.android.icing.proto.DocumentIndexingConfig;
|
||||||
import com.google.android.icing.proto.PropertyConfigProto;
|
import com.google.android.icing.proto.PropertyConfigProto;
|
||||||
import com.google.android.icing.proto.SchemaTypeConfigProto;
|
import com.google.android.icing.proto.SchemaTypeConfigProto;
|
||||||
@@ -30,6 +28,7 @@ import com.google.android.icing.proto.StringIndexingConfig;
|
|||||||
import com.google.android.icing.proto.TermMatchType;
|
import com.google.android.icing.proto.TermMatchType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}.
|
* Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}.
|
||||||
@@ -48,7 +47,7 @@ public final class SchemaToProtoConverter {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static SchemaTypeConfigProto toSchemaTypeConfigProto(
|
public static SchemaTypeConfigProto toSchemaTypeConfigProto(
|
||||||
@NonNull AppSearchSchema schema, int version) {
|
@NonNull AppSearchSchema schema, int version) {
|
||||||
Preconditions.checkNotNull(schema);
|
Objects.requireNonNull(schema);
|
||||||
SchemaTypeConfigProto.Builder protoBuilder =
|
SchemaTypeConfigProto.Builder protoBuilder =
|
||||||
SchemaTypeConfigProto.newBuilder()
|
SchemaTypeConfigProto.newBuilder()
|
||||||
.setSchemaType(schema.getSchemaType())
|
.setSchemaType(schema.getSchemaType())
|
||||||
@@ -64,7 +63,7 @@ public final class SchemaToProtoConverter {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private static PropertyConfigProto toPropertyConfigProto(
|
private static PropertyConfigProto toPropertyConfigProto(
|
||||||
@NonNull AppSearchSchema.PropertyConfig property) {
|
@NonNull AppSearchSchema.PropertyConfig property) {
|
||||||
Preconditions.checkNotNull(property);
|
Objects.requireNonNull(property);
|
||||||
PropertyConfigProto.Builder builder =
|
PropertyConfigProto.Builder builder =
|
||||||
PropertyConfigProto.newBuilder().setPropertyName(property.getName());
|
PropertyConfigProto.newBuilder().setPropertyName(property.getName());
|
||||||
|
|
||||||
@@ -116,7 +115,7 @@ public final class SchemaToProtoConverter {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static AppSearchSchema toAppSearchSchema(@NonNull SchemaTypeConfigProtoOrBuilder proto) {
|
public static AppSearchSchema toAppSearchSchema(@NonNull SchemaTypeConfigProtoOrBuilder proto) {
|
||||||
Preconditions.checkNotNull(proto);
|
Objects.requireNonNull(proto);
|
||||||
AppSearchSchema.Builder builder = new AppSearchSchema.Builder(proto.getSchemaType());
|
AppSearchSchema.Builder builder = new AppSearchSchema.Builder(proto.getSchemaType());
|
||||||
List<PropertyConfigProto> properties = proto.getPropertiesList();
|
List<PropertyConfigProto> properties = proto.getPropertiesList();
|
||||||
for (int i = 0; i < properties.size(); i++) {
|
for (int i = 0; i < properties.size(); i++) {
|
||||||
@@ -129,7 +128,7 @@ public final class SchemaToProtoConverter {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private static AppSearchSchema.PropertyConfig toPropertyConfig(
|
private static AppSearchSchema.PropertyConfig toPropertyConfig(
|
||||||
@NonNull PropertyConfigProto proto) {
|
@NonNull PropertyConfigProto proto) {
|
||||||
Preconditions.checkNotNull(proto);
|
Objects.requireNonNull(proto);
|
||||||
switch (proto.getDataType()) {
|
switch (proto.getDataType()) {
|
||||||
case STRING:
|
case STRING:
|
||||||
return toStringPropertyConfig(proto);
|
return toStringPropertyConfig(proto);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.server.appsearch.external.localstorage.converter;
|
package com.android.server.appsearch.external.localstorage.converter;
|
||||||
|
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.createPrefix;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.appsearch.GenericDocument;
|
import android.app.appsearch.GenericDocument;
|
||||||
import android.app.appsearch.SearchResult;
|
import android.app.appsearch.SearchResult;
|
||||||
@@ -24,6 +26,7 @@ import android.os.Bundle;
|
|||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import com.google.android.icing.proto.SchemaTypeConfigProto;
|
||||||
import com.google.android.icing.proto.SearchResultProto;
|
import com.google.android.icing.proto.SearchResultProto;
|
||||||
import com.google.android.icing.proto.SearchResultProtoOrBuilder;
|
import com.google.android.icing.proto.SearchResultProtoOrBuilder;
|
||||||
import com.google.android.icing.proto.SnippetMatchProto;
|
import com.google.android.icing.proto.SnippetMatchProto;
|
||||||
@@ -31,6 +34,7 @@ import com.google.android.icing.proto.SnippetProto;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a {@link SearchResultProto} into {@link SearchResult}s.
|
* Translates a {@link SearchResultProto} into {@link SearchResult}s.
|
||||||
@@ -49,13 +53,17 @@ public class SearchResultToProtoConverter {
|
|||||||
* @param databaseNames A parallel array of database names. The database name at index 'i' of
|
* @param databaseNames A parallel array of database names. The database name at index 'i' of
|
||||||
* this list shold be the database that indexed the document at index 'i' of
|
* this list shold be the database that indexed the document at index 'i' of
|
||||||
* proto.getResults(i).
|
* proto.getResults(i).
|
||||||
|
* @param schemaMap A map of prefixes to an inner-map of prefixed schema type to
|
||||||
|
* SchemaTypeConfigProtos, used for setting a default value for results with DocumentProtos
|
||||||
|
* that have empty values.
|
||||||
* @return {@link SearchResultPage} of results.
|
* @return {@link SearchResultPage} of results.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static SearchResultPage toSearchResultPage(
|
public static SearchResultPage toSearchResultPage(
|
||||||
@NonNull SearchResultProtoOrBuilder proto,
|
@NonNull SearchResultProtoOrBuilder proto,
|
||||||
@NonNull List<String> packageNames,
|
@NonNull List<String> packageNames,
|
||||||
@NonNull List<String> databaseNames) {
|
@NonNull List<String> databaseNames,
|
||||||
|
@NonNull Map<String, Map<String, SchemaTypeConfigProto>> schemaMap) {
|
||||||
Preconditions.checkArgument(
|
Preconditions.checkArgument(
|
||||||
proto.getResultsCount() == packageNames.size(),
|
proto.getResultsCount() == packageNames.size(),
|
||||||
"Size of results does not match the number of package names.");
|
"Size of results does not match the number of package names.");
|
||||||
@@ -63,8 +71,14 @@ public class SearchResultToProtoConverter {
|
|||||||
bundle.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, proto.getNextPageToken());
|
bundle.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, proto.getNextPageToken());
|
||||||
ArrayList<Bundle> resultBundles = new ArrayList<>(proto.getResultsCount());
|
ArrayList<Bundle> resultBundles = new ArrayList<>(proto.getResultsCount());
|
||||||
for (int i = 0; i < proto.getResultsCount(); i++) {
|
for (int i = 0; i < proto.getResultsCount(); i++) {
|
||||||
|
String prefix = createPrefix(packageNames.get(i), databaseNames.get(i));
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaTypeMap = schemaMap.get(prefix);
|
||||||
SearchResult result =
|
SearchResult result =
|
||||||
toSearchResult(proto.getResults(i), packageNames.get(i), databaseNames.get(i));
|
toSearchResult(
|
||||||
|
proto.getResults(i),
|
||||||
|
packageNames.get(i),
|
||||||
|
databaseNames.get(i),
|
||||||
|
schemaTypeMap);
|
||||||
resultBundles.add(result.getBundle());
|
resultBundles.add(result.getBundle());
|
||||||
}
|
}
|
||||||
bundle.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, resultBundles);
|
bundle.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, resultBundles);
|
||||||
@@ -77,15 +91,21 @@ public class SearchResultToProtoConverter {
|
|||||||
* @param proto The proto to be converted.
|
* @param proto The proto to be converted.
|
||||||
* @param packageName The package name associated with the document in {@code proto}.
|
* @param packageName The package name associated with the document in {@code proto}.
|
||||||
* @param databaseName The database name associated with the document in {@code proto}.
|
* @param databaseName The database name associated with the document in {@code proto}.
|
||||||
|
* @param schemaTypeToProtoMap A map of prefixed schema types to their corresponding
|
||||||
|
* SchemaTypeConfigProto, used for setting a default value for results with DocumentProtos
|
||||||
|
* that have empty values.
|
||||||
* @return A {@link SearchResult} bundle.
|
* @return A {@link SearchResult} bundle.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private static SearchResult toSearchResult(
|
private static SearchResult toSearchResult(
|
||||||
@NonNull SearchResultProto.ResultProtoOrBuilder proto,
|
@NonNull SearchResultProto.ResultProtoOrBuilder proto,
|
||||||
@NonNull String packageName,
|
@NonNull String packageName,
|
||||||
@NonNull String databaseName) {
|
@NonNull String databaseName,
|
||||||
|
@NonNull Map<String, SchemaTypeConfigProto> schemaTypeToProtoMap) {
|
||||||
|
String prefix = createPrefix(packageName, databaseName);
|
||||||
GenericDocument document =
|
GenericDocument document =
|
||||||
GenericDocumentToProtoConverter.toGenericDocument(proto.getDocument());
|
GenericDocumentToProtoConverter.toGenericDocument(
|
||||||
|
proto.getDocument(), prefix, schemaTypeToProtoMap);
|
||||||
SearchResult.Builder builder =
|
SearchResult.Builder builder =
|
||||||
new SearchResult.Builder(packageName, databaseName)
|
new SearchResult.Builder(packageName, databaseName)
|
||||||
.setGenericDocument(document)
|
.setGenericDocument(document)
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ package com.android.server.appsearch.external.localstorage.converter;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.appsearch.SearchSpec;
|
import android.app.appsearch.SearchSpec;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import com.google.android.icing.proto.ResultSpecProto;
|
import com.google.android.icing.proto.ResultSpecProto;
|
||||||
import com.google.android.icing.proto.ScoringSpecProto;
|
import com.google.android.icing.proto.ScoringSpecProto;
|
||||||
import com.google.android.icing.proto.SearchSpecProto;
|
import com.google.android.icing.proto.SearchSpecProto;
|
||||||
import com.google.android.icing.proto.TermMatchType;
|
import com.google.android.icing.proto.TermMatchType;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a {@link SearchSpec} into icing search protos.
|
* Translates a {@link SearchSpec} into icing search protos.
|
||||||
*
|
*
|
||||||
@@ -37,7 +37,7 @@ public final class SearchSpecToProtoConverter {
|
|||||||
/** Extracts {@link SearchSpecProto} information from a {@link SearchSpec}. */
|
/** Extracts {@link SearchSpecProto} information from a {@link SearchSpec}. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) {
|
public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) {
|
||||||
Preconditions.checkNotNull(spec);
|
Objects.requireNonNull(spec);
|
||||||
SearchSpecProto.Builder protoBuilder =
|
SearchSpecProto.Builder protoBuilder =
|
||||||
SearchSpecProto.newBuilder()
|
SearchSpecProto.newBuilder()
|
||||||
.addAllSchemaTypeFilters(spec.getFilterSchemas())
|
.addAllSchemaTypeFilters(spec.getFilterSchemas())
|
||||||
@@ -56,7 +56,7 @@ public final class SearchSpecToProtoConverter {
|
|||||||
/** Extracts {@link ResultSpecProto} information from a {@link SearchSpec}. */
|
/** Extracts {@link ResultSpecProto} information from a {@link SearchSpec}. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
|
public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
|
||||||
Preconditions.checkNotNull(spec);
|
Objects.requireNonNull(spec);
|
||||||
return ResultSpecProto.newBuilder()
|
return ResultSpecProto.newBuilder()
|
||||||
.setNumPerPage(spec.getResultCountPerPage())
|
.setNumPerPage(spec.getResultCountPerPage())
|
||||||
.setSnippetSpec(
|
.setSnippetSpec(
|
||||||
@@ -73,7 +73,7 @@ public final class SearchSpecToProtoConverter {
|
|||||||
/** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */
|
/** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ScoringSpecProto toScoringSpecProto(@NonNull SearchSpec spec) {
|
public static ScoringSpecProto toScoringSpecProto(@NonNull SearchSpec spec) {
|
||||||
Preconditions.checkNotNull(spec);
|
Objects.requireNonNull(spec);
|
||||||
ScoringSpecProto.Builder protoBuilder = ScoringSpecProto.newBuilder();
|
ScoringSpecProto.Builder protoBuilder = ScoringSpecProto.newBuilder();
|
||||||
|
|
||||||
@SearchSpec.Order int orderCode = spec.getOrder();
|
@SearchSpec.Order int orderCode = spec.getOrder();
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ package com.android.server.appsearch.external.localstorage.converter;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.appsearch.SetSchemaResponse;
|
import android.app.appsearch.SetSchemaResponse;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import com.google.android.icing.proto.SetSchemaResultProto;
|
import com.google.android.icing.proto.SetSchemaResultProto;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a {@link SetSchemaResultProto} into {@link SetSchemaResponse}.
|
* Translates a {@link SetSchemaResultProto} into {@link SetSchemaResponse}.
|
||||||
*
|
*
|
||||||
@@ -42,8 +42,8 @@ public class SetSchemaResponseToProtoConverter {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static SetSchemaResponse toSetSchemaResponse(
|
public static SetSchemaResponse toSetSchemaResponse(
|
||||||
@NonNull SetSchemaResultProto proto, @NonNull String prefix) {
|
@NonNull SetSchemaResultProto proto, @NonNull String prefix) {
|
||||||
Preconditions.checkNotNull(proto);
|
Objects.requireNonNull(proto);
|
||||||
Preconditions.checkNotNull(prefix);
|
Objects.requireNonNull(prefix);
|
||||||
SetSchemaResponse.Builder builder = new SetSchemaResponse.Builder();
|
SetSchemaResponse.Builder builder = new SetSchemaResponse.Builder();
|
||||||
|
|
||||||
for (int i = 0; i < proto.getDeletedSchemaTypesCount(); i++) {
|
for (int i = 0; i < proto.getDeletedSchemaTypesCount(); i++) {
|
||||||
|
|||||||
@@ -18,13 +18,12 @@ package com.android.server.appsearch.external.localstorage.converter;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import com.google.android.icing.proto.TypePropertyMask;
|
import com.google.android.icing.proto.TypePropertyMask;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a <code>Map<String, List<String>></code> into <code>List<TypePropertyMask></code>.
|
* Translates a <code>Map<String, List<String>></code> into <code>List<TypePropertyMask></code>.
|
||||||
@@ -38,7 +37,7 @@ public final class TypePropertyPathToProtoConverter {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static List<TypePropertyMask> toTypePropertyMaskList(
|
public static List<TypePropertyMask> toTypePropertyMaskList(
|
||||||
@NonNull Map<String, List<String>> typePropertyPaths) {
|
@NonNull Map<String, List<String>> typePropertyPaths) {
|
||||||
Preconditions.checkNotNull(typePropertyPaths);
|
Objects.requireNonNull(typePropertyPaths);
|
||||||
List<TypePropertyMask> typePropertyMasks = new ArrayList<>(typePropertyPaths.size());
|
List<TypePropertyMask> typePropertyMasks = new ArrayList<>(typePropertyPaths.size());
|
||||||
for (Map.Entry<String, List<String>> e : typePropertyPaths.entrySet()) {
|
for (Map.Entry<String, List<String>> e : typePropertyPaths.entrySet()) {
|
||||||
typePropertyMasks.add(
|
typePropertyMasks.add(
|
||||||
|
|||||||
@@ -19,10 +19,9 @@ package com.android.server.appsearch.external.localstorage.stats;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for setting basic information to log for all function calls.
|
* A class for setting basic information to log for all function calls.
|
||||||
@@ -75,8 +74,8 @@ public class CallStats {
|
|||||||
private final int mNumOperationsFailed;
|
private final int mNumOperationsFailed;
|
||||||
|
|
||||||
CallStats(@NonNull Builder builder) {
|
CallStats(@NonNull Builder builder) {
|
||||||
Preconditions.checkNotNull(builder);
|
Objects.requireNonNull(builder);
|
||||||
mGeneralStats = Preconditions.checkNotNull(builder.mGeneralStatsBuilder).build();
|
mGeneralStats = Objects.requireNonNull(builder.mGeneralStatsBuilder).build();
|
||||||
mCallType = builder.mCallType;
|
mCallType = builder.mCallType;
|
||||||
mEstimatedBinderLatencyMillis = builder.mEstimatedBinderLatencyMillis;
|
mEstimatedBinderLatencyMillis = builder.mEstimatedBinderLatencyMillis;
|
||||||
mNumOperationsSucceeded = builder.mNumOperationsSucceeded;
|
mNumOperationsSucceeded = builder.mNumOperationsSucceeded;
|
||||||
@@ -140,8 +139,8 @@ public class CallStats {
|
|||||||
|
|
||||||
/** Builder takes {@link GeneralStats.Builder}. */
|
/** Builder takes {@link GeneralStats.Builder}. */
|
||||||
public Builder(@NonNull String packageName, @NonNull String database) {
|
public Builder(@NonNull String packageName, @NonNull String database) {
|
||||||
Preconditions.checkNotNull(packageName);
|
Objects.requireNonNull(packageName);
|
||||||
Preconditions.checkNotNull(database);
|
Objects.requireNonNull(database);
|
||||||
mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database);
|
mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.android.server.appsearch.external.localstorage.stats;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.appsearch.AppSearchResult;
|
import android.app.appsearch.AppSearchResult;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for holding general logging information.
|
* A class for holding general logging information.
|
||||||
@@ -48,9 +48,9 @@ public final class GeneralStats {
|
|||||||
private final int mTotalLatencyMillis;
|
private final int mTotalLatencyMillis;
|
||||||
|
|
||||||
GeneralStats(@NonNull Builder builder) {
|
GeneralStats(@NonNull Builder builder) {
|
||||||
Preconditions.checkNotNull(builder);
|
Objects.requireNonNull(builder);
|
||||||
mPackageName = Preconditions.checkNotNull(builder.mPackageName);
|
mPackageName = Objects.requireNonNull(builder.mPackageName);
|
||||||
mDatabase = Preconditions.checkNotNull(builder.mDatabase);
|
mDatabase = Objects.requireNonNull(builder.mDatabase);
|
||||||
mStatusCode = builder.mStatusCode;
|
mStatusCode = builder.mStatusCode;
|
||||||
mTotalLatencyMillis = builder.mTotalLatencyMillis;
|
mTotalLatencyMillis = builder.mTotalLatencyMillis;
|
||||||
}
|
}
|
||||||
@@ -92,8 +92,8 @@ public final class GeneralStats {
|
|||||||
* @param database name of the database logging stats
|
* @param database name of the database logging stats
|
||||||
*/
|
*/
|
||||||
public Builder(@NonNull String packageName, @NonNull String database) {
|
public Builder(@NonNull String packageName, @NonNull String database) {
|
||||||
mPackageName = Preconditions.checkNotNull(packageName);
|
mPackageName = Objects.requireNonNull(packageName);
|
||||||
mDatabase = Preconditions.checkNotNull(database);
|
mDatabase = Objects.requireNonNull(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets status code returned from {@link AppSearchResult#getResultCode()} */
|
/** Sets status code returned from {@link AppSearchResult#getResultCode()} */
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package com.android.server.appsearch.external.localstorage.stats;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for holding detailed stats to log for each individual document put by a {@link
|
* A class for holding detailed stats to log for each individual document put by a {@link
|
||||||
@@ -60,8 +60,8 @@ public final class PutDocumentStats {
|
|||||||
private final boolean mNativeExceededMaxNumTokens;
|
private final boolean mNativeExceededMaxNumTokens;
|
||||||
|
|
||||||
PutDocumentStats(@NonNull Builder builder) {
|
PutDocumentStats(@NonNull Builder builder) {
|
||||||
Preconditions.checkNotNull(builder);
|
Objects.requireNonNull(builder);
|
||||||
mGeneralStats = Preconditions.checkNotNull(builder.mGeneralStatsBuilder).build();
|
mGeneralStats = Objects.requireNonNull(builder.mGeneralStatsBuilder).build();
|
||||||
mGenerateDocumentProtoLatencyMillis = builder.mGenerateDocumentProtoLatencyMillis;
|
mGenerateDocumentProtoLatencyMillis = builder.mGenerateDocumentProtoLatencyMillis;
|
||||||
mRewriteDocumentTypesLatencyMillis = builder.mRewriteDocumentTypesLatencyMillis;
|
mRewriteDocumentTypesLatencyMillis = builder.mRewriteDocumentTypesLatencyMillis;
|
||||||
mNativeLatencyMillis = builder.mNativeLatencyMillis;
|
mNativeLatencyMillis = builder.mNativeLatencyMillis;
|
||||||
@@ -142,8 +142,8 @@ public final class PutDocumentStats {
|
|||||||
|
|
||||||
/** Builder takes {@link GeneralStats.Builder}. */
|
/** Builder takes {@link GeneralStats.Builder}. */
|
||||||
public Builder(@NonNull String packageName, @NonNull String database) {
|
public Builder(@NonNull String packageName, @NonNull String database) {
|
||||||
Preconditions.checkNotNull(packageName);
|
Objects.requireNonNull(packageName);
|
||||||
Preconditions.checkNotNull(database);
|
Objects.requireNonNull(database);
|
||||||
mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database);
|
mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
229
apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java
vendored
Normal file
229
apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java
vendored
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.appsearch.external.localstorage.util;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.app.appsearch.AppSearchResult;
|
||||||
|
import android.app.appsearch.exceptions.AppSearchException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.google.android.icing.proto.DocumentProto;
|
||||||
|
import com.google.android.icing.proto.PropertyProto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides utility functions for working with package + database prefixes.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class PrefixUtil {
|
||||||
|
private static final String TAG = "AppSearchPrefixUtil";
|
||||||
|
|
||||||
|
@VisibleForTesting public static final char DATABASE_DELIMITER = '/';
|
||||||
|
|
||||||
|
@VisibleForTesting public static final char PACKAGE_DELIMITER = '$';
|
||||||
|
|
||||||
|
private PrefixUtil() {}
|
||||||
|
|
||||||
|
/** Creates prefix string for given package name and database name. */
|
||||||
|
@NonNull
|
||||||
|
public static String createPrefix(@NonNull String packageName, @NonNull String databaseName) {
|
||||||
|
return packageName + PACKAGE_DELIMITER + databaseName + DATABASE_DELIMITER;
|
||||||
|
}
|
||||||
|
/** Creates prefix string for given package name. */
|
||||||
|
@NonNull
|
||||||
|
public static String createPackagePrefix(@NonNull String packageName) {
|
||||||
|
return packageName + PACKAGE_DELIMITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package name that's contained within the {@code prefix}.
|
||||||
|
*
|
||||||
|
* @param prefix Prefix string that contains the package name inside of it. The package name
|
||||||
|
* must be in the front of the string, and separated from the rest of the string by the
|
||||||
|
* {@link #PACKAGE_DELIMITER}.
|
||||||
|
* @return Valid package name.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String getPackageName(@NonNull String prefix) {
|
||||||
|
int delimiterIndex = prefix.indexOf(PACKAGE_DELIMITER);
|
||||||
|
if (delimiterIndex == -1) {
|
||||||
|
// This should never happen if we construct our prefixes properly
|
||||||
|
Log.wtf(TAG, "Malformed prefix doesn't contain package delimiter: " + prefix);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return prefix.substring(0, delimiterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the database name that's contained within the {@code prefix}.
|
||||||
|
*
|
||||||
|
* @param prefix Prefix string that contains the database name inside of it. The database name
|
||||||
|
* must be between the {@link #PACKAGE_DELIMITER} and {@link #DATABASE_DELIMITER}
|
||||||
|
* @return Valid database name.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String getDatabaseName(@NonNull String prefix) {
|
||||||
|
// TODO (b/184050178) Start database delimiter index search from after package delimiter
|
||||||
|
int packageDelimiterIndex = prefix.indexOf(PACKAGE_DELIMITER);
|
||||||
|
int databaseDelimiterIndex = prefix.indexOf(DATABASE_DELIMITER);
|
||||||
|
if (packageDelimiterIndex == -1) {
|
||||||
|
// This should never happen if we construct our prefixes properly
|
||||||
|
Log.wtf(TAG, "Malformed prefix doesn't contain package delimiter: " + prefix);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (databaseDelimiterIndex == -1) {
|
||||||
|
// This should never happen if we construct our prefixes properly
|
||||||
|
Log.wtf(TAG, "Malformed prefix doesn't contain database delimiter: " + prefix);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return prefix.substring(packageDelimiterIndex + 1, databaseDelimiterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a string with the package and database prefix removed from the input string.
|
||||||
|
*
|
||||||
|
* @param prefixedString a string containing a package and database prefix.
|
||||||
|
* @return a string with the package and database prefix removed.
|
||||||
|
* @throws AppSearchException if the prefixed value does not contain a valid database name.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String removePrefix(@NonNull String prefixedString) throws AppSearchException {
|
||||||
|
// The prefix is made up of the package, then the database. So we only need to find the
|
||||||
|
// database cutoff.
|
||||||
|
int delimiterIndex;
|
||||||
|
if ((delimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER)) != -1) {
|
||||||
|
// Add 1 to include the char size of the DATABASE_DELIMITER
|
||||||
|
return prefixedString.substring(delimiterIndex + 1);
|
||||||
|
}
|
||||||
|
throw new AppSearchException(
|
||||||
|
AppSearchResult.RESULT_UNKNOWN_ERROR,
|
||||||
|
"The prefixed value doesn't contains a valid database name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a package and database prefix string from the input string.
|
||||||
|
*
|
||||||
|
* @param prefixedString a string containing a package and database prefix.
|
||||||
|
* @return a string with the package and database prefix
|
||||||
|
* @throws AppSearchException if the prefixed value does not contain a valid database name.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String getPrefix(@NonNull String prefixedString) throws AppSearchException {
|
||||||
|
int databaseDelimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER);
|
||||||
|
if (databaseDelimiterIndex == -1) {
|
||||||
|
throw new AppSearchException(
|
||||||
|
AppSearchResult.RESULT_UNKNOWN_ERROR,
|
||||||
|
"The databaseName prefixed value doesn't contain a valid database name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 1 to include the char size of the DATABASE_DELIMITER
|
||||||
|
return prefixedString.substring(0, databaseDelimiterIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepends {@code prefix} to all types and namespaces mentioned anywhere in {@code
|
||||||
|
* documentBuilder}.
|
||||||
|
*
|
||||||
|
* @param documentBuilder The document to mutate
|
||||||
|
* @param prefix The prefix to add
|
||||||
|
*/
|
||||||
|
public static void addPrefixToDocument(
|
||||||
|
@NonNull DocumentProto.Builder documentBuilder, @NonNull String prefix) {
|
||||||
|
// Rewrite the type name to include/remove the prefix.
|
||||||
|
String newSchema = prefix + documentBuilder.getSchema();
|
||||||
|
documentBuilder.setSchema(newSchema);
|
||||||
|
|
||||||
|
// Rewrite the namespace to include/remove the prefix.
|
||||||
|
documentBuilder.setNamespace(prefix + documentBuilder.getNamespace());
|
||||||
|
|
||||||
|
// Recurse into derived documents
|
||||||
|
for (int propertyIdx = 0;
|
||||||
|
propertyIdx < documentBuilder.getPropertiesCount();
|
||||||
|
propertyIdx++) {
|
||||||
|
int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount();
|
||||||
|
if (documentCount > 0) {
|
||||||
|
PropertyProto.Builder propertyBuilder =
|
||||||
|
documentBuilder.getProperties(propertyIdx).toBuilder();
|
||||||
|
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
|
||||||
|
DocumentProto.Builder derivedDocumentBuilder =
|
||||||
|
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
|
||||||
|
addPrefixToDocument(derivedDocumentBuilder, prefix);
|
||||||
|
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
|
||||||
|
}
|
||||||
|
documentBuilder.setProperties(propertyIdx, propertyBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any prefixes from types and namespaces mentioned anywhere in {@code documentBuilder}.
|
||||||
|
*
|
||||||
|
* @param documentBuilder The document to mutate
|
||||||
|
* @return Prefix name that was removed from the document.
|
||||||
|
* @throws AppSearchException if there are unexpected database prefixing errors.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String removePrefixesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
|
||||||
|
throws AppSearchException {
|
||||||
|
// Rewrite the type name and namespace to remove the prefix.
|
||||||
|
String schemaPrefix = getPrefix(documentBuilder.getSchema());
|
||||||
|
String namespacePrefix = getPrefix(documentBuilder.getNamespace());
|
||||||
|
|
||||||
|
if (!schemaPrefix.equals(namespacePrefix)) {
|
||||||
|
throw new AppSearchException(
|
||||||
|
AppSearchResult.RESULT_INTERNAL_ERROR,
|
||||||
|
"Found unexpected"
|
||||||
|
+ " multiple prefix names in document: "
|
||||||
|
+ schemaPrefix
|
||||||
|
+ ", "
|
||||||
|
+ namespacePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
documentBuilder.setSchema(removePrefix(documentBuilder.getSchema()));
|
||||||
|
documentBuilder.setNamespace(removePrefix(documentBuilder.getNamespace()));
|
||||||
|
|
||||||
|
// Recurse into derived documents
|
||||||
|
for (int propertyIdx = 0;
|
||||||
|
propertyIdx < documentBuilder.getPropertiesCount();
|
||||||
|
propertyIdx++) {
|
||||||
|
int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount();
|
||||||
|
if (documentCount > 0) {
|
||||||
|
PropertyProto.Builder propertyBuilder =
|
||||||
|
documentBuilder.getProperties(propertyIdx).toBuilder();
|
||||||
|
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
|
||||||
|
DocumentProto.Builder derivedDocumentBuilder =
|
||||||
|
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
|
||||||
|
String nestedPrefix = removePrefixesFromDocument(derivedDocumentBuilder);
|
||||||
|
if (!nestedPrefix.equals(schemaPrefix)) {
|
||||||
|
throw new AppSearchException(
|
||||||
|
AppSearchResult.RESULT_INTERNAL_ERROR,
|
||||||
|
"Found unexpected multiple prefix names in document: "
|
||||||
|
+ schemaPrefix
|
||||||
|
+ ", "
|
||||||
|
+ nestedPrefix);
|
||||||
|
}
|
||||||
|
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
|
||||||
|
}
|
||||||
|
documentBuilder.setProperties(propertyIdx, propertyBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return schemaPrefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
I925ec12f4901c7759976c344ba3428210aada8ad
|
If9d1d770d2327d7d0db7d82acfc54787b5de64bc
|
||||||
|
|||||||
@@ -187,9 +187,8 @@ public interface AppSearchSessionShim extends Closeable {
|
|||||||
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link #getByUri}
|
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link #getByUri}
|
||||||
* calls.
|
* calls.
|
||||||
*
|
*
|
||||||
* <p><b>NOTE:</b>By default, documents are removed via a soft delete operation. Once the
|
* <p>Once the database crosses the document count or byte usage threshold, removed documents
|
||||||
* document crosses the count threshold or byte usage threshold, the documents will be removed
|
* will be deleted from disk.
|
||||||
* from disk.
|
|
||||||
*
|
*
|
||||||
* @param request {@link RemoveByUriRequest} with URIs and namespace to remove from the index.
|
* @param request {@link RemoveByUriRequest} with URIs and namespace to remove from the index.
|
||||||
* @return a {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
|
* @return a {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
|
||||||
|
|||||||
41
core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java
vendored
Normal file
41
core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.junit.Test;
|
||||||
|
|
||||||
|
public class AppSearchResultTest {
|
||||||
|
@Test
|
||||||
|
public void testMapNullPointerException() {
|
||||||
|
NullPointerException e =
|
||||||
|
expectThrows(
|
||||||
|
NullPointerException.class,
|
||||||
|
() -> {
|
||||||
|
Object o = null;
|
||||||
|
o.toString();
|
||||||
|
});
|
||||||
|
AppSearchResult<?> result = AppSearchResult.throwableToFailedResult(e);
|
||||||
|
assertThat(result.getResultCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
|
||||||
|
// Makes sure the exception name is included in the string. Some exceptions have terse or
|
||||||
|
// missing strings so it's confusing to read the output without the exception name.
|
||||||
|
assertThat(result.getErrorMessage()).startsWith("NullPointerException");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,8 @@ import android.content.pm.PackageManager;
|
|||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
@@ -203,7 +205,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
||||||
|
|
||||||
// Set schema1
|
// Set schema1
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
@@ -280,7 +282,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
|
mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
|
||||||
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
||||||
|
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
@@ -353,7 +355,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetSchema_defaultPlatformVisible() throws Exception {
|
public void testSetSchema_defaultPlatformVisible() throws Exception {
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
@@ -372,7 +374,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetSchema_platformHidden() throws Exception {
|
public void testSetSchema_platformHidden() throws Exception {
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
@@ -391,7 +393,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetSchema_defaultNotPackageAccessible() throws Exception {
|
public void testSetSchema_defaultNotPackageAccessible() throws Exception {
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
@@ -419,7 +421,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
|
mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
|
||||||
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
|
||||||
|
|
||||||
String prefix = AppSearchImpl.createPrefix("package", "database");
|
String prefix = PrefixUtil.createPrefix("package", "database");
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import android.content.pm.PackageManager;
|
|||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
@@ -78,13 +80,9 @@ public class VisibilityStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidPackageName() {
|
public void testValidPackageName() {
|
||||||
assertThat(VisibilityStore.PACKAGE_NAME)
|
assertThat(VisibilityStore.PACKAGE_NAME)
|
||||||
.doesNotContain(
|
.doesNotContain(String.valueOf(PrefixUtil.PACKAGE_DELIMITER));
|
||||||
"" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
|
|
||||||
assertThat(VisibilityStore.PACKAGE_NAME)
|
assertThat(VisibilityStore.PACKAGE_NAME)
|
||||||
.doesNotContain(
|
.doesNotContain(String.valueOf(PrefixUtil.DATABASE_DELIMITER));
|
||||||
""
|
|
||||||
+ AppSearchImpl
|
|
||||||
.DATABASE_DELIMITER); // Convert the chars to CharSequences
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,13 +91,9 @@ public class VisibilityStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidDatabaseName() {
|
public void testValidDatabaseName() {
|
||||||
assertThat(VisibilityStore.DATABASE_NAME)
|
assertThat(VisibilityStore.DATABASE_NAME)
|
||||||
.doesNotContain(
|
.doesNotContain(String.valueOf(PrefixUtil.PACKAGE_DELIMITER));
|
||||||
"" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
|
|
||||||
assertThat(VisibilityStore.DATABASE_NAME)
|
assertThat(VisibilityStore.DATABASE_NAME)
|
||||||
.doesNotContain(
|
.doesNotContain(String.valueOf(PrefixUtil.DATABASE_DELIMITER));
|
||||||
""
|
|
||||||
+ AppSearchImpl
|
|
||||||
.DATABASE_DELIMITER); // Convert the chars to CharSequences
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.server.appsearch.external.localstorage;
|
package com.android.server.appsearch.external.localstorage;
|
||||||
|
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.addPrefixToDocument;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.createPrefix;
|
||||||
|
import static com.android.server.appsearch.external.localstorage.util.PrefixUtil.removePrefixesFromDocument;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.testng.Assert.expectThrows;
|
import static org.testng.Assert.expectThrows;
|
||||||
@@ -35,8 +39,10 @@ import android.util.ArraySet;
|
|||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
|
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
|
||||||
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
import com.android.server.appsearch.proto.DocumentProto;
|
import com.android.server.appsearch.proto.DocumentProto;
|
||||||
import com.android.server.appsearch.proto.GetOptimizeInfoResultProto;
|
import com.android.server.appsearch.proto.GetOptimizeInfoResultProto;
|
||||||
|
import com.android.server.appsearch.proto.PersistType;
|
||||||
import com.android.server.appsearch.proto.PropertyConfigProto;
|
import com.android.server.appsearch.proto.PropertyConfigProto;
|
||||||
import com.android.server.appsearch.proto.PropertyProto;
|
import com.android.server.appsearch.proto.PropertyProto;
|
||||||
import com.android.server.appsearch.proto.SchemaProto;
|
import com.android.server.appsearch.proto.SchemaProto;
|
||||||
@@ -47,6 +53,7 @@ import com.android.server.appsearch.proto.StringIndexingConfig;
|
|||||||
import com.android.server.appsearch.proto.TermMatchType;
|
import com.android.server.appsearch.proto.TermMatchType;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -54,6 +61,7 @@ import org.junit.Rule;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -96,56 +104,71 @@ public class AppSearchImplTest {
|
|||||||
// Create a copy so we can modify it.
|
// Create a copy so we can modify it.
|
||||||
List<SchemaTypeConfigProto> existingTypes =
|
List<SchemaTypeConfigProto> existingTypes =
|
||||||
new ArrayList<>(existingSchemaBuilder.getTypesList());
|
new ArrayList<>(existingSchemaBuilder.getTypesList());
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto1 =
|
||||||
SchemaProto newSchema =
|
SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build();
|
||||||
SchemaProto.newBuilder()
|
SchemaTypeConfigProto schemaTypeConfigProto2 =
|
||||||
.addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build())
|
SchemaTypeConfigProto.newBuilder()
|
||||||
.addTypes(
|
.setSchemaType("TestType")
|
||||||
SchemaTypeConfigProto.newBuilder()
|
.addProperties(
|
||||||
.setSchemaType("TestType")
|
PropertyConfigProto.newBuilder()
|
||||||
.addProperties(
|
.setPropertyName("subject")
|
||||||
PropertyConfigProto.newBuilder()
|
.setDataType(PropertyConfigProto.DataType.Code.STRING)
|
||||||
.setPropertyName("subject")
|
.setCardinality(
|
||||||
.setDataType(
|
PropertyConfigProto.Cardinality.Code.OPTIONAL)
|
||||||
PropertyConfigProto.DataType.Code
|
.setStringIndexingConfig(
|
||||||
.STRING)
|
StringIndexingConfig.newBuilder()
|
||||||
.setCardinality(
|
.setTokenizerType(
|
||||||
PropertyConfigProto.Cardinality.Code
|
StringIndexingConfig.TokenizerType
|
||||||
.OPTIONAL)
|
.Code.PLAIN)
|
||||||
.setStringIndexingConfig(
|
.setTermMatchType(TermMatchType.Code.PREFIX)
|
||||||
StringIndexingConfig.newBuilder()
|
|
||||||
.setTokenizerType(
|
|
||||||
StringIndexingConfig
|
|
||||||
.TokenizerType
|
|
||||||
.Code.PLAIN)
|
|
||||||
.setTermMatchType(
|
|
||||||
TermMatchType.Code
|
|
||||||
.PREFIX)
|
|
||||||
.build())
|
|
||||||
.build())
|
|
||||||
.addProperties(
|
|
||||||
PropertyConfigProto.newBuilder()
|
|
||||||
.setPropertyName("link")
|
|
||||||
.setDataType(
|
|
||||||
PropertyConfigProto.DataType.Code
|
|
||||||
.DOCUMENT)
|
|
||||||
.setCardinality(
|
|
||||||
PropertyConfigProto.Cardinality.Code
|
|
||||||
.OPTIONAL)
|
|
||||||
.setSchemaType("RefType")
|
|
||||||
.build())
|
.build())
|
||||||
.build())
|
.build())
|
||||||
|
.addProperties(
|
||||||
|
PropertyConfigProto.newBuilder()
|
||||||
|
.setPropertyName("link")
|
||||||
|
.setDataType(PropertyConfigProto.DataType.Code.DOCUMENT)
|
||||||
|
.setCardinality(
|
||||||
|
PropertyConfigProto.Cardinality.Code.OPTIONAL)
|
||||||
|
.setSchemaType("RefType")
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto3 =
|
||||||
|
SchemaTypeConfigProto.newBuilder().setSchemaType("RefType").build();
|
||||||
|
SchemaProto newSchema =
|
||||||
|
SchemaProto.newBuilder()
|
||||||
|
.addTypes(schemaTypeConfigProto1)
|
||||||
|
.addTypes(schemaTypeConfigProto2)
|
||||||
|
.addTypes(schemaTypeConfigProto3)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
mAppSearchImpl.rewriteSchema(
|
||||||
AppSearchImpl.createPrefix("package", "newDatabase"),
|
createPrefix("package", "newDatabase"), existingSchemaBuilder, newSchema);
|
||||||
existingSchemaBuilder,
|
|
||||||
newSchema);
|
|
||||||
|
|
||||||
// We rewrote all the new types that were added. And nothing was removed.
|
// We rewrote all the new types that were added. And nothing was removed.
|
||||||
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
|
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes.keySet())
|
||||||
.containsExactly("package$newDatabase/Foo", "package$newDatabase/TestType");
|
.containsExactly(
|
||||||
|
"package$newDatabase/Foo",
|
||||||
|
"package$newDatabase/TestType",
|
||||||
|
"package$newDatabase/RefType");
|
||||||
|
assertThat(
|
||||||
|
rewrittenSchemaResults
|
||||||
|
.mRewrittenPrefixedTypes
|
||||||
|
.get("package$newDatabase/Foo")
|
||||||
|
.getSchemaType())
|
||||||
|
.isEqualTo("package$newDatabase/Foo");
|
||||||
|
assertThat(
|
||||||
|
rewrittenSchemaResults
|
||||||
|
.mRewrittenPrefixedTypes
|
||||||
|
.get("package$newDatabase/TestType")
|
||||||
|
.getSchemaType())
|
||||||
|
.isEqualTo("package$newDatabase/TestType");
|
||||||
|
assertThat(
|
||||||
|
rewrittenSchemaResults
|
||||||
|
.mRewrittenPrefixedTypes
|
||||||
|
.get("package$newDatabase/RefType")
|
||||||
|
.getSchemaType())
|
||||||
|
.isEqualTo("package$newDatabase/RefType");
|
||||||
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
|
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
|
||||||
|
|
||||||
SchemaProto expectedSchema =
|
SchemaProto expectedSchema =
|
||||||
@@ -190,6 +213,10 @@ public class AppSearchImplTest {
|
|||||||
"package$newDatabase/RefType")
|
"package$newDatabase/RefType")
|
||||||
.build())
|
.build())
|
||||||
.build())
|
.build())
|
||||||
|
.addTypes(
|
||||||
|
SchemaTypeConfigProto.newBuilder()
|
||||||
|
.setSchemaType("package$newDatabase/RefType")
|
||||||
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
existingTypes.addAll(expectedSchema.getTypesList());
|
existingTypes.addAll(expectedSchema.getTypesList());
|
||||||
@@ -216,12 +243,12 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
mAppSearchImpl.rewriteSchema(
|
||||||
AppSearchImpl.createPrefix("package", "existingDatabase"),
|
createPrefix("package", "existingDatabase"),
|
||||||
existingSchemaBuilder,
|
existingSchemaBuilder,
|
||||||
newSchema);
|
newSchema);
|
||||||
|
|
||||||
// Nothing was removed, but the method did rewrite the type name.
|
// Nothing was removed, but the method did rewrite the type name.
|
||||||
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
|
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes.keySet())
|
||||||
.containsExactly("package$existingDatabase/Foo");
|
.containsExactly("package$existingDatabase/Foo");
|
||||||
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
|
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
|
||||||
|
|
||||||
@@ -251,14 +278,15 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
mAppSearchImpl.rewriteSchema(
|
||||||
AppSearchImpl.createPrefix("package", "existingDatabase"),
|
createPrefix("package", "existingDatabase"),
|
||||||
existingSchemaBuilder,
|
existingSchemaBuilder,
|
||||||
newSchema);
|
newSchema);
|
||||||
|
|
||||||
// Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the
|
// Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the
|
||||||
// new schema.
|
// new schema.
|
||||||
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
|
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
|
||||||
.containsExactly("package$existingDatabase/Bar");
|
.containsKey("package$existingDatabase/Bar");
|
||||||
|
assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes.keySet().size()).isEqualTo(1);
|
||||||
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes)
|
assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes)
|
||||||
.containsExactly("package$existingDatabase/Foo");
|
.containsExactly("package$existingDatabase/Foo");
|
||||||
|
|
||||||
@@ -308,8 +336,7 @@ public class AppSearchImplTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
||||||
mAppSearchImpl.addPrefixToDocument(
|
addPrefixToDocument(actualDocument, createPrefix("package", "databaseName"));
|
||||||
actualDocument, AppSearchImpl.createPrefix("package", "databaseName"));
|
|
||||||
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
|
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,8 +374,7 @@ public class AppSearchImplTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
||||||
assertThat(mAppSearchImpl.removePrefixesFromDocument(actualDocument))
|
assertThat(removePrefixesFromDocument(actualDocument)).isEqualTo("package$databaseName/");
|
||||||
.isEqualTo("package$databaseName/");
|
|
||||||
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
|
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,8 +391,7 @@ public class AppSearchImplTest {
|
|||||||
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
||||||
AppSearchException e =
|
AppSearchException e =
|
||||||
expectThrows(
|
expectThrows(
|
||||||
AppSearchException.class,
|
AppSearchException.class, () -> removePrefixesFromDocument(actualDocument));
|
||||||
() -> mAppSearchImpl.removePrefixesFromDocument(actualDocument));
|
|
||||||
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
|
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,8 +416,7 @@ public class AppSearchImplTest {
|
|||||||
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
DocumentProto.Builder actualDocument = documentProto.toBuilder();
|
||||||
AppSearchException e =
|
AppSearchException e =
|
||||||
expectThrows(
|
expectThrows(
|
||||||
AppSearchException.class,
|
AppSearchException.class, () -> removePrefixesFromDocument(actualDocument));
|
||||||
() -> mAppSearchImpl.removePrefixesFromDocument(actualDocument));
|
|
||||||
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
|
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +508,7 @@ public class AppSearchImplTest {
|
|||||||
// Rewrite SearchSpec
|
// Rewrite SearchSpec
|
||||||
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
||||||
searchSpecProto,
|
searchSpecProto,
|
||||||
Collections.singleton(AppSearchImpl.createPrefix("package", "database")),
|
Collections.singleton(createPrefix("package", "database")),
|
||||||
ImmutableSet.of("package$database/type"));
|
ImmutableSet.of("package$database/type"));
|
||||||
assertThat(searchSpecProto.getSchemaTypeFiltersList())
|
assertThat(searchSpecProto.getSchemaTypeFiltersList())
|
||||||
.containsExactly("package$database/type");
|
.containsExactly("package$database/type");
|
||||||
@@ -531,8 +555,7 @@ public class AppSearchImplTest {
|
|||||||
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
||||||
searchSpecProto,
|
searchSpecProto,
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
AppSearchImpl.createPrefix("package", "database1"),
|
createPrefix("package", "database1"), createPrefix("package", "database2")),
|
||||||
AppSearchImpl.createPrefix("package", "database2")),
|
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
"package$database1/typeA", "package$database1/typeB",
|
"package$database1/typeA", "package$database1/typeB",
|
||||||
"package$database2/typeA", "package$database2/typeB"));
|
"package$database2/typeA", "package$database2/typeB"));
|
||||||
@@ -573,8 +596,7 @@ public class AppSearchImplTest {
|
|||||||
assertThat(
|
assertThat(
|
||||||
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
|
||||||
searchSpecProto,
|
searchSpecProto,
|
||||||
Collections.singleton(
|
Collections.singleton(createPrefix("package", "database")),
|
||||||
AppSearchImpl.createPrefix("package", "database")),
|
|
||||||
/*allowedPrefixedSchemas=*/ Collections.emptySet()))
|
/*allowedPrefixedSchemas=*/ Collections.emptySet()))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
@@ -1082,7 +1104,7 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
// Has database1
|
// Has database1
|
||||||
Set<String> expectedPrefixes = new ArraySet<>(existingPrefixes);
|
Set<String> expectedPrefixes = new ArraySet<>(existingPrefixes);
|
||||||
expectedPrefixes.add(AppSearchImpl.createPrefix("package", "database1"));
|
expectedPrefixes.add(createPrefix("package", "database1"));
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
@@ -1094,7 +1116,7 @@ public class AppSearchImplTest {
|
|||||||
assertThat(mAppSearchImpl.getPrefixesLocked()).containsExactlyElementsIn(expectedPrefixes);
|
assertThat(mAppSearchImpl.getPrefixesLocked()).containsExactlyElementsIn(expectedPrefixes);
|
||||||
|
|
||||||
// Has both databases
|
// Has both databases
|
||||||
expectedPrefixes.add(AppSearchImpl.createPrefix("package", "database2"));
|
expectedPrefixes.add(createPrefix("package", "database2"));
|
||||||
mAppSearchImpl.setSchema(
|
mAppSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database2",
|
"database2",
|
||||||
@@ -1110,9 +1132,9 @@ public class AppSearchImplTest {
|
|||||||
public void testRewriteSearchResultProto() throws Exception {
|
public void testRewriteSearchResultProto() throws Exception {
|
||||||
final String prefix =
|
final String prefix =
|
||||||
"com.package.foo"
|
"com.package.foo"
|
||||||
+ AppSearchImpl.PACKAGE_DELIMITER
|
+ PrefixUtil.PACKAGE_DELIMITER
|
||||||
+ "databaseName"
|
+ "databaseName"
|
||||||
+ AppSearchImpl.DATABASE_DELIMITER;
|
+ PrefixUtil.DATABASE_DELIMITER;
|
||||||
final String uri = "uri";
|
final String uri = "uri";
|
||||||
final String namespace = prefix + "namespace";
|
final String namespace = prefix + "namespace";
|
||||||
final String schemaType = prefix + "schema";
|
final String schemaType = prefix + "schema";
|
||||||
@@ -1128,18 +1150,22 @@ public class AppSearchImplTest {
|
|||||||
SearchResultProto.ResultProto.newBuilder().setDocument(documentProto).build();
|
SearchResultProto.ResultProto.newBuilder().setDocument(documentProto).build();
|
||||||
SearchResultProto searchResultProto =
|
SearchResultProto searchResultProto =
|
||||||
SearchResultProto.newBuilder().addResults(resultProto).build();
|
SearchResultProto.newBuilder().addResults(resultProto).build();
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto =
|
||||||
|
SchemaTypeConfigProto.newBuilder().setSchemaType(schemaType).build();
|
||||||
|
Map<String, Map<String, SchemaTypeConfigProto>> schemaMap =
|
||||||
|
ImmutableMap.of(prefix, ImmutableMap.of(schemaType, schemaTypeConfigProto));
|
||||||
|
|
||||||
DocumentProto.Builder strippedDocumentProto = documentProto.toBuilder();
|
DocumentProto.Builder strippedDocumentProto = documentProto.toBuilder();
|
||||||
AppSearchImpl.removePrefixesFromDocument(strippedDocumentProto);
|
removePrefixesFromDocument(strippedDocumentProto);
|
||||||
SearchResultPage searchResultPage =
|
SearchResultPage searchResultPage =
|
||||||
AppSearchImpl.rewriteSearchResultProto(searchResultProto);
|
AppSearchImpl.rewriteSearchResultProto(searchResultProto, schemaMap);
|
||||||
for (SearchResult result : searchResultPage.getResults()) {
|
for (SearchResult result : searchResultPage.getResults()) {
|
||||||
assertThat(result.getPackageName()).isEqualTo("com.package.foo");
|
assertThat(result.getPackageName()).isEqualTo("com.package.foo");
|
||||||
assertThat(result.getDatabaseName()).isEqualTo("databaseName");
|
assertThat(result.getDatabaseName()).isEqualTo("databaseName");
|
||||||
assertThat(result.getGenericDocument())
|
assertThat(result.getGenericDocument())
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
GenericDocumentToProtoConverter.toGenericDocument(
|
GenericDocumentToProtoConverter.toGenericDocument(
|
||||||
strippedDocumentProto.build()));
|
strippedDocumentProto.build(), prefix, schemaMap.get(prefix)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,7 +1635,221 @@ public class AppSearchImplTest {
|
|||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> {
|
||||||
appSearchImpl.persistToDisk();
|
appSearchImpl.persistToDisk(PersistType.Code.FULL);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutPersistsWithLiteFlush() throws Exception {
|
||||||
|
// Setup the index
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
|
AppSearchImpl appSearchImpl =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
|
||||||
|
List<AppSearchSchema> schemas =
|
||||||
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
|
appSearchImpl.setSchema(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
schemas,
|
||||||
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
|
/*forceOverride=*/ false,
|
||||||
|
/*version=*/ 0);
|
||||||
|
|
||||||
|
// Add a document and persist it.
|
||||||
|
GenericDocument document =
|
||||||
|
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
|
||||||
|
appSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
|
||||||
|
appSearchImpl.persistToDisk(PersistType.Code.LITE);
|
||||||
|
|
||||||
|
GenericDocument getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri1", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document);
|
||||||
|
|
||||||
|
// That document should be visible even from another instance.
|
||||||
|
AppSearchImpl appSearchImpl2 =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
getResult =
|
||||||
|
appSearchImpl2.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri1", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeletePersistsWithLiteFlush() throws Exception {
|
||||||
|
// Setup the index
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
|
AppSearchImpl appSearchImpl =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
|
||||||
|
List<AppSearchSchema> schemas =
|
||||||
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
|
appSearchImpl.setSchema(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
schemas,
|
||||||
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
|
/*forceOverride=*/ false,
|
||||||
|
/*version=*/ 0);
|
||||||
|
|
||||||
|
// Add two documents and persist them.
|
||||||
|
GenericDocument document1 =
|
||||||
|
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
|
||||||
|
appSearchImpl.putDocument("package", "database", document1, /*logger=*/ null);
|
||||||
|
GenericDocument document2 =
|
||||||
|
new GenericDocument.Builder<>("namespace1", "uri2", "type").build();
|
||||||
|
appSearchImpl.putDocument("package", "database", document2, /*logger=*/ null);
|
||||||
|
appSearchImpl.persistToDisk(PersistType.Code.LITE);
|
||||||
|
|
||||||
|
GenericDocument getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri1", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document1);
|
||||||
|
getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
|
||||||
|
// Delete the first document
|
||||||
|
appSearchImpl.remove("package", "database", "namespace1", "uri1");
|
||||||
|
appSearchImpl.persistToDisk(PersistType.Code.LITE);
|
||||||
|
expectThrows(
|
||||||
|
AppSearchException.class,
|
||||||
|
() ->
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
"namespace1",
|
||||||
|
"uri1",
|
||||||
|
Collections.emptyMap()));
|
||||||
|
getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
|
||||||
|
// Only the second document should be retrievable from another instance.
|
||||||
|
AppSearchImpl appSearchImpl2 =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
expectThrows(
|
||||||
|
AppSearchException.class,
|
||||||
|
() ->
|
||||||
|
appSearchImpl2.getDocument(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
"namespace1",
|
||||||
|
"uri1",
|
||||||
|
Collections.emptyMap()));
|
||||||
|
getResult =
|
||||||
|
appSearchImpl2.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteByQueryPersistsWithLiteFlush() throws Exception {
|
||||||
|
// Setup the index
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
|
AppSearchImpl appSearchImpl =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
|
||||||
|
List<AppSearchSchema> schemas =
|
||||||
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
|
appSearchImpl.setSchema(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
schemas,
|
||||||
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
|
/*forceOverride=*/ false,
|
||||||
|
/*version=*/ 0);
|
||||||
|
|
||||||
|
// Add two documents and persist them.
|
||||||
|
GenericDocument document1 =
|
||||||
|
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
|
||||||
|
appSearchImpl.putDocument("package", "database", document1, /*logger=*/ null);
|
||||||
|
GenericDocument document2 =
|
||||||
|
new GenericDocument.Builder<>("namespace2", "uri2", "type").build();
|
||||||
|
appSearchImpl.putDocument("package", "database", document2, /*logger=*/ null);
|
||||||
|
appSearchImpl.persistToDisk(PersistType.Code.LITE);
|
||||||
|
|
||||||
|
GenericDocument getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace1", "uri1", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document1);
|
||||||
|
getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace2", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
|
||||||
|
// Delete the first document
|
||||||
|
appSearchImpl.removeByQuery(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
"",
|
||||||
|
new SearchSpec.Builder()
|
||||||
|
.addFilterNamespaces("namespace1")
|
||||||
|
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
|
||||||
|
.build());
|
||||||
|
appSearchImpl.persistToDisk(PersistType.Code.LITE);
|
||||||
|
expectThrows(
|
||||||
|
AppSearchException.class,
|
||||||
|
() ->
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
"namespace1",
|
||||||
|
"uri1",
|
||||||
|
Collections.emptyMap()));
|
||||||
|
getResult =
|
||||||
|
appSearchImpl.getDocument(
|
||||||
|
"package", "database", "namespace2", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
|
||||||
|
// Only the second document should be retrievable from another instance.
|
||||||
|
AppSearchImpl appSearchImpl2 =
|
||||||
|
AppSearchImpl.create(
|
||||||
|
appsearchDir,
|
||||||
|
context,
|
||||||
|
VisibilityStore.NO_OP_USER_ID,
|
||||||
|
/*globalQuerierPackage=*/ "");
|
||||||
|
expectThrows(
|
||||||
|
AppSearchException.class,
|
||||||
|
() ->
|
||||||
|
appSearchImpl2.getDocument(
|
||||||
|
"package",
|
||||||
|
"database",
|
||||||
|
"namespace1",
|
||||||
|
"uri1",
|
||||||
|
Collections.emptyMap()));
|
||||||
|
getResult =
|
||||||
|
appSearchImpl2.getDocument(
|
||||||
|
"package", "database", "namespace2", "uri2", Collections.emptyMap());
|
||||||
|
assertThat(getResult).isEqualTo(document2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,35 +21,50 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import android.app.appsearch.GenericDocument;
|
import android.app.appsearch.GenericDocument;
|
||||||
|
|
||||||
import com.android.server.appsearch.proto.DocumentProto;
|
import com.android.server.appsearch.proto.DocumentProto;
|
||||||
|
import com.android.server.appsearch.proto.PropertyConfigProto;
|
||||||
import com.android.server.appsearch.proto.PropertyProto;
|
import com.android.server.appsearch.proto.PropertyProto;
|
||||||
|
import com.android.server.appsearch.proto.SchemaTypeConfigProto;
|
||||||
import com.android.server.appsearch.protobuf.ByteString;
|
import com.android.server.appsearch.protobuf.ByteString;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class GenericDocumentToProtoConverterTest {
|
public class GenericDocumentToProtoConverterTest {
|
||||||
private static final byte[] BYTE_ARRAY_1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
|
private static final byte[] BYTE_ARRAY_1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
|
||||||
private static final byte[] BYTE_ARRAY_2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
|
private static final byte[] BYTE_ARRAY_2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
|
||||||
|
private static final String SCHEMA_TYPE_1 = "sDocumentPropertiesSchemaType1";
|
||||||
|
private static final String SCHEMA_TYPE_2 = "sDocumentPropertiesSchemaType2";
|
||||||
private static final GenericDocument DOCUMENT_PROPERTIES_1 =
|
private static final GenericDocument DOCUMENT_PROPERTIES_1 =
|
||||||
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
"namespace", "sDocumentProperties1", "sDocumentPropertiesSchemaType1")
|
"namespace", "sDocumentProperties1", SCHEMA_TYPE_1)
|
||||||
.setCreationTimestampMillis(12345L)
|
.setCreationTimestampMillis(12345L)
|
||||||
.build();
|
.build();
|
||||||
private static final GenericDocument DOCUMENT_PROPERTIES_2 =
|
private static final GenericDocument DOCUMENT_PROPERTIES_2 =
|
||||||
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
"namespace", "sDocumentProperties2", "sDocumentPropertiesSchemaType2")
|
"namespace", "sDocumentProperties2", SCHEMA_TYPE_2)
|
||||||
.setCreationTimestampMillis(6789L)
|
.setCreationTimestampMillis(6789L)
|
||||||
.build();
|
.build();
|
||||||
|
private static final SchemaTypeConfigProto SCHEMA_PROTO_1 =
|
||||||
|
SchemaTypeConfigProto.newBuilder().setSchemaType(SCHEMA_TYPE_1).build();
|
||||||
|
private static final SchemaTypeConfigProto SCHEMA_PROTO_2 =
|
||||||
|
SchemaTypeConfigProto.newBuilder().setSchemaType(SCHEMA_TYPE_2).build();
|
||||||
|
private static final String PREFIX = "package$databaseName/";
|
||||||
|
private static final Map<String, SchemaTypeConfigProto> SCHEMA_MAP =
|
||||||
|
ImmutableMap.of(
|
||||||
|
PREFIX + SCHEMA_TYPE_1, SCHEMA_PROTO_1, PREFIX + SCHEMA_TYPE_2, SCHEMA_PROTO_2);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDocumentProtoConvert() {
|
public void testDocumentProtoConvert() {
|
||||||
GenericDocument document =
|
GenericDocument document =
|
||||||
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
"namespace", "uri1", "schemaType1")
|
"namespace", "uri1", SCHEMA_TYPE_1)
|
||||||
.setCreationTimestampMillis(5L)
|
.setCreationTimestampMillis(5L)
|
||||||
.setScore(1)
|
.setScore(1)
|
||||||
.setTtlMillis(1L)
|
.setTtlMillis(1L)
|
||||||
@@ -66,7 +81,7 @@ public class GenericDocumentToProtoConverterTest {
|
|||||||
DocumentProto.Builder documentProtoBuilder =
|
DocumentProto.Builder documentProtoBuilder =
|
||||||
DocumentProto.newBuilder()
|
DocumentProto.newBuilder()
|
||||||
.setUri("uri1")
|
.setUri("uri1")
|
||||||
.setSchema("schemaType1")
|
.setSchema(SCHEMA_TYPE_1)
|
||||||
.setCreationTimestampMs(5L)
|
.setCreationTimestampMs(5L)
|
||||||
.setScore(1)
|
.setScore(1)
|
||||||
.setTtlMs(1L)
|
.setTtlMs(1L)
|
||||||
@@ -109,9 +124,133 @@ public class GenericDocumentToProtoConverterTest {
|
|||||||
documentProtoBuilder.addProperties(propertyProtoMap.get(key));
|
documentProtoBuilder.addProperties(propertyProtoMap.get(key));
|
||||||
}
|
}
|
||||||
DocumentProto documentProto = documentProtoBuilder.build();
|
DocumentProto documentProto = documentProtoBuilder.build();
|
||||||
assertThat(GenericDocumentToProtoConverter.toDocumentProto(document))
|
|
||||||
.isEqualTo(documentProto);
|
GenericDocument convertedGenericDocument =
|
||||||
assertThat(document)
|
GenericDocumentToProtoConverter.toGenericDocument(
|
||||||
.isEqualTo(GenericDocumentToProtoConverter.toGenericDocument(documentProto));
|
documentProto, PREFIX, SCHEMA_MAP);
|
||||||
|
DocumentProto convertedDocumentProto =
|
||||||
|
GenericDocumentToProtoConverter.toDocumentProto(document);
|
||||||
|
|
||||||
|
assertThat(convertedDocumentProto).isEqualTo(documentProto);
|
||||||
|
assertThat(convertedGenericDocument).isEqualTo(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConvertDocument_whenPropertyHasEmptyList() {
|
||||||
|
String emptyStringPropertyName = "emptyStringProperty";
|
||||||
|
DocumentProto documentProto =
|
||||||
|
DocumentProto.newBuilder()
|
||||||
|
.setUri("uri1")
|
||||||
|
.setSchema(SCHEMA_TYPE_1)
|
||||||
|
.setCreationTimestampMs(5L)
|
||||||
|
.setNamespace("namespace")
|
||||||
|
.addProperties(
|
||||||
|
PropertyProto.newBuilder().setName(emptyStringPropertyName).build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
PropertyConfigProto emptyStringListProperty =
|
||||||
|
PropertyConfigProto.newBuilder()
|
||||||
|
.setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
|
||||||
|
.setDataType(PropertyConfigProto.DataType.Code.STRING)
|
||||||
|
.setPropertyName(emptyStringPropertyName)
|
||||||
|
.build();
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto =
|
||||||
|
SchemaTypeConfigProto.newBuilder()
|
||||||
|
.addProperties(emptyStringListProperty)
|
||||||
|
.setSchemaType(SCHEMA_TYPE_1)
|
||||||
|
.build();
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaMap =
|
||||||
|
ImmutableMap.of(PREFIX + SCHEMA_TYPE_1, schemaTypeConfigProto);
|
||||||
|
|
||||||
|
GenericDocument convertedDocument =
|
||||||
|
GenericDocumentToProtoConverter.toGenericDocument(documentProto, PREFIX, schemaMap);
|
||||||
|
|
||||||
|
GenericDocument expectedDocument =
|
||||||
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
|
"namespace", "uri1", SCHEMA_TYPE_1)
|
||||||
|
.setCreationTimestampMillis(5L)
|
||||||
|
.setPropertyString(emptyStringPropertyName)
|
||||||
|
.build();
|
||||||
|
assertThat(convertedDocument).isEqualTo(expectedDocument);
|
||||||
|
assertThat(expectedDocument.getPropertyStringArray(emptyStringPropertyName)).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConvertDocument_whenNestedDocumentPropertyHasEmptyList() {
|
||||||
|
String emptyStringPropertyName = "emptyStringProperty";
|
||||||
|
String documentPropertyName = "documentProperty";
|
||||||
|
DocumentProto nestedDocumentProto =
|
||||||
|
DocumentProto.newBuilder()
|
||||||
|
.setUri("uri2")
|
||||||
|
.setSchema(SCHEMA_TYPE_2)
|
||||||
|
.setCreationTimestampMs(5L)
|
||||||
|
.setNamespace("namespace")
|
||||||
|
.addProperties(
|
||||||
|
PropertyProto.newBuilder().setName(emptyStringPropertyName).build())
|
||||||
|
.build();
|
||||||
|
DocumentProto documentProto =
|
||||||
|
DocumentProto.newBuilder()
|
||||||
|
.setUri("uri1")
|
||||||
|
.setSchema(SCHEMA_TYPE_1)
|
||||||
|
.setCreationTimestampMs(5L)
|
||||||
|
.setNamespace("namespace")
|
||||||
|
.addProperties(
|
||||||
|
PropertyProto.newBuilder()
|
||||||
|
.addDocumentValues(nestedDocumentProto)
|
||||||
|
.setName(documentPropertyName)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
PropertyConfigProto documentProperty =
|
||||||
|
PropertyConfigProto.newBuilder()
|
||||||
|
.setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
|
||||||
|
.setDataType(PropertyConfigProto.DataType.Code.DOCUMENT)
|
||||||
|
.setPropertyName(documentPropertyName)
|
||||||
|
.setSchemaType(SCHEMA_TYPE_2)
|
||||||
|
.build();
|
||||||
|
SchemaTypeConfigProto schemaTypeConfigProto =
|
||||||
|
SchemaTypeConfigProto.newBuilder()
|
||||||
|
.addProperties(documentProperty)
|
||||||
|
.setSchemaType(SCHEMA_TYPE_1)
|
||||||
|
.build();
|
||||||
|
PropertyConfigProto emptyStringListProperty =
|
||||||
|
PropertyConfigProto.newBuilder()
|
||||||
|
.setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
|
||||||
|
.setDataType(PropertyConfigProto.DataType.Code.STRING)
|
||||||
|
.setPropertyName(emptyStringPropertyName)
|
||||||
|
.build();
|
||||||
|
SchemaTypeConfigProto nestedSchemaTypeConfigProto =
|
||||||
|
SchemaTypeConfigProto.newBuilder()
|
||||||
|
.addProperties(emptyStringListProperty)
|
||||||
|
.setSchemaType(SCHEMA_TYPE_2)
|
||||||
|
.build();
|
||||||
|
Map<String, SchemaTypeConfigProto> schemaMap =
|
||||||
|
ImmutableMap.of(
|
||||||
|
PREFIX + SCHEMA_TYPE_1,
|
||||||
|
schemaTypeConfigProto,
|
||||||
|
PREFIX + SCHEMA_TYPE_2,
|
||||||
|
nestedSchemaTypeConfigProto);
|
||||||
|
|
||||||
|
GenericDocument convertedDocument =
|
||||||
|
GenericDocumentToProtoConverter.toGenericDocument(documentProto, PREFIX, schemaMap);
|
||||||
|
|
||||||
|
GenericDocument expectedDocument =
|
||||||
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
|
"namespace", "uri1", SCHEMA_TYPE_1)
|
||||||
|
.setCreationTimestampMillis(5L)
|
||||||
|
.setPropertyDocument(
|
||||||
|
documentPropertyName,
|
||||||
|
new GenericDocument.Builder<GenericDocument.Builder<?>>(
|
||||||
|
"namespace", "uri2", SCHEMA_TYPE_2)
|
||||||
|
.setCreationTimestampMillis(5L)
|
||||||
|
.setPropertyString(emptyStringPropertyName)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
assertThat(convertedDocument).isEqualTo(expectedDocument);
|
||||||
|
assertThat(
|
||||||
|
expectedDocument
|
||||||
|
.getPropertyDocument(documentPropertyName)
|
||||||
|
.getPropertyStringArray(emptyStringPropertyName))
|
||||||
|
.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import android.app.appsearch.SearchResult;
|
import android.app.appsearch.SearchResult;
|
||||||
import android.app.appsearch.SearchResultPage;
|
import android.app.appsearch.SearchResultPage;
|
||||||
|
|
||||||
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
import com.android.server.appsearch.proto.DocumentProto;
|
import com.android.server.appsearch.proto.DocumentProto;
|
||||||
import com.android.server.appsearch.proto.PropertyProto;
|
import com.android.server.appsearch.proto.PropertyProto;
|
||||||
|
import com.android.server.appsearch.proto.SchemaTypeConfigProto;
|
||||||
import com.android.server.appsearch.proto.SearchResultProto;
|
import com.android.server.appsearch.proto.SearchResultProto;
|
||||||
import com.android.server.appsearch.proto.SnippetMatchProto;
|
import com.android.server.appsearch.proto.SnippetMatchProto;
|
||||||
import com.android.server.appsearch.proto.SnippetProto;
|
import com.android.server.appsearch.proto.SnippetProto;
|
||||||
@@ -30,20 +32,29 @@ import com.android.server.appsearch.proto.SnippetProto;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class SnippetTest {
|
public class SnippetTest {
|
||||||
|
private static final String SCHEMA_TYPE = "schema1";
|
||||||
|
private static final String PACKAGE_NAME = "packageName";
|
||||||
|
private static final String DATABASE_NAME = "databaseName";
|
||||||
|
private static final String PREFIX = PrefixUtil.createPrefix(PACKAGE_NAME, DATABASE_NAME);
|
||||||
|
private static final SchemaTypeConfigProto SCHEMA_TYPE_CONFIG_PROTO =
|
||||||
|
SchemaTypeConfigProto.newBuilder().setSchemaType(PREFIX + SCHEMA_TYPE).build();
|
||||||
|
private static final Map<String, Map<String, SchemaTypeConfigProto>> SCHEMA_MAP =
|
||||||
|
Collections.singletonMap(
|
||||||
|
PREFIX,
|
||||||
|
Collections.singletonMap(PREFIX + SCHEMA_TYPE, SCHEMA_TYPE_CONFIG_PROTO));
|
||||||
|
|
||||||
// TODO(tytytyww): Add tests for Double and Long Snippets.
|
// TODO(tytytyww): Add tests for Double and Long Snippets.
|
||||||
@Test
|
@Test
|
||||||
public void testSingleStringSnippet() {
|
public void testSingleStringSnippet() {
|
||||||
|
|
||||||
final String propertyKeyString = "content";
|
final String propertyKeyString = "content";
|
||||||
final String propertyValueString =
|
final String propertyValueString =
|
||||||
"A commonly used fake word is foo.\n"
|
"A commonly used fake word is foo.\n"
|
||||||
+ " Another nonsense word that’s used a lot\n"
|
+ " Another nonsense word that’s used a lot\n"
|
||||||
+ " is bar.\n";
|
+ " is bar.\n";
|
||||||
final String uri = "uri1";
|
final String uri = "uri1";
|
||||||
final String schemaType = "schema1";
|
|
||||||
final String searchWord = "foo";
|
final String searchWord = "foo";
|
||||||
final String exactMatch = "foo";
|
final String exactMatch = "foo";
|
||||||
final String window = "is foo";
|
final String window = "is foo";
|
||||||
@@ -57,7 +68,7 @@ public class SnippetTest {
|
|||||||
DocumentProto documentProto =
|
DocumentProto documentProto =
|
||||||
DocumentProto.newBuilder()
|
DocumentProto.newBuilder()
|
||||||
.setUri(uri)
|
.setUri(uri)
|
||||||
.setSchema(schemaType)
|
.setSchema(SCHEMA_TYPE)
|
||||||
.addProperties(property)
|
.addProperties(property)
|
||||||
.build();
|
.build();
|
||||||
SnippetProto snippetProto =
|
SnippetProto snippetProto =
|
||||||
@@ -86,8 +97,9 @@ public class SnippetTest {
|
|||||||
SearchResultPage searchResultPage =
|
SearchResultPage searchResultPage =
|
||||||
SearchResultToProtoConverter.toSearchResultPage(
|
SearchResultToProtoConverter.toSearchResultPage(
|
||||||
searchResultProto,
|
searchResultProto,
|
||||||
Collections.singletonList("packageName"),
|
Collections.singletonList(PACKAGE_NAME),
|
||||||
Collections.singletonList("databaseName"));
|
Collections.singletonList(DATABASE_NAME),
|
||||||
|
SCHEMA_MAP);
|
||||||
for (SearchResult result : searchResultPage.getResults()) {
|
for (SearchResult result : searchResultPage.getResults()) {
|
||||||
SearchResult.MatchInfo match = result.getMatches().get(0);
|
SearchResult.MatchInfo match = result.getMatches().get(0);
|
||||||
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
|
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
|
||||||
@@ -112,7 +124,6 @@ public class SnippetTest {
|
|||||||
+ " Another nonsense word that’s used a lot\n"
|
+ " Another nonsense word that’s used a lot\n"
|
||||||
+ " is bar.\n";
|
+ " is bar.\n";
|
||||||
final String uri = "uri1";
|
final String uri = "uri1";
|
||||||
final String schemaType = "schema1";
|
|
||||||
final String searchWord = "foo";
|
final String searchWord = "foo";
|
||||||
final String exactMatch = "foo";
|
final String exactMatch = "foo";
|
||||||
final String window = "is foo";
|
final String window = "is foo";
|
||||||
@@ -126,7 +137,7 @@ public class SnippetTest {
|
|||||||
DocumentProto documentProto =
|
DocumentProto documentProto =
|
||||||
DocumentProto.newBuilder()
|
DocumentProto.newBuilder()
|
||||||
.setUri(uri)
|
.setUri(uri)
|
||||||
.setSchema(schemaType)
|
.setSchema(SCHEMA_TYPE)
|
||||||
.addProperties(property)
|
.addProperties(property)
|
||||||
.build();
|
.build();
|
||||||
SearchResultProto.ResultProto resultProto =
|
SearchResultProto.ResultProto resultProto =
|
||||||
@@ -137,8 +148,9 @@ public class SnippetTest {
|
|||||||
SearchResultPage searchResultPage =
|
SearchResultPage searchResultPage =
|
||||||
SearchResultToProtoConverter.toSearchResultPage(
|
SearchResultToProtoConverter.toSearchResultPage(
|
||||||
searchResultProto,
|
searchResultProto,
|
||||||
Collections.singletonList("packageName"),
|
Collections.singletonList(PACKAGE_NAME),
|
||||||
Collections.singletonList("databaseName"));
|
Collections.singletonList(DATABASE_NAME),
|
||||||
|
SCHEMA_MAP);
|
||||||
for (SearchResult result : searchResultPage.getResults()) {
|
for (SearchResult result : searchResultPage.getResults()) {
|
||||||
assertThat(result.getMatches()).isEmpty();
|
assertThat(result.getMatches()).isEmpty();
|
||||||
}
|
}
|
||||||
@@ -162,7 +174,7 @@ public class SnippetTest {
|
|||||||
DocumentProto documentProto =
|
DocumentProto documentProto =
|
||||||
DocumentProto.newBuilder()
|
DocumentProto.newBuilder()
|
||||||
.setUri("uri1")
|
.setUri("uri1")
|
||||||
.setSchema("schema1")
|
.setSchema(SCHEMA_TYPE)
|
||||||
.addProperties(property1)
|
.addProperties(property1)
|
||||||
.addProperties(property2)
|
.addProperties(property2)
|
||||||
.build();
|
.build();
|
||||||
@@ -203,8 +215,9 @@ public class SnippetTest {
|
|||||||
SearchResultPage searchResultPage =
|
SearchResultPage searchResultPage =
|
||||||
SearchResultToProtoConverter.toSearchResultPage(
|
SearchResultToProtoConverter.toSearchResultPage(
|
||||||
searchResultProto,
|
searchResultProto,
|
||||||
Collections.singletonList("packageName"),
|
Collections.singletonList(PACKAGE_NAME),
|
||||||
Collections.singletonList("databaseName"));
|
Collections.singletonList(DATABASE_NAME),
|
||||||
|
SCHEMA_MAP);
|
||||||
for (SearchResult result : searchResultPage.getResults()) {
|
for (SearchResult result : searchResultPage.getResults()) {
|
||||||
|
|
||||||
SearchResult.MatchInfo match1 = result.getMatches().get(0);
|
SearchResult.MatchInfo match1 = result.getMatches().get(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user