diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java index aca0fc07eb65c..f0b04fccd4063 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java @@ -19,8 +19,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.util.ArrayMap; -import com.android.internal.util.Preconditions; - import java.util.Map; import java.util.Objects; @@ -117,30 +115,26 @@ public final class AppSearchBatchResult { /** * Builder for {@link AppSearchBatchResult} objects. * - *

Once {@link #build} is called, the instance can no longer be used. - * * @param The type of the keys for which the results will be reported. * @param The type of the result objects for successful results. */ public static final class Builder { - private final Map mSuccesses = new ArrayMap<>(); - private final Map> mFailures = new ArrayMap<>(); - private final Map> mAll = new ArrayMap<>(); + private ArrayMap mSuccesses = new ArrayMap<>(); + private ArrayMap> mFailures = new ArrayMap<>(); + private ArrayMap> mAll = new ArrayMap<>(); private boolean mBuilt = false; /** * Associates the {@code key} with the provided successful return value. * *

Any previous mapping for a key, whether success or failure, is deleted. - * - * @throws IllegalStateException if the builder has already been used. */ @SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses @NonNull public Builder setSuccess( @NonNull KeyType key, @Nullable ValueType result) { - Preconditions.checkState(!mBuilt, "Builder has already been used"); Objects.requireNonNull(key); + resetIfBuilt(); return setResult(key, AppSearchResult.newSuccessfulResult(result)); } @@ -148,8 +142,6 @@ public final class AppSearchBatchResult { * Associates the {@code key} with the provided failure code and error message. * *

Any previous mapping for a key, whether success or failure, is deleted. - * - * @throws IllegalStateException if the builder has already been used. */ @SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures @NonNull @@ -157,8 +149,8 @@ public final class AppSearchBatchResult { @NonNull KeyType key, @AppSearchResult.ResultCode int resultCode, @Nullable String errorMessage) { - Preconditions.checkState(!mBuilt, "Builder has already been used"); Objects.requireNonNull(key); + resetIfBuilt(); return setResult(key, AppSearchResult.newFailedResult(resultCode, errorMessage)); } @@ -166,16 +158,14 @@ public final class AppSearchBatchResult { * Associates the {@code key} with the provided {@code result}. * *

Any previous mapping for a key, whether success or failure, is deleted. - * - * @throws IllegalStateException if the builder has already been used. */ @SuppressWarnings("MissingGetterMatchingBuilder") // See getAll @NonNull public Builder setResult( @NonNull KeyType key, @NonNull AppSearchResult result) { - Preconditions.checkState(!mBuilt, "Builder has already been used"); Objects.requireNonNull(key); Objects.requireNonNull(result); + resetIfBuilt(); if (result.isSuccess()) { mSuccesses.put(key, result.getResultValue()); mFailures.remove(key); @@ -189,14 +179,21 @@ public final class AppSearchBatchResult { /** * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}. - * - * @throws IllegalStateException if the builder has already been used. */ @NonNull public AppSearchBatchResult build() { - Preconditions.checkState(!mBuilt, "Builder has already been used"); mBuilt = true; - return new AppSearchBatchResult<>(mSuccesses, mFailures, mAll); + return new AppSearchBatchResult<>( + new ArrayMap<>(mSuccesses), new ArrayMap<>(mFailures), new ArrayMap<>(mAll)); + } + + private void resetIfBuilt() { + if (mBuilt) { + mSuccesses = new ArrayMap<>(mSuccesses); + mFailures = new ArrayMap<>(mFailures); + mAll = new ArrayMap<>(mAll); + mBuilt = false; + } } } } diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java index 736deab429e39..cc48ccb463ee5 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java @@ -892,129 +892,121 @@ public class GenericDocument { @Override @NonNull public String toString() { - return formatGenericDocumentString(this, /*indentLevel=*/ 0); + StringBuilder stringBuilder = new StringBuilder(); + appendGenericDocumentString(this, /*indentLevel=*/ 0, stringBuilder); + return stringBuilder.toString(); } - @NonNull - private static String formatGenericDocumentString( - @NonNull GenericDocument document, int indentLevel) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(getIndent(indentLevel)).append("{\n"); + private static void appendGenericDocumentString( + @NonNull GenericDocument document, int indentLevel, @NonNull StringBuilder builder) { + Objects.requireNonNull(document); + Objects.requireNonNull(builder); - String indentLevelOneString = getIndent(indentLevel + 1); + builder.append(getIndent(indentLevel)).append("{\n"); - stringBuilder - .append(indentLevelOneString) + String indent1 = getIndent(indentLevel + 1); + + builder.append(indent1) .append("namespace: \"") .append(document.getNamespace()) .append("\",\n"); - stringBuilder - .append(indentLevelOneString) - .append("id: \"") - .append(document.getId()) - .append("\",\n"); + builder.append(indent1).append("id: \"").append(document.getId()).append("\",\n"); - stringBuilder - .append(indentLevelOneString) - .append("score: " + document.getScore()) - .append(",\n"); + builder.append(indent1).append("score: ").append(document.getScore()).append(",\n"); - stringBuilder - .append(indentLevelOneString) + builder.append(indent1) .append("schemaType: \"") .append(document.getSchemaType()) .append("\",\n"); - stringBuilder - .append(indentLevelOneString) - .append("creationTimestampMillis: " + document.getCreationTimestampMillis()) + builder.append(indent1) + .append("creationTimestampMillis: ") + .append(document.getCreationTimestampMillis()) .append(",\n"); - stringBuilder - .append(indentLevelOneString) - .append("timeToLiveMillis: " + document.getTtlMillis()) + builder.append(indent1) + .append("timeToLiveMillis: ") + .append(document.getTtlMillis()) .append(",\n"); - stringBuilder.append(indentLevelOneString).append("properties: {\n"); + builder.append(indent1).append("properties: {\n"); - int idx = 0; - for (String propertyName : document.getPropertyNames()) { - Object property = document.getProperty(propertyName); - stringBuilder - .append(getIndent(indentLevel + 2)) + String[] sortedProperties = document.getPropertyNames().toArray(new String[0]); + Arrays.sort(sortedProperties); + + for (int i = 0; i < sortedProperties.length; i++) { + Object property = document.getProperty(sortedProperties[i]); + builder.append(getIndent(indentLevel + 2)) .append("\"") - .append(propertyName) + .append(sortedProperties[i]) .append("\"") .append(": "); - stringBuilder.append(getPropertyString(property, indentLevel + 2)); - if (idx != document.getPropertyNames().size() - 1) { - stringBuilder.append(",\n"); + appendPropertyString(property, indentLevel + 2, builder); + if (i != sortedProperties.length - 1) { + builder.append(",\n"); } - ++idx; } - stringBuilder.append("\n"); - stringBuilder.append(indentLevelOneString).append("}"); + builder.append("\n"); + builder.append(indent1).append("}"); - stringBuilder.append("\n"); - stringBuilder.append(getIndent(indentLevel)).append("}"); - - return stringBuilder.toString(); + builder.append("\n"); + builder.append(getIndent(indentLevel)).append("}"); } /** - * Creates string for property. + * Appends a string for the given property to the given builder. * * @param property property object to create string for. * @param indentLevel base indent level for property. + * @param builder the builder to append to. */ - @NonNull - private static String getPropertyString(@NonNull Object property, int indentLevel) { + private static void appendPropertyString( + @NonNull Object property, int indentLevel, @NonNull StringBuilder builder) { Objects.requireNonNull(property); + Objects.requireNonNull(builder); - StringBuilder str = new StringBuilder("["); - + builder.append("["); if (property instanceof GenericDocument[]) { GenericDocument[] documentValues = (GenericDocument[]) property; for (int i = 0; i < documentValues.length; ++i) { - str.append("\n"); - str.append(formatGenericDocumentString(documentValues[i], indentLevel + 1)); + builder.append("\n"); + appendGenericDocumentString(documentValues[i], indentLevel + 1, builder); if (i != documentValues.length - 1) { - str.append(", "); + builder.append(", "); } - str.append("\n"); + builder.append("\n"); } - str.append(getIndent(indentLevel)); + builder.append(getIndent(indentLevel)); } else { int propertyArrLength = Array.getLength(property); for (int i = 0; i < propertyArrLength; i++) { Object propertyElement = Array.get(property, i); if (propertyElement instanceof String) { - str.append("\"").append(propertyElement).append("\""); + builder.append("\"").append(propertyElement).append("\""); } else if (propertyElement instanceof byte[]) { - str.append(Arrays.toString((byte[]) propertyElement)); + builder.append(Arrays.toString((byte[]) propertyElement)); } else { - str.append(propertyElement); + builder.append(propertyElement); } if (i != propertyArrLength - 1) { - str.append(", "); + builder.append(", "); } } } - str.append("]"); - return str.toString(); + builder.append("]"); } - /** Creates string for given indent level. */ + /** Appends a string for given indent level to the given builder. */ @NonNull private static String getIndent(int indentLevel) { - StringBuilder indentedString = new StringBuilder(); + StringBuilder builder = new StringBuilder(); for (int i = 0; i < indentLevel; ++i) { - indentedString.append(" "); + builder.append(" "); } - return indentedString.toString(); + return builder.toString(); } /** diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java index ecc774c289ed6..6b443b3852e19 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java @@ -128,14 +128,14 @@ public class SearchResultToProtoConverter { return new SearchResult.MatchInfo.Builder(propertyPath) .setExactMatchRange( new SearchResult.MatchRange( - snippetMatchProto.getExactMatchPosition(), - snippetMatchProto.getExactMatchPosition() - + snippetMatchProto.getExactMatchBytes())) + snippetMatchProto.getExactMatchUtf16Position(), + snippetMatchProto.getExactMatchUtf16Position() + + snippetMatchProto.getExactMatchUtf16Length())) .setSnippetRange( new SearchResult.MatchRange( - snippetMatchProto.getWindowPosition(), - snippetMatchProto.getWindowPosition() - + snippetMatchProto.getWindowBytes())) + snippetMatchProto.getWindowUtf16Position(), + snippetMatchProto.getWindowUtf16Position() + + snippetMatchProto.getWindowUtf16Length())) .build(); } } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java index cf640c1a8d21d..ea5263aa9aa53 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java @@ -43,13 +43,16 @@ public class CallStats { CALL_TYPE_SET_SCHEMA, CALL_TYPE_PUT_DOCUMENTS, CALL_TYPE_GET_DOCUMENTS, - CALL_TYPE_REMOVE_DOCUMENTS, + CALL_TYPE_REMOVE_DOCUMENTS_BY_ID, CALL_TYPE_PUT_DOCUMENT, CALL_TYPE_GET_DOCUMENT, - CALL_TYPE_REMOVE_DOCUMENT, - CALL_TYPE_QUERY, + CALL_TYPE_REMOVE_DOCUMENT_BY_ID, + CALL_TYPE_SEARCH, CALL_TYPE_OPTIMIZE, CALL_TYPE_FLUSH, + CALL_TYPE_GLOBAL_SEARCH, + CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH, + CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH, }) @Retention(RetentionPolicy.SOURCE) public @interface CallType {} @@ -59,13 +62,16 @@ public class CallStats { public static final int CALL_TYPE_SET_SCHEMA = 2; public static final int CALL_TYPE_PUT_DOCUMENTS = 3; public static final int CALL_TYPE_GET_DOCUMENTS = 4; - public static final int CALL_TYPE_REMOVE_DOCUMENTS = 5; + public static final int CALL_TYPE_REMOVE_DOCUMENTS_BY_ID = 5; public static final int CALL_TYPE_PUT_DOCUMENT = 6; public static final int CALL_TYPE_GET_DOCUMENT = 7; - public static final int CALL_TYPE_REMOVE_DOCUMENT = 8; - public static final int CALL_TYPE_QUERY = 9; + public static final int CALL_TYPE_REMOVE_DOCUMENT_BY_ID = 8; + public static final int CALL_TYPE_SEARCH = 9; public static final int CALL_TYPE_OPTIMIZE = 10; public static final int CALL_TYPE_FLUSH = 11; + public static final int CALL_TYPE_GLOBAL_SEARCH = 12; + public static final int CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH = 13; + public static final int CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH = 14; @NonNull private final GeneralStats mGeneralStats; @CallType private final int mCallType; diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt index d07a3b9e229a1..85d85aa5aa314 100644 --- a/apex/appsearch/synced_jetpack_changeid.txt +++ b/apex/appsearch/synced_jetpack_changeid.txt @@ -1 +1 @@ -Ibbf4260deb720ce724be81ee4394ea96181ee0f7 +I0216abecc41d020f16ed8947a9f37b710afd331e diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java index 9e88373861287..a613e7774d33b 100644 --- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java +++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java @@ -16,18 +16,12 @@ package android.app.appsearch; - import static com.google.common.truth.Truth.assertThat; import android.os.Bundle; -import com.google.common.collect.ImmutableList; - import org.junit.Test; -import java.util.List; -import java.util.Map; - public class SearchSpecTest { @Test @@ -63,32 +57,4 @@ public class SearchSpecTest { assertThat(bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD)) .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE); } - - @Test - public void testGetProjectionTypePropertyMasks() { - SearchSpec searchSpec = - new SearchSpec.Builder() - .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) - .addProjection("TypeA", ImmutableList.of("field1", "field2.subfield2")) - .addProjection("TypeB", ImmutableList.of("field7")) - .addProjection("TypeC", ImmutableList.of()) - .build(); - - Map> typePropertyPathMap = searchSpec.getProjections(); - assertThat(typePropertyPathMap.keySet()).containsExactly("TypeA", "TypeB", "TypeC"); - assertThat(typePropertyPathMap.get("TypeA")).containsExactly("field1", "field2.subfield2"); - assertThat(typePropertyPathMap.get("TypeB")).containsExactly("field7"); - assertThat(typePropertyPathMap.get("TypeC")).isEmpty(); - } - - @Test - public void testGetRankingStrategy() { - SearchSpec searchSpec = - new SearchSpec.Builder() - .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) - .setRankingStrategy(SearchSpec.RANKING_STRATEGY_RELEVANCE_SCORE) - .build(); - assertThat(searchSpec.getRankingStrategy()) - .isEqualTo(SearchSpec.RANKING_STRATEGY_RELEVANCE_SCORE); - } } diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java index 8fe1139a771de..d3feb12912ad7 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java @@ -75,10 +75,14 @@ public class SnippetTest { .setPropertyName(propertyKeyString) .addSnippetMatches( SnippetMatchProto.newBuilder() - .setExactMatchPosition(29) - .setExactMatchBytes(3) - .setWindowPosition(26) - .setWindowBytes(6))) + .setExactMatchBytePosition(29) + .setExactMatchByteLength(3) + .setExactMatchUtf16Position(29) + .setExactMatchUtf16Length(3) + .setWindowBytePosition(26) + .setWindowByteLength(6) + .setWindowUtf16Position(26) + .setWindowUtf16Length(6))) .build(); SearchResultProto searchResultProto = SearchResultProto.newBuilder() @@ -168,19 +172,27 @@ public class SnippetTest { .setPropertyName("senderName") .addSnippetMatches( SnippetMatchProto.newBuilder() - .setExactMatchPosition(0) - .setExactMatchBytes(4) - .setWindowPosition(0) - .setWindowBytes(9))) + .setExactMatchBytePosition(0) + .setExactMatchByteLength(4) + .setExactMatchUtf16Position(0) + .setExactMatchUtf16Length(4) + .setWindowBytePosition(0) + .setWindowByteLength(9) + .setWindowUtf16Position(0) + .setWindowUtf16Length(9))) .addEntries( SnippetProto.EntryProto.newBuilder() .setPropertyName("senderEmail") .addSnippetMatches( SnippetMatchProto.newBuilder() - .setExactMatchPosition(0) - .setExactMatchBytes(20) - .setWindowPosition(0) - .setWindowBytes(20))) + .setExactMatchBytePosition(0) + .setExactMatchByteLength(20) + .setExactMatchUtf16Position(0) + .setExactMatchUtf16Length(20) + .setWindowBytePosition(0) + .setWindowByteLength(20) + .setWindowUtf16Position(0) + .setWindowUtf16Length(20))) .build(); SearchResultProto searchResultProto = SearchResultProto.newBuilder() @@ -251,19 +263,27 @@ public class SnippetTest { .setPropertyName("sender.name") .addSnippetMatches( SnippetMatchProto.newBuilder() - .setExactMatchPosition(0) - .setExactMatchBytes(4) - .setWindowPosition(0) - .setWindowBytes(9))) + .setExactMatchBytePosition(0) + .setExactMatchByteLength(4) + .setExactMatchUtf16Position(0) + .setExactMatchUtf16Length(4) + .setWindowBytePosition(0) + .setWindowByteLength(9) + .setWindowUtf16Position(0) + .setWindowUtf16Length(9))) .addEntries( SnippetProto.EntryProto.newBuilder() .setPropertyName("sender.email[1]") .addSnippetMatches( SnippetMatchProto.newBuilder() - .setExactMatchPosition(0) - .setExactMatchBytes(21) - .setWindowPosition(0) - .setWindowBytes(21))) + .setExactMatchBytePosition(0) + .setExactMatchByteLength(21) + .setExactMatchUtf16Position(0) + .setExactMatchUtf16Length(21) + .setWindowBytePosition(0) + .setWindowByteLength(21) + .setWindowUtf16Position(0) + .setWindowUtf16Length(21))) .build(); SearchResultProto searchResultProto = SearchResultProto.newBuilder() diff --git a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java index 5de8a7abc90a9..217430c37ccb9 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java @@ -89,7 +89,7 @@ public class PlatformLoggerTest { CallStats.CALL_TYPE_INITIALIZE).mSamplingRatio).isEqualTo( TEST_DEFAULT_SAMPLING_RATIO); assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME, - CallStats.CALL_TYPE_QUERY).mSamplingRatio).isEqualTo( + CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo( TEST_DEFAULT_SAMPLING_RATIO); assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME, CallStats.CALL_TYPE_FLUSH).mSamplingRatio).isEqualTo( @@ -103,7 +103,7 @@ public class PlatformLoggerTest { int querySamplingRatio = 2; final SparseIntArray samplingRatios = new SparseIntArray(); samplingRatios.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingRatio); - samplingRatios.put(CallStats.CALL_TYPE_QUERY, querySamplingRatio); + samplingRatios.put(CallStats.CALL_TYPE_SEARCH, querySamplingRatio); PlatformLogger logger = new PlatformLogger( ApplicationProvider.getApplicationContext(), UserHandle.USER_NULL, @@ -127,7 +127,7 @@ public class PlatformLoggerTest { CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingRatio).isEqualTo( putDocumentSamplingRatio); assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME, - CallStats.CALL_TYPE_QUERY).mSamplingRatio).isEqualTo( + CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo( querySamplingRatio); }