Snap for 11268588 from a8ee5e92163ac6820dec08c906c9906a9b977d4e to mainline-art-release
Change-Id: I9ff573ba5daa5f086c5f63aaae58cc5788bb8665
diff --git a/framework/java/android/app/appsearch/aidl/AppSearchAttributionSource.java b/framework/java/android/app/appsearch/aidl/AppSearchAttributionSource.java
index 5771e5f..c2ecb9d 100644
--- a/framework/java/android/app/appsearch/aidl/AppSearchAttributionSource.java
+++ b/framework/java/android/app/appsearch/aidl/AppSearchAttributionSource.java
@@ -19,6 +19,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresApi;
+import android.app.appsearch.safeparcel.AbstractSafeParcelable;
+import android.app.appsearch.safeparcel.SafeParcelable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
@@ -44,60 +46,78 @@
*
* @hide
*/
-// TODO(b/275629842): Update the class to use SafeParcelable instead of Parcelable.
-public final class AppSearchAttributionSource implements Parcelable {
+@SafeParcelable.Class(creator = "AppSearchAttributionSourceCreator")
+public final class AppSearchAttributionSource extends AbstractSafeParcelable {
+ @NonNull
+ public static final AppSearchAttributionSourceCreator CREATOR =
+ new AppSearchAttributionSourceCreator();
+ @NonNull
private final Compat mCompat;
- @Nullable private final String mCallingPackageName;
+
+ @Nullable
+ @Field(id = 1, getter = "getAttributionSource")
+ private final AttributionSource mAttributionSource;
+ @Nullable
+ @Field(id = 2, getter = "getPackageName")
+ private final String mCallingPackageName;
+ @Field(id = 3, getter = "getUid")
private final int mCallingUid;
/**
+ * Constructs an instance of AppSearchAttributionSource for AbstractSafeParcelable.
+ * @param attributionSource The attribution source that is accessing permission
+ * protected data.
+ * @param callingPackageName The package that is accessing the permission protected data.
+ * @param callingUid The UID that is accessing the permission protected data.
+ */
+ @Constructor
+ AppSearchAttributionSource(
+ @Param(id = 1) @Nullable AttributionSource attributionSource,
+ @Param(id = 2) @Nullable String callingPackageName,
+ @Param(id = 3) int callingUid) {
+ mAttributionSource = attributionSource;
+ mCallingPackageName = callingPackageName;
+ mCallingUid = callingUid;
+ if (VERSION.SDK_INT >= Build.VERSION_CODES.S && mAttributionSource != null) {
+ mCompat = new Api31Impl(mAttributionSource);
+ } else {
+ mCompat = new Api19Impl(mCallingPackageName, mCallingUid);
+ }
+ }
+
+ /**
* Constructs an instance of AppSearchAttributionSource.
* @param compat The compat version that provides AttributionSource implementation on
* lower API levels.
*/
private AppSearchAttributionSource(@NonNull Compat compat) {
mCompat = Objects.requireNonNull(compat);
+ mAttributionSource = mCompat.getAttributionSource();
mCallingPackageName = mCompat.getPackageName();
mCallingUid = mCompat.getUid();
}
+ /**
+ * Constructs an instance of AppSearchAttributionSource for testing.
+ * @param callingPackageName The package that is accessing the permission protected data.
+ * @param callingUid The UID that is accessing the permission protected data.
+ */
@VisibleForTesting
public AppSearchAttributionSource(@Nullable String callingPackageName, int callingUid) {
mCallingPackageName = callingPackageName;
mCallingUid = callingUid;
if (VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- AttributionSource attributionSource =
- new AttributionSource.Builder(mCallingUid)
- .setPackageName(mCallingPackageName).build();
- mCompat = new Api31Impl(attributionSource);
+ mAttributionSource = new AttributionSource.Builder(mCallingUid)
+ .setPackageName(mCallingPackageName).build();
+ mCompat = new Api31Impl(mAttributionSource);
} else {
+ mAttributionSource = null;
mCompat = new Api19Impl(mCallingPackageName, mCallingUid);
}
}
- private AppSearchAttributionSource(@NonNull Parcel in) {
- if (VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- // Deserializing attributionSource calls enforceCallingUidAndPid similar to
- // AttributionSource.
- AttributionSource attributionSource =
- in.readParcelable(AttributionSource.class.getClassLoader());
- mCompat = new Api31Impl(attributionSource);
- mCallingPackageName = mCompat.getPackageName();
- mCallingUid = mCompat.getUid();
- } else {
- mCallingPackageName = in.readString();
- mCallingUid = in.readInt();
- Api19Impl impl = new Api19Impl(mCallingPackageName, mCallingUid);
- // Enforce calling pid and uid must be called here on R and below similar to how
- // AttributionSource is implemented.
- impl.enforceCallingUid();
- impl.enforceCallingPid();
- mCompat = impl;
- }
- }
-
/**
* Provides a backward-compatible wrapper for AttributionSource.
*
@@ -165,7 +185,7 @@
public int hashCode() {
if (VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AttributionSource attributionSource = Objects.requireNonNull(
- mCompat.getAttributionSource());
+ mCompat.getAttributionSource());
return attributionSource.hashCode();
}
@@ -181,44 +201,21 @@
AppSearchAttributionSource that = (AppSearchAttributionSource) o;
if (VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AttributionSource thisAttributionSource = Objects.requireNonNull(
- mCompat.getAttributionSource());
+ mCompat.getAttributionSource());
AttributionSource thatAttributionSource = Objects.requireNonNull(
- that.getAttributionSource());
+ that.getAttributionSource());
return thisAttributionSource.equals(thatAttributionSource);
}
return (Objects.equals(mCompat.getPackageName(), that.getPackageName())
- && (mCompat.getUid() == that.getUid()));
- }
-
- @Override
- public int describeContents() {
- return 0;
+ && (mCompat.getUid() == that.getUid()));
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- if (VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- dest.writeParcelable(mCompat.getAttributionSource(), flags);
- } else {
- dest.writeString(mCompat.getPackageName());
- dest.writeInt(mCompat.getUid());
- }
+ AppSearchAttributionSourceCreator.writeToParcel(this, dest, flags);
}
- public static final Creator<AppSearchAttributionSource> CREATOR =
- new Creator<>() {
- @Override
- public AppSearchAttributionSource createFromParcel(Parcel in) {
- return new AppSearchAttributionSource(in);
- }
-
- @Override
- public AppSearchAttributionSource[] newArray(int size) {
- return new AppSearchAttributionSource[size];
- }
- };
-
/** Compat class for AttributionSource to provide implementation for lower API levels. */
private interface Compat {
/** The package that is accessing the permission protected data. */
diff --git a/framework/java/external/android/app/appsearch/AppSearchSchema.java b/framework/java/external/android/app/appsearch/AppSearchSchema.java
index 02152d7..a0eea64 100644
--- a/framework/java/external/android/app/appsearch/AppSearchSchema.java
+++ b/framework/java/external/android/app/appsearch/AppSearchSchema.java
@@ -36,6 +36,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -181,7 +182,7 @@
public static final class Builder {
private final String mSchemaType;
private ArrayList<Bundle> mPropertyBundles = new ArrayList<>();
- private ArraySet<String> mParentTypes = new ArraySet<>();
+ private LinkedHashSet<String> mParentTypes = new LinkedHashSet<>();
private final Set<String> mPropertyNames = new ArraySet<>();
private boolean mBuilt = false;
@@ -289,7 +290,7 @@
private void resetIfBuilt() {
if (mBuilt) {
mPropertyBundles = new ArrayList<>(mPropertyBundles);
- mParentTypes = new ArraySet<>(mParentTypes);
+ mParentTypes = new LinkedHashSet<>(mParentTypes);
mBuilt = false;
}
}
@@ -1342,7 +1343,7 @@
*
* @throws IllegalArgumentException if the provided PropertyConfig sets {@link
* #shouldIndexNestedProperties()} to true and has one or more properties defined
- * for {@link #getIndexableNestedProperties()}.
+ * using {@link #addIndexableNestedProperties(Collection)}.
*/
@NonNull
public DocumentPropertyConfig build() {
diff --git a/framework/java/external/android/app/appsearch/GenericDocument.java b/framework/java/external/android/app/appsearch/GenericDocument.java
index 9766748..a977c68 100644
--- a/framework/java/external/android/app/appsearch/GenericDocument.java
+++ b/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -887,10 +887,13 @@
*
* <p>The returned builder is a deep copy whose data is separate from this document.
*
+ * @deprecated This API is not compliant with API guidelines. Use {@link
+ * Builder#Builder(GenericDocument)} instead.
* @hide
*/
// TODO(b/171882200): Expose this API in Android T
@NonNull
+ @Deprecated
public GenericDocument.Builder<GenericDocument.Builder<?>> toBuilder() {
Bundle clonedBundle = BundleUtil.deepCopy(mBundle);
return new GenericDocument.Builder<>(clonedBundle);
@@ -999,7 +1002,6 @@
builder.append("\n");
builder.decreaseIndentLevel();
}
- builder.append("]");
} else {
int propertyArrLength = Array.getLength(property);
for (int i = 0; i < propertyArrLength; i++) {
@@ -1013,11 +1015,10 @@
}
if (i != propertyArrLength - 1) {
builder.append(", ");
- } else {
- builder.append("]");
}
}
}
+ builder.append("]");
}
/**
@@ -1082,6 +1083,18 @@
}
/**
+ * Creates a new {@link GenericDocument.Builder} from the given GenericDocument.
+ *
+ * <p>The GenericDocument is deep copied, i.e. changes to the new GenericDocument returned
+ * by this function will NOT affect the original GenericDocument.
+ *
+ * @hide
+ */
+ public Builder(@NonNull GenericDocument document) {
+ this(BundleUtil.deepCopy(document.getBundle()));
+ }
+
+ /**
* Sets the app-defined namespace this document resides in, changing the value provided in
* the constructor. No special values are reserved or understood by the infrastructure.
*
diff --git a/framework/java/external/android/app/appsearch/JoinSpec.java b/framework/java/external/android/app/appsearch/JoinSpec.java
index f4e62fc..7b487b7 100644
--- a/framework/java/external/android/app/appsearch/JoinSpec.java
+++ b/framework/java/external/android/app/appsearch/JoinSpec.java
@@ -277,9 +277,9 @@
* Sets the query and the SearchSpec for the documents being joined. This will score and
* rank the joined documents as well as filter the joined documents.
*
- * <p>If {@link SearchSpec.RankingStrategy#RANKING_STRATEGY_JOIN_AGGREGATE_SCORE} is set in
- * the outer {@link SearchSpec}, the resulting signals will be used to rank the parent
- * documents. Note that the aggregation strategy also needs to be set with {@link
+ * <p>If {@link SearchSpec#RANKING_STRATEGY_JOIN_AGGREGATE_SCORE} is set in the outer {@link
+ * SearchSpec}, the resulting signals will be used to rank the parent documents. Note that
+ * the aggregation strategy also needs to be set with {@link
* JoinSpec.Builder#setAggregationScoringStrategy}, otherwise the default will be {@link
* JoinSpec#AGGREGATION_SCORING_OUTER_RESULT_RANKING_SIGNAL}, which will just use the parent
* documents ranking signal.
diff --git a/framework/java/external/android/app/appsearch/SearchSpec.java b/framework/java/external/android/app/appsearch/SearchSpec.java
index 68d0946..bab25ad 100644
--- a/framework/java/external/android/app/appsearch/SearchSpec.java
+++ b/framework/java/external/android/app/appsearch/SearchSpec.java
@@ -487,17 +487,17 @@
return mBundle.getString(ADVANCED_RANKING_EXPRESSION, "");
}
- /** Returns whether the {@link Features#NUMERIC_SEARCH} feature is enabled. */
+ /** Returns whether the NUMERIC_SEARCH feature is enabled. */
public boolean isNumericSearchEnabled() {
return getEnabledFeatures().contains(FeatureConstants.NUMERIC_SEARCH);
}
- /** Returns whether the {@link Features#VERBATIM_SEARCH} feature is enabled. */
+ /** Returns whether the VERBATIM_SEARCH feature is enabled. */
public boolean isVerbatimSearchEnabled() {
return getEnabledFeatures().contains(FeatureConstants.VERBATIM_SEARCH);
}
- /** Returns whether the {@link Features#LIST_FILTER_QUERY_LANGUAGE} feature is enabled. */
+ /** Returns whether the LIST_FILTER_QUERY_LANGUAGE feature is enabled. */
public boolean isListFilterQueryLanguageEnabled() {
return getEnabledFeatures().contains(FeatureConstants.LIST_FILTER_QUERY_LANGUAGE);
}
@@ -1199,8 +1199,7 @@
}
/**
- * Sets the {@link Features#NUMERIC_SEARCH} feature as enabled/disabled according to the
- * enabled parameter.
+ * Sets the NUMERIC_SEARCH feature as enabled/disabled according to the enabled parameter.
*
* @param enabled Enables the feature if true, otherwise disables it.
* <p>If disabled, disallows use of {@link
@@ -1214,8 +1213,7 @@
}
/**
- * Sets the {@link Features#VERBATIM_SEARCH} feature as enabled/disabled according to the
- * enabled parameter.
+ * Sets the VERBATIM_SEARCH feature as enabled/disabled according to the enabled parameter.
*
* @param enabled Enables the feature if true, otherwise disables it
* <p>If disabled, disallows use of {@link
@@ -1232,8 +1230,8 @@
}
/**
- * Sets the {@link Features#LIST_FILTER_QUERY_LANGUAGE} feature as enabled/disabled
- * according to the enabled parameter.
+ * Sets the LIST_FILTER_QUERY_LANGUAGE feature as enabled/disabled according to the enabled
+ * parameter.
*
* @param enabled Enables the feature if true, otherwise disables it.
* <p>This feature covers the expansion of the query language to conform to the
diff --git a/framework/java/external/android/app/appsearch/stats/SchemaMigrationStats.java b/framework/java/external/android/app/appsearch/stats/SchemaMigrationStats.java
index b2b9ff6..9efef2b 100644
--- a/framework/java/external/android/app/appsearch/stats/SchemaMigrationStats.java
+++ b/framework/java/external/android/app/appsearch/stats/SchemaMigrationStats.java
@@ -39,7 +39,7 @@
@NonNull
public static final SchemaMigrationStatsCreator CREATOR = new SchemaMigrationStatsCreator();
- // Indicate how a SetSchema call relative to SchemaMigration case.
+ // Indicate the how a SetSchema call relative to SchemaMigration case.
@IntDef(
value = {
NO_MIGRATION,
diff --git a/service/java/com/android/server/appsearch/FrameworkAppSearchConfigImpl.java b/service/java/com/android/server/appsearch/FrameworkAppSearchConfigImpl.java
index 4333384..440a3c3 100644
--- a/service/java/com/android/server/appsearch/FrameworkAppSearchConfigImpl.java
+++ b/service/java/com/android/server/appsearch/FrameworkAppSearchConfigImpl.java
@@ -104,6 +104,10 @@
"icing_lite_index_sort_size";
public static final String KEY_SHOULD_RETRIEVE_PARENT_INFO =
"should_retrieve_parent_info";
+ public static final String KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX =
+ "use_new_qualified_id_join_index";
+ public static final String KEY_BUILD_PROPERTY_EXISTENCE_METADATA_HITS =
+ "build_property_existence_metadata_hits";
/**
* This config does not need to be cached in FrameworkAppSearchConfigImpl as it is only accessed
@@ -147,6 +151,8 @@
KEY_ICING_LITE_INDEX_SORT_AT_INDEXING,
KEY_ICING_LITE_INDEX_SORT_SIZE,
KEY_SHOULD_RETRIEVE_PARENT_INFO,
+ KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX,
+ KEY_BUILD_PROPERTY_EXISTENCE_METADATA_HITS,
};
// Lock needed for all the operations in this class.
@@ -549,6 +555,22 @@
}
@Override
+ public boolean getUseNewQualifiedIdJoinIndex() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getBoolean(
+ KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX,
+ DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX);
+ }
+ }
+
+ @Override
+ public boolean getBuildPropertyExistenceMetadataHits() {
+ // TODO(b/309826655) Set this value properly in main branch
+ return false; // We never turn this feature on in udc-mainline-prod
+ }
+
+ @Override
public boolean shouldStoreParentInfoAsSyntheticProperty() {
// This option is always true in Framework.
return true;
@@ -773,6 +795,14 @@
DEFAULT_SHOULD_RETRIEVE_PARENT_INFO));
}
break;
+ case KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX:
+ synchronized (mLock) {
+ mBundleLocked.putBoolean(key, properties.getBoolean(key, true));
+ }
+ break;
+ case KEY_BUILD_PROPERTY_EXISTENCE_METADATA_HITS:
+ // TODO(b/309826655) Set this value properly in main branch
+ // fall throw to default since we never turn this feature on in udc-mainline-prod
default:
break;
}
diff --git a/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 71a4f11..1e70a8a 100644
--- a/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -315,6 +315,9 @@
mConfig.getIntegerIndexBucketSplitThreshold())
.setLiteIndexSortAtIndexing(mConfig.getLiteIndexSortAtIndexing())
.setLiteIndexSortSize(mConfig.getLiteIndexSortSize())
+ .setUseNewQualifiedIdJoinIndex(mConfig.getUseNewQualifiedIdJoinIndex())
+ .setBuildPropertyExistenceMetadataHits(
+ mConfig.getBuildPropertyExistenceMetadataHits())
.build();
LogUtil.piiTrace(TAG, "Constructing IcingSearchEngine, request", options);
mIcingSearchEngineLocked = new IcingSearchEngine(options);
@@ -566,8 +569,7 @@
(int) (getOldSchemaEndTimeMillis - getOldSchemaStartTimeMillis));
}
- int getOldSchemaObserverStartTimeMillis =
- (int) (SystemClock.elapsedRealtime() - getOldSchemaEndTimeMillis);
+ long getOldSchemaObserverStartTimeMillis = SystemClock.elapsedRealtime();
// Cache some lookup tables to help us work with the old schema
Set<AppSearchSchema> oldSchemaTypes = oldSchema.getSchemas();
Map<String, AppSearchSchema> oldSchemaNameToType = new ArrayMap<>(oldSchemaTypes.size());
@@ -732,7 +734,7 @@
int version,
@Nullable SetSchemaStats.Builder setSchemaStatsBuilder)
throws AppSearchException {
- long setRewriteSchemaLatencyMillis = SystemClock.elapsedRealtime();
+ long setRewriteSchemaLatencyStartTimeMillis = SystemClock.elapsedRealtime();
SchemaProto.Builder existingSchemaBuilder = getSchemaProtoLocked().toBuilder();
SchemaProto.Builder newSchemaBuilder = SchemaProto.newBuilder();
@@ -752,7 +754,7 @@
long rewriteSchemaEndTimeMillis = SystemClock.elapsedRealtime();
if (setSchemaStatsBuilder != null) {
setSchemaStatsBuilder.setRewriteSchemaLatencyMillis(
- (int) (rewriteSchemaEndTimeMillis - setRewriteSchemaLatencyMillis));
+ (int) (rewriteSchemaEndTimeMillis - setRewriteSchemaLatencyStartTimeMillis));
}
// Apply schema
diff --git a/service/java/com/android/server/appsearch/external/localstorage/IcingOptionsConfig.java b/service/java/com/android/server/appsearch/external/localstorage/IcingOptionsConfig.java
index c3c59a4..e2b569b 100644
--- a/service/java/com/android/server/appsearch/external/localstorage/IcingOptionsConfig.java
+++ b/service/java/com/android/server/appsearch/external/localstorage/IcingOptionsConfig.java
@@ -68,6 +68,10 @@
*/
int DEFAULT_LITE_INDEX_SORT_SIZE = 8192; // 8Kib
+ boolean DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX = false;
+
+ boolean DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS = false;
+
/**
* The maximum allowable token length. All tokens in excess of this size will be truncated to
* max_token_length before being indexed.
@@ -201,4 +205,19 @@
* <p>Setting a lower sort size reduces querying latency at the expense of indexing latency.
*/
int getLiteIndexSortSize();
+
+ /**
+ * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
+ *
+ * <p>Whether to use the new qualified Id join index.
+ */
+ boolean getUseNewQualifiedIdJoinIndex();
+
+ /**
+ * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
+ *
+ * <p>Whether to build the metadata hits used for property existence check, which is required to
+ * support the hasProperty function in advanced query.
+ */
+ boolean getBuildPropertyExistenceMetadataHits();
}
diff --git a/service/java/com/android/server/appsearch/external/localstorage/ObserverManager.java b/service/java/com/android/server/appsearch/external/localstorage/ObserverManager.java
index b34fac3..4b711ae 100644
--- a/service/java/com/android/server/appsearch/external/localstorage/ObserverManager.java
+++ b/service/java/com/android/server/appsearch/external/localstorage/ObserverManager.java
@@ -387,14 +387,13 @@
Map<String, Set<String>> schemaChanges = observerInfo.mSchemaChanges;
Map<DocumentChangeGroupKey, Set<String>> documentChanges = observerInfo.mDocumentChanges;
if (schemaChanges.isEmpty() && documentChanges.isEmpty()) {
+ // There is nothing to send, return early.
return;
}
- if (!schemaChanges.isEmpty()) {
- observerInfo.mSchemaChanges = new ArrayMap<>();
- }
- if (!documentChanges.isEmpty()) {
- observerInfo.mDocumentChanges = new ArrayMap<>();
- }
+ // Clean the pending changes in the observer. We already copy pending changes to local
+ // variables.
+ observerInfo.mSchemaChanges = new ArrayMap<>();
+ observerInfo.mDocumentChanges = new ArrayMap<>();
// Dispatch the pending changes
observerInfo.mExecutor.execute(
diff --git a/synced_jetpack_sha.txt b/synced_jetpack_sha.txt
index 9f457ba..26e7658 100644
--- a/synced_jetpack_sha.txt
+++ b/synced_jetpack_sha.txt
@@ -1 +1 @@
-ca831ece697f8b14a0861fd2f19f3654d79097fa
+0c8ad0cdfa25a4d2f80554d0e8d45fe34ce16aa6
diff --git a/testing/coretests/src/android/app/appsearch/external/app/AppSearchSessionInternalTestBase.java b/testing/coretests/src/android/app/appsearch/external/app/AppSearchSessionInternalTestBase.java
index 43475bd..d2e52af 100644
--- a/testing/coretests/src/android/app/appsearch/external/app/AppSearchSessionInternalTestBase.java
+++ b/testing/coretests/src/android/app/appsearch/external/app/AppSearchSessionInternalTestBase.java
@@ -1504,7 +1504,9 @@
.addGenericDocuments(personDoc, artistDoc, emailDoc)
.build()));
GenericDocument artistDocWithParent =
- artistDoc.toBuilder().setParentTypes(Collections.singletonList("Person")).build();
+ new GenericDocument.Builder<>(artistDoc)
+ .setParentTypes(Collections.singletonList("Person"))
+ .build();
// Query for the documents
SearchResultsShim searchResults =
@@ -1717,9 +1719,13 @@
.addGenericDocuments(artistDoc, messageDoc)
.build()));
GenericDocument expectedArtistDoc =
- artistDoc.toBuilder().setParentTypes(Collections.singletonList("Person")).build();
+ new GenericDocument.Builder<>(artistDoc)
+ .setParentTypes(Collections.singletonList("Person"))
+ .build();
GenericDocument expectedMessageDoc =
- messageDoc.toBuilder().setPropertyDocument("sender", expectedArtistDoc).build();
+ new GenericDocument.Builder<>(messageDoc)
+ .setPropertyDocument("sender", expectedArtistDoc)
+ .build();
// Query for the documents
SearchResultsShim searchResults =
@@ -1781,13 +1787,17 @@
.build()));
GenericDocument expectedDocA =
- docA.toBuilder()
+ new GenericDocument.Builder<>(docA)
.setParentTypes(new ArrayList<>(Arrays.asList("C", "B", "D")))
.build();
GenericDocument expectedDocB =
- docB.toBuilder().setParentTypes(Collections.singletonList("D")).build();
+ new GenericDocument.Builder<>(docB)
+ .setParentTypes(Collections.singletonList("D"))
+ .build();
GenericDocument expectedDocC =
- docC.toBuilder().setParentTypes(new ArrayList<>(Arrays.asList("B", "D"))).build();
+ new GenericDocument.Builder<>(docC)
+ .setParentTypes(new ArrayList<>(Arrays.asList("B", "D")))
+ .build();
// Query for the documents
SearchResultsShim searchResults = mDb1.search("", new SearchSpec.Builder().build());
List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
diff --git a/testing/coretests/src/android/app/appsearch/external/app/GenericDocumentInternalTest.java b/testing/coretests/src/android/app/appsearch/external/app/GenericDocumentInternalTest.java
index ab8360c..08cb351 100644
--- a/testing/coretests/src/android/app/appsearch/external/app/GenericDocumentInternalTest.java
+++ b/testing/coretests/src/android/app/appsearch/external/app/GenericDocumentInternalTest.java
@@ -107,4 +107,56 @@
assertThat(outDoc.getPropertyDocument("propDocument").getPropertyBytesArray("propBytes"))
.isEqualTo(new byte[][] {{3, 4}});
}
+
+ @Test
+ public void testGenericDocumentBuilderDoesNotMutateOriginal() {
+ GenericDocument oldDoc =
+ new GenericDocument.Builder<>("namespace", "id1", "schema1")
+ .setParentTypes(new ArrayList<>(Arrays.asList("Class1", "Class2")))
+ .setScore(42)
+ .setPropertyString("propString", "Hello")
+ .setPropertyBytes("propBytes", new byte[][] {{1, 2}})
+ .setPropertyDocument(
+ "propDocument",
+ new GenericDocument.Builder<>("namespace", "id2", "schema2")
+ .setPropertyString("propString", "Goodbye")
+ .setPropertyBytes("propBytes", new byte[][] {{3, 4}})
+ .build())
+ .build();
+
+ GenericDocument newDoc =
+ new GenericDocument.Builder<>(oldDoc)
+ .setParentTypes(new ArrayList<>(Arrays.asList("Class3", "Class4")))
+ .setPropertyBytes("propBytes", new byte[][] {{1, 2}})
+ .setPropertyDocument(
+ "propDocument",
+ new GenericDocument.Builder<>("namespace", "id3", "schema3")
+ .setPropertyString("propString", "Bye")
+ .setPropertyBytes("propBytes", new byte[][] {{5, 6}})
+ .build())
+ .build();
+
+ // Check that the original GenericDocument is unmodified.
+ assertThat(oldDoc.getParentTypes()).isEqualTo(Arrays.asList("Class1", "Class2"));
+ assertThat(oldDoc.getScore()).isEqualTo(42);
+ assertThat(oldDoc.getPropertyString("propString")).isEqualTo("Hello");
+ assertThat(oldDoc.getPropertyBytesArray("propBytes")).isEqualTo(new byte[][] {{1, 2}});
+ assertThat(oldDoc.getPropertyDocument("propDocument").getPropertyString("propString"))
+ .isEqualTo("Goodbye");
+ assertThat(oldDoc.getPropertyDocument("propDocument").getPropertyBytesArray("propBytes"))
+ .isEqualTo(new byte[][] {{3, 4}});
+
+ // Check that the new GenericDocument has modified the original fields correctly.
+ assertThat(newDoc.getParentTypes()).isEqualTo(Arrays.asList("Class3", "Class4"));
+ assertThat(newDoc.getPropertyBytesArray("propBytes")).isEqualTo(new byte[][] {{1, 2}});
+ assertThat(newDoc.getPropertyDocument("propDocument").getPropertyString("propString"))
+ .isEqualTo("Bye");
+ assertThat(newDoc.getPropertyDocument("propDocument").getPropertyBytesArray("propBytes"))
+ .isEqualTo(new byte[][] {{5, 6}});
+
+ // Check that the new GenericDocument copies fields that aren't set.
+ assertThat(oldDoc.getScore()).isEqualTo(newDoc.getScore());
+ assertThat(oldDoc.getPropertyString("propString"))
+ .isEqualTo(newDoc.getPropertyString("propString"));
+ }
}
diff --git a/testing/mockingservicestests/src/com/android/server/appsearch/FrameworkAppSearchConfigTest.java b/testing/mockingservicestests/src/com/android/server/appsearch/FrameworkAppSearchConfigTest.java
index 0faa310..908f188 100644
--- a/testing/mockingservicestests/src/com/android/server/appsearch/FrameworkAppSearchConfigTest.java
+++ b/testing/mockingservicestests/src/com/android/server/appsearch/FrameworkAppSearchConfigTest.java
@@ -33,6 +33,7 @@
import static com.android.server.appsearch.FrameworkAppSearchConfig.DEFAULT_INTEGER_INDEX_BUCKET_SPLIT_THRESHOLD;
import static com.android.server.appsearch.FrameworkAppSearchConfig.DEFAULT_LITE_INDEX_SORT_AT_INDEXING;
import static com.android.server.appsearch.FrameworkAppSearchConfig.DEFAULT_LITE_INDEX_SORT_SIZE;
+import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_BUILD_PROPERTY_EXISTENCE_METADATA_HITS;
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS;
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS;
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_SAMPLING_INTERVAL_DEFAULT;
@@ -66,7 +67,10 @@
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_RATE_LIMIT_TASK_QUEUE_TOTAL_CAPACITY;
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_RATE_LIMIT_TASK_QUEUE_PER_PACKAGE_CAPACITY_PERCENTAGE;
import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_RATE_LIMIT_API_COSTS;
+import static com.android.server.appsearch.FrameworkAppSearchConfigImpl.KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX;
+import static com.android.server.appsearch.external.localstorage.IcingOptionsConfig.DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS;
+import static com.android.server.appsearch.external.localstorage.IcingOptionsConfig.DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX;
import static com.google.common.truth.Truth.assertThat;
import android.provider.DeviceConfig;
@@ -161,6 +165,10 @@
assertThat(appSearchConfig.getLiteIndexSortAtIndexing()).isEqualTo(
DEFAULT_LITE_INDEX_SORT_AT_INDEXING);
assertThat(appSearchConfig.getLiteIndexSortSize()).isEqualTo(DEFAULT_LITE_INDEX_SORT_SIZE);
+ assertThat(appSearchConfig.getUseNewQualifiedIdJoinIndex())
+ .isEqualTo(DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX);
+ assertThat(appSearchConfig.getBuildPropertyExistenceMetadataHits())
+ .isEqualTo(DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS);
}
@Test
@@ -824,6 +832,44 @@
}
@Test
+ public void testCustomizedValue_joins() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX, Boolean.toString(true), false);
+
+ FrameworkAppSearchConfig appSearchConfig =
+ FrameworkAppSearchConfigImpl.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getUseNewQualifiedIdJoinIndex()).isEqualTo(true);
+ }
+
+ @Test
+ public void testCustomizedValueOverride_joins() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX, Boolean.toString(true), false);
+
+ FrameworkAppSearchConfig appSearchConfig =
+ FrameworkAppSearchConfigImpl.create(DIRECT_EXECUTOR);
+
+ // Override
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_USE_NEW_QUALIFIED_ID_JOIN_INDEX, Boolean.toString(false), false);
+
+ assertThat(appSearchConfig.getUseNewQualifiedIdJoinIndex()).isEqualTo(false);
+ }
+
+ @Test
+ public void testCustomizedValue_hasProperty_alwaysFalse() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ KEY_BUILD_PROPERTY_EXISTENCE_METADATA_HITS, Boolean.toString(true), false);
+
+ FrameworkAppSearchConfig appSearchConfig =
+ FrameworkAppSearchConfigImpl.create(DIRECT_EXECUTOR);
+
+ // We never turn on this flag in udc-mainline-prod.
+ assertThat(appSearchConfig.getBuildPropertyExistenceMetadataHits()).isEqualTo(false);
+ }
+
+ @Test
public void testNotUsable_afterClose() {
FrameworkAppSearchConfig appSearchConfig =
FrameworkAppSearchConfigImpl.create(DIRECT_EXECUTOR);
@@ -920,5 +966,8 @@
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getLiteIndexSortSize());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getUseNewQualifiedIdJoinIndex());
}
}
diff --git a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index 9d01cf0..788bf98 100644
--- a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -217,19 +217,10 @@
.addParentTypes("Email")
.addParentTypes("Message")
.build();
- SchemaTypeConfigProto alternativeExpectedSchemaProto =
- SchemaTypeConfigProto.newBuilder()
- .setSchemaType("EmailMessage")
- .setVersion(12345)
- .addParentTypes("Message")
- .addParentTypes("Email")
- .build();
assertThat(SchemaToProtoConverter.toSchemaTypeConfigProto(schema, /*version=*/ 12345))
- .isAnyOf(expectedSchemaProto, alternativeExpectedSchemaProto);
+ .isEqualTo(expectedSchemaProto);
assertThat(SchemaToProtoConverter.toAppSearchSchema(expectedSchemaProto)).isEqualTo(schema);
- assertThat(SchemaToProtoConverter.toAppSearchSchema(alternativeExpectedSchemaProto))
- .isEqualTo(schema);
}
@Test