From c02dcf75f40fe71de35da7e48a70337abc079564 Mon Sep 17 00:00:00 2001 From: Alexander Dorokhine Date: Fri, 12 Mar 2021 12:12:37 -0800 Subject: [PATCH] Update platform from Jetpack. Included changes: * b2c0825: Unhide builders for AppSearch objects to facilitate testing. * dde789a: Expose Builders for SearchResult and MatchInfo. Bug: 180143983 Bug: 177954902 Test: Presubmit Change-Id: I3307cb5fd52b99bcbd72216bb4afbc7b58dd8650 --- apex/appsearch/framework/api/current.txt | 51 +++- .../app/appsearch/AppSearchSchema.java | 6 +- .../android/app/appsearch/SearchResult.java | 255 ++++++++++++++---- .../app/appsearch/SetSchemaResponse.java | 16 +- .../exceptions/AppSearchException.java | 22 +- .../AppSearchMigrationHelperImpl.java | 2 +- .../SearchResultToProtoConverter.java | 61 ++--- apex/appsearch/synced_jetpack_changeid.txt | 2 +- .../testing/external/AppSearchTestUtils.java | 2 +- .../localstorage/AppSearchImplTest.java | 6 +- .../localstorage/converter/SnippetTest.java | 12 +- 11 files changed, 310 insertions(+), 125 deletions(-) diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt index 5ded446ff81a7..9de6ed2c7663d 100644 --- a/apex/appsearch/framework/api/current.txt +++ b/apex/appsearch/framework/api/current.txt @@ -115,7 +115,6 @@ package android.app.appsearch { public abstract static class AppSearchSchema.PropertyConfig { method public int getCardinality(); - method public int getDataType(); method @NonNull public String getName(); field public static final int CARDINALITY_OPTIONAL = 2; // 0x2 field public static final int CARDINALITY_REPEATED = 1; // 0x1 @@ -265,21 +264,40 @@ package android.app.appsearch { public final class SearchResult { method @NonNull public String getDatabaseName(); - method @NonNull public android.app.appsearch.GenericDocument getDocument(); + method @Deprecated @NonNull public android.app.appsearch.GenericDocument getDocument(); + method @NonNull public android.app.appsearch.GenericDocument getGenericDocument(); method @NonNull public java.util.List getMatches(); method @NonNull public String getPackageName(); } + public static final class SearchResult.Builder { + ctor public SearchResult.Builder(@NonNull String, @NonNull String); + method @NonNull public android.app.appsearch.SearchResult.Builder addMatch(@NonNull android.app.appsearch.SearchResult.MatchInfo); + method @NonNull public android.app.appsearch.SearchResult build(); + method @NonNull public android.app.appsearch.SearchResult.Builder setGenericDocument(@NonNull android.app.appsearch.GenericDocument); + } + public static final class SearchResult.MatchInfo { method @NonNull public CharSequence getExactMatch(); - method @NonNull public android.app.appsearch.SearchResult.MatchRange getExactMatchPosition(); + method @Deprecated @NonNull public android.app.appsearch.SearchResult.MatchRange getExactMatchPosition(); + method @NonNull public android.app.appsearch.SearchResult.MatchRange getExactMatchRange(); method @NonNull public String getFullText(); method @NonNull public String getPropertyPath(); method @NonNull public CharSequence getSnippet(); - method @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetPosition(); + method @Deprecated @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetPosition(); + method @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetRange(); + } + + public static final class SearchResult.MatchInfo.Builder { + ctor public SearchResult.MatchInfo.Builder(); + method @NonNull public android.app.appsearch.SearchResult.MatchInfo build(); + method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setExactMatchRange(@NonNull android.app.appsearch.SearchResult.MatchRange); + method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setPropertyPath(@NonNull String); + method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setSnippetRange(@NonNull android.app.appsearch.SearchResult.MatchRange); } public static final class SearchResult.MatchRange { + ctor public SearchResult.MatchRange(int, int); method public int getEnd(); method public int getStart(); } @@ -361,6 +379,19 @@ package android.app.appsearch { method @NonNull public java.util.List getMigrationFailures(); } + public static final class SetSchemaResponse.Builder { + ctor public SetSchemaResponse.Builder(); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addDeletedType(@NonNull String); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addDeletedTypes(@NonNull java.util.Collection); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addIncompatibleType(@NonNull String); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addIncompatibleTypes(@NonNull java.util.Collection); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigratedType(@NonNull String); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigratedTypes(@NonNull java.util.Collection); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigrationFailure(@NonNull android.app.appsearch.SetSchemaResponse.MigrationFailure); + method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigrationFailures(@NonNull java.util.Collection); + method @NonNull public android.app.appsearch.SetSchemaResponse build(); + } + public static class SetSchemaResponse.MigrationFailure { method @NonNull public android.app.appsearch.AppSearchResult getAppSearchResult(); method @NonNull public String getNamespace(); @@ -368,11 +399,23 @@ package android.app.appsearch { method @NonNull public String getUri(); } + public static final class SetSchemaResponse.MigrationFailure.Builder { + ctor public SetSchemaResponse.MigrationFailure.Builder(); + method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure build(); + method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setAppSearchResult(@NonNull android.app.appsearch.AppSearchResult); + method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setNamespace(@NonNull String); + method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setSchemaType(@NonNull String); + method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setUri(@NonNull String); + } + } package android.app.appsearch.exceptions { public class AppSearchException extends java.lang.Exception { + ctor public AppSearchException(int); + ctor public AppSearchException(int, @Nullable String); + ctor public AppSearchException(int, @Nullable String, @Nullable Throwable); method public int getResultCode(); method @NonNull public android.app.appsearch.AppSearchResult toAppSearchResult(); } diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java index 8bf438d43cd13..2cf52716cffc2 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java @@ -309,7 +309,11 @@ public final class AppSearchSchema { return mBundle.getString(NAME_FIELD, ""); } - /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */ + /** + * Returns the type of data the property contains (e.g. string, int, bytes, etc). + * + * @hide + */ public @DataType int getDataType() { return mBundle.getInt(DATA_TYPE_FIELD, -1); } diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java index f34034b1c5c09..cb20849dd36f2 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java @@ -32,7 +32,7 @@ import java.util.Objects; *

This allows clients to obtain: * *

    - *
  • The document which matched, using {@link #getDocument} + *
  • The document which matched, using {@link #getGenericDocument} *
  • Information about which properties in the document matched, and "snippet" information * containing textual summaries of the document's matches, using {@link #getMatches} *
@@ -43,17 +43,10 @@ import java.util.Objects; * @see SearchResults */ public final class SearchResult { - /** @hide */ - public static final String DOCUMENT_FIELD = "document"; - - /** @hide */ - public static final String MATCHES_FIELD = "matches"; - - /** @hide */ - public static final String PACKAGE_NAME_FIELD = "packageName"; - - /** @hide */ - public static final String DATABASE_NAME_FIELD = "databaseName"; + static final String DOCUMENT_FIELD = "document"; + static final String MATCHES_FIELD = "matches"; + static final String PACKAGE_NAME_FIELD = "packageName"; + static final String DATABASE_NAME_FIELD = "databaseName"; @NonNull private final Bundle mBundle; @@ -74,13 +67,20 @@ public final class SearchResult { return mBundle; } + /** @deprecated TODO(b/181887768): This method exists only for dogfooder transition. */ + @NonNull + @Deprecated + public GenericDocument getDocument() { + return getGenericDocument(); + } + /** * Contains the matching {@link GenericDocument}. * * @return Document object which matched the query. */ @NonNull - public GenericDocument getDocument() { + public GenericDocument getGenericDocument() { if (mDocument == null) { mDocument = new GenericDocument( @@ -104,7 +104,7 @@ public final class SearchResult { Preconditions.checkNotNull(mBundle.getParcelableArrayList(MATCHES_FIELD)); mMatches = new ArrayList<>(matchBundles.size()); for (int i = 0; i < matchBundles.size(); i++) { - MatchInfo matchInfo = new MatchInfo(getDocument(), matchBundles.get(i)); + MatchInfo matchInfo = new MatchInfo(matchBundles.get(i), getGenericDocument()); mMatches.add(matchInfo); } } @@ -124,13 +124,69 @@ public final class SearchResult { /** * Contains the database name that stored the {@link GenericDocument}. * - * @return Database name that stored the document + * @return Name of the database within which the document is stored */ @NonNull public String getDatabaseName() { return Preconditions.checkNotNull(mBundle.getString(DATABASE_NAME_FIELD)); } + /** Builder for {@link SearchResult} objects. */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private final ArrayList mMatchInfos = new ArrayList<>(); + + private boolean mBuilt; + + /** + * Constructs a new builder for {@link SearchResult} objects. + * + * @param packageName the package name the matched document belongs to + * @param databaseName the database name the matched document belongs to. + */ + public Builder(@NonNull String packageName, @NonNull String databaseName) { + mBundle.putString(PACKAGE_NAME_FIELD, Preconditions.checkNotNull(packageName)); + mBundle.putString(DATABASE_NAME_FIELD, Preconditions.checkNotNull(databaseName)); + } + + /** + * Sets the document which matched. + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public Builder setGenericDocument(@NonNull GenericDocument document) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBundle.putBundle(DOCUMENT_FIELD, document.getBundle()); + return this; + } + + /** Adds another match to this SearchResult. */ + @NonNull + public Builder addMatch(@NonNull MatchInfo matchInfo) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkState( + matchInfo.mDocument == null, + "This MatchInfo is already associated with a SearchResult and can't be " + + "reassigned"); + mMatchInfos.add(matchInfo.mBundle); + return this; + } + + /** + * Constructs a new {@link SearchResult}. + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public SearchResult build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBundle.putParcelableArrayList(MATCHES_FIELD, mMatchInfos); + mBuilt = true; + return new SearchResult(mBundle); + } + } + /** * This class represents a match objects for any Snippets that might be present in {@link * SearchResults} from query. Using this class user can get the full text, exact matches and @@ -147,11 +203,11 @@ public final class SearchResult { *

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

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

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

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

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

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

{@link MatchInfo#getSnippet()} returns "is foo." * @@ -172,11 +228,11 @@ public final class SearchResult { * *

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

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

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

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

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

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

{@link MatchInfo#getSnippet()} returns "Test Name" * @@ -186,52 +242,54 @@ public final class SearchResult { * *

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

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

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

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

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

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

{@link MatchInfo#getSnippet()} returns "TestNameJr@gmail.com" */ public static final class MatchInfo { - /** - * The path of the matching snippet property. - * - * @hide - */ - public static final String PROPERTY_PATH_FIELD = "propertyPath"; + /** The path of the matching snippet property. */ + private static final String PROPERTY_PATH_FIELD = "propertyPath"; - /** @hide */ - public static final String EXACT_MATCH_POSITION_LOWER_FIELD = "exactMatchPositionLower"; + private static final String EXACT_MATCH_RANGE_LOWER_FIELD = "exactMatchRangeLower"; + private static final String EXACT_MATCH_RANGE_UPPER_FIELD = "exactMatchRangeUpper"; + private static final String SNIPPET_RANGE_LOWER_FIELD = "snippetRangeLower"; + private static final String SNIPPET_RANGE_UPPER_FIELD = "snippetRangeUpper"; - /** @hide */ - public static final String EXACT_MATCH_POSITION_UPPER_FIELD = "exactMatchPositionUpper"; - - /** @hide */ - public static final String WINDOW_POSITION_LOWER_FIELD = "windowPositionLower"; - - /** @hide */ - public static final String WINDOW_POSITION_UPPER_FIELD = "windowPositionUpper"; - - private final String mFullText; private final String mPropertyPath; - private final Bundle mBundle; - private MatchRange mExactMatchRange; - private MatchRange mWindowRange; + final Bundle mBundle; - MatchInfo(@NonNull GenericDocument document, @NonNull Bundle bundle) { + /** + * Document which the match comes from. + * + *

If this is {@code null}, methods which require access to the document, like {@link + * #getExactMatch}, will throw {@link NullPointerException}. + */ + @Nullable final GenericDocument mDocument; + + /** Full text of the matched property. Populated on first use. */ + @Nullable private String mFullText; + + /** Range of property that exactly matched the query. Populated on first use. */ + @Nullable private MatchRange mExactMatchRange; + + /** Range of some reasonable amount of context around the query. Populated on first use. */ + @Nullable private MatchRange mWindowRange; + + MatchInfo(@NonNull Bundle bundle, @Nullable GenericDocument document) { mBundle = Preconditions.checkNotNull(bundle); - Preconditions.checkNotNull(document); + mDocument = document; mPropertyPath = Preconditions.checkNotNull(bundle.getString(PROPERTY_PATH_FIELD)); - mFullText = getPropertyValues(document, mPropertyPath); } /** * Gets the property path corresponding to the given entry. * - *

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

A property path is a '.' - delimited sequence of property names indicating which + * property in the document these snippets correspond to. * *

Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. For class * example 1 this returns "subject" @@ -249,21 +307,34 @@ public final class SearchResult { */ @NonNull public String getFullText() { + if (mFullText == null) { + Preconditions.checkState( + mDocument != null, + "Document has not been populated; this MatchInfo cannot be used yet"); + mFullText = getPropertyValues(mDocument, mPropertyPath); + } return mFullText; } + /** @deprecated TODO(b/181887768): This method exists only for dogfooder transition. */ + @NonNull + @Deprecated + public MatchRange getExactMatchPosition() { + return getExactMatchRange(); + } + /** * Gets the exact {@link MatchRange} corresponding to the given entry. * *

For class example 1 this returns [29, 32] */ @NonNull - public MatchRange getExactMatchPosition() { + public MatchRange getExactMatchRange() { if (mExactMatchRange == null) { mExactMatchRange = new MatchRange( - mBundle.getInt(EXACT_MATCH_POSITION_LOWER_FIELD), - mBundle.getInt(EXACT_MATCH_POSITION_UPPER_FIELD)); + mBundle.getInt(EXACT_MATCH_RANGE_LOWER_FIELD), + mBundle.getInt(EXACT_MATCH_RANGE_UPPER_FIELD)); } return mExactMatchRange; } @@ -275,7 +346,14 @@ public final class SearchResult { */ @NonNull public CharSequence getExactMatch() { - return getSubstring(getExactMatchPosition()); + return getSubstring(getExactMatchRange()); + } + + /** @deprecated TODO(b/181887768): This method exists only for dogfooder transition. */ + @NonNull + @Deprecated + public MatchRange getSnippetPosition() { + return getSnippetRange(); } /** @@ -287,12 +365,12 @@ public final class SearchResult { *

For class example 1 this returns [29, 41]. */ @NonNull - public MatchRange getSnippetPosition() { + public MatchRange getSnippetRange() { if (mWindowRange == null) { mWindowRange = new MatchRange( - mBundle.getInt(WINDOW_POSITION_LOWER_FIELD), - mBundle.getInt(WINDOW_POSITION_UPPER_FIELD)); + mBundle.getInt(SNIPPET_RANGE_LOWER_FIELD), + mBundle.getInt(SNIPPET_RANGE_UPPER_FIELD)); } return mWindowRange; } @@ -309,7 +387,7 @@ public final class SearchResult { */ @NonNull public CharSequence getSnippet() { - return getSubstring(getSnippetPosition()); + return getSubstring(getSnippetRange()); } private CharSequence getSubstring(MatchRange range) { @@ -331,6 +409,72 @@ public final class SearchResult { // TODO(b/175146044): Return the proper match based on the index in the propertyName. return values[0]; } + + /** Builder for {@link MatchInfo} objects. */ + public static final class Builder { + private final Bundle mBundle = new Bundle(); + private boolean mBuilt = false; + + /** + * Sets the property path corresponding to the given entry. + * + *

A property path is a '.' - delimited sequence of property names indicating which + * property in the document these snippets correspond to. + * + *

Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. For class + * example 1 this returns "subject" + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public Builder setPropertyPath(@NonNull String propertyPath) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBundle.putString( + SearchResult.MatchInfo.PROPERTY_PATH_FIELD, + Preconditions.checkNotNull(propertyPath)); + return this; + } + + /** + * Sets the exact {@link MatchRange} corresponding to the given entry. + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public Builder setExactMatchRange(@NonNull MatchRange matchRange) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(matchRange); + mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_LOWER_FIELD, matchRange.getStart()); + mBundle.putInt(MatchInfo.EXACT_MATCH_RANGE_UPPER_FIELD, matchRange.getEnd()); + return this; + } + + /** + * Sets the snippet {@link MatchRange} corresponding to the given entry. + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public Builder setSnippetRange(@NonNull MatchRange matchRange) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(matchRange); + mBundle.putInt(MatchInfo.SNIPPET_RANGE_LOWER_FIELD, matchRange.getStart()); + mBundle.putInt(MatchInfo.SNIPPET_RANGE_UPPER_FIELD, matchRange.getEnd()); + return this; + } + + /** + * Constructs a new {@link MatchInfo}. + * + * @throws IllegalStateException if the builder has already been used + */ + @NonNull + public MatchInfo build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new MatchInfo(mBundle, /*document=*/ null); + } + } } /** @@ -353,7 +497,6 @@ public final class SearchResult { * * @param start The start point (inclusive) * @param end The end point (exclusive) - * @hide */ public MatchRange(int start, int end) { if (start > end) { diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java index a146006f355ce..98cd49b79737a 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java @@ -160,12 +160,8 @@ public class SetSchemaResponse { .addMigrationFailures(mMigrationFailures); } - /** - * Builder for {@link SetSchemaResponse} objects. - * - * @hide - */ - public static class Builder { + /** Builder for {@link SetSchemaResponse} objects. */ + public static final class Builder { private final ArrayList mMigrationFailures = new ArrayList<>(); private final ArrayList mDeletedTypes = new ArrayList<>(); private final ArrayList mMigratedTypes = new ArrayList<>(); @@ -309,12 +305,8 @@ public class SetSchemaResponse { mBundle.getString(ERROR_MESSAGE_FIELD, /*defaultValue=*/ "")); } - /** - * Builder for {@link MigrationFailure} objects. - * - * @hide - */ - public static class Builder { + /** Builder for {@link MigrationFailure} objects. */ + public static final class Builder { private String mSchemaType; private String mNamespace; private String mUri; diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java index b1a33a478a47e..ca4ea2bfd3bb7 100644 --- a/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java @@ -32,19 +32,27 @@ public class AppSearchException extends Exception { /** * Initializes an {@link AppSearchException} with no message. * - * @hide + * @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}. */ public AppSearchException(@AppSearchResult.ResultCode int resultCode) { this(resultCode, /*message=*/ null); } - /** @hide */ + /** + * Initializes an {@link AppSearchException} with a result code and message. + * + * @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}. + */ public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message) { this(resultCode, message, /*cause=*/ null); } - /** @hide */ + /** + * Initializes an {@link AppSearchException} with a result code, message and cause. + * + * @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}. + */ public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message, @@ -53,12 +61,16 @@ public class AppSearchException extends Exception { mResultCode = resultCode; } - /** Returns the result code this exception was constructed with. */ + /** + * Returns the result code this exception was constructed with. + * + * @return One of the constants documented in {@link AppSearchResult#getResultCode}. + */ public @AppSearchResult.ResultCode int getResultCode() { return mResultCode; } - /** Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult} */ + /** Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult}. */ @NonNull public AppSearchResult toAppSearchResult() { return AppSearchResult.newFailedResult(mResultCode, getMessage()); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java index a7f1cc4c793fa..4b8ce6d2c1d1f 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchMigrationHelperImpl.java @@ -93,7 +93,7 @@ class AppSearchMigrationHelperImpl implements AppSearchMigrationHelper { migrator.transform( currentVersion, finalVersion, - searchResultPage.getResults().get(i).getDocument()); + searchResultPage.getResults().get(i).getGenericDocument()); Bundle bundle = newDocument.getBundle(); Parcel parcel = Parcel.obtain(); parcel.writeBundle(bundle); 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 e9852aa1cd41b..1d8db7233a7ac 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 @@ -58,14 +58,14 @@ public class SearchResultToProtoConverter { @NonNull List databaseNames) { Preconditions.checkArgument( 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."); Bundle bundle = new Bundle(); bundle.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, proto.getNextPageToken()); ArrayList resultBundles = new ArrayList<>(proto.getResultsCount()); for (int i = 0; i < proto.getResultsCount(); i++) { - resultBundles.add( - toSearchResultBundle( - proto.getResults(i), packageNames.get(i), databaseNames.get(i))); + SearchResult result = + toSearchResult(proto.getResults(i), packageNames.get(i), databaseNames.get(i)); + resultBundles.add(result.getBundle()); } bundle.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, resultBundles); return new SearchResultPage(bundle); @@ -80,50 +80,41 @@ public class SearchResultToProtoConverter { * @return A {@link SearchResult} bundle. */ @NonNull - private static Bundle toSearchResultBundle( + private static SearchResult toSearchResult( @NonNull SearchResultProto.ResultProtoOrBuilder proto, @NonNull String packageName, @NonNull String databaseName) { - Bundle bundle = new Bundle(); GenericDocument document = GenericDocumentToProtoConverter.toGenericDocument(proto.getDocument()); - bundle.putBundle(SearchResult.DOCUMENT_FIELD, document.getBundle()); - bundle.putString(SearchResult.PACKAGE_NAME_FIELD, packageName); - bundle.putString(SearchResult.DATABASE_NAME_FIELD, databaseName); - - ArrayList matchList = new ArrayList<>(); + SearchResult.Builder builder = + new SearchResult.Builder(packageName, databaseName).setGenericDocument(document); if (proto.hasSnippet()) { for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) { SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i); for (int j = 0; j < entry.getSnippetMatchesCount(); j++) { - Bundle matchInfoBundle = - convertToMatchInfoBundle( - entry.getSnippetMatches(j), entry.getPropertyName()); - matchList.add(matchInfoBundle); + SearchResult.MatchInfo matchInfo = + toMatchInfo(entry.getSnippetMatches(j), entry.getPropertyName()); + builder.addMatch(matchInfo); } } } - bundle.putParcelableArrayList(SearchResult.MATCHES_FIELD, matchList); - - return bundle; + return builder.build(); } - private static Bundle convertToMatchInfoBundle( - SnippetMatchProto snippetMatchProto, String propertyPath) { - Bundle bundle = new Bundle(); - bundle.putString(SearchResult.MatchInfo.PROPERTY_PATH_FIELD, propertyPath); - bundle.putInt( - SearchResult.MatchInfo.EXACT_MATCH_POSITION_LOWER_FIELD, - snippetMatchProto.getExactMatchPosition()); - bundle.putInt( - SearchResult.MatchInfo.EXACT_MATCH_POSITION_UPPER_FIELD, - snippetMatchProto.getExactMatchPosition() + snippetMatchProto.getExactMatchBytes()); - bundle.putInt( - SearchResult.MatchInfo.WINDOW_POSITION_LOWER_FIELD, - snippetMatchProto.getWindowPosition()); - bundle.putInt( - SearchResult.MatchInfo.WINDOW_POSITION_UPPER_FIELD, - snippetMatchProto.getWindowPosition() + snippetMatchProto.getWindowBytes()); - return bundle; + private static SearchResult.MatchInfo toMatchInfo( + @NonNull SnippetMatchProto snippetMatchProto, @NonNull String propertyPath) { + return new SearchResult.MatchInfo.Builder() + .setPropertyPath(propertyPath) + .setExactMatchRange( + new SearchResult.MatchRange( + snippetMatchProto.getExactMatchPosition(), + snippetMatchProto.getExactMatchPosition() + + snippetMatchProto.getExactMatchBytes())) + .setSnippetRange( + new SearchResult.MatchRange( + snippetMatchProto.getWindowPosition(), + snippetMatchProto.getWindowPosition() + + snippetMatchProto.getWindowBytes())) + .build(); } } diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt index 41c70f072262b..68531b6ee1e55 100644 --- a/apex/appsearch/synced_jetpack_changeid.txt +++ b/apex/appsearch/synced_jetpack_changeid.txt @@ -1 +1 @@ -I42b89416968565ceb6483b400894f5b49524208c +I1926fb1d13628607f7a513c8149b65dd86c98dd6 diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java index 37717d6837b91..28b1e9983517b 100644 --- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java @@ -80,7 +80,7 @@ public class AppSearchTestUtils { List documents = new ArrayList<>(); while (results.size() > 0) { for (SearchResult result : results) { - documents.add(result.getDocument()); + documents.add(result.getGenericDocument()); } results = searchResults.getNextPage().get(); } diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index 6890ed1688bbc..90ce6e2ac168a 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -632,7 +632,7 @@ public class AppSearchImplTest { // No query filters specified. package2 should only get its own documents back. searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec); assertThat(searchResultPage.getResults()).hasSize(1); - assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document); } /** @@ -692,7 +692,7 @@ public class AppSearchImplTest { .build(); searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec); assertThat(searchResultPage.getResults()).hasSize(1); - assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document); } @Test @@ -1073,7 +1073,7 @@ public class AppSearchImplTest { for (SearchResult result : searchResultPage.getResults()) { assertThat(result.getPackageName()).isEqualTo("com.package.foo"); assertThat(result.getDatabaseName()).isEqualTo("databaseName"); - assertThat(result.getDocument()) + assertThat(result.getGenericDocument()) .isEqualTo( GenericDocumentToProtoConverter.toGenericDocument( strippedDocumentProto.build())); 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 0b1c120d8a1e4..d07211fe20286 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 @@ -93,10 +93,10 @@ public class SnippetTest { assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString); assertThat(match.getFullText()).isEqualTo(propertyValueString); assertThat(match.getExactMatch()).isEqualTo(exactMatch); - assertThat(match.getExactMatchPosition()) + assertThat(match.getExactMatchRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 29, /*upper=*/ 32)); assertThat(match.getFullText()).isEqualTo(propertyValueString); - assertThat(match.getSnippetPosition()) + assertThat(match.getSnippetRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 26, /*upper=*/ 32)); assertThat(match.getSnippet()).isEqualTo(window); } @@ -210,20 +210,20 @@ public class SnippetTest { SearchResult.MatchInfo match1 = result.getMatches().get(0); assertThat(match1.getPropertyPath()).isEqualTo("sender.name"); assertThat(match1.getFullText()).isEqualTo("Test Name Jr."); - assertThat(match1.getExactMatchPosition()) + assertThat(match1.getExactMatchRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4)); assertThat(match1.getExactMatch()).isEqualTo("Test"); - assertThat(match1.getSnippetPosition()) + assertThat(match1.getSnippetRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9)); assertThat(match1.getSnippet()).isEqualTo("Test Name"); SearchResult.MatchInfo match2 = result.getMatches().get(1); assertThat(match2.getPropertyPath()).isEqualTo("sender.email"); assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com"); - assertThat(match2.getExactMatchPosition()) + assertThat(match2.getExactMatchRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20)); assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com"); - assertThat(match2.getSnippetPosition()) + assertThat(match2.getSnippetRange()) .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20)); assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com"); }