Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c02dcf75 authored by Alexander Dorokhine's avatar Alexander Dorokhine
Browse files

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
parent 096b9615
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
@@ -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<android.app.appsearch.SearchResult.MatchInfo> 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<android.app.appsearch.SetSchemaResponse.MigrationFailure> 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<java.lang.String>);
    method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addIncompatibleType(@NonNull String);
    method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addIncompatibleTypes(@NonNull java.util.Collection<java.lang.String>);
    method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigratedType(@NonNull String);
    method @NonNull public android.app.appsearch.SetSchemaResponse.Builder addMigratedTypes(@NonNull java.util.Collection<java.lang.String>);
    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<android.app.appsearch.SetSchemaResponse.MigrationFailure>);
    method @NonNull public android.app.appsearch.SetSchemaResponse build();
  }

  public static class SetSchemaResponse.MigrationFailure {
    method @NonNull public android.app.appsearch.AppSearchResult<java.lang.Void> 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<java.lang.Void>);
    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 <T> android.app.appsearch.AppSearchResult<T> toAppSearchResult();
  }
+5 −1
Original line number Diff line number Diff line
@@ -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);
        }
+196 −53
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import java.util.Objects;
 * <p>This allows clients to obtain:
 *
 * <ul>
 *   <li>The document which matched, using {@link #getDocument}
 *   <li>The document which matched, using {@link #getGenericDocument}
 *   <li>Information about which properties in the document matched, and "snippet" information
 *       containing textual summaries of the document's matches, using {@link #getMatches}
 * </ul>
@@ -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<Bundle> 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 {
     * <p>{@link MatchInfo#getFullText()} returns "A commonly used fake word is foo. Another
     * nonsense word that’s used a lot is bar."
     *
     * <p>{@link MatchInfo#getExactMatchPosition()} returns [29, 32]
     * <p>{@link MatchInfo#getExactMatchRange()} returns [29, 32]
     *
     * <p>{@link MatchInfo#getExactMatch()} returns "foo"
     *
     * <p>{@link MatchInfo#getSnippetPosition()} returns [26, 33]
     * <p>{@link MatchInfo#getSnippetRange()} returns [26, 33]
     *
     * <p>{@link MatchInfo#getSnippet()} returns "is foo."
     *
@@ -172,11 +228,11 @@ public final class SearchResult {
     *
     * <p>{@link MatchInfo#getFullText()} returns "Test Name Jr."
     *
     * <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 4]
     * <p>{@link MatchInfo#getExactMatchRange()} returns [0, 4]
     *
     * <p>{@link MatchInfo#getExactMatch()} returns "Test"
     *
     * <p>{@link MatchInfo#getSnippetPosition()} returns [0, 9]
     * <p>{@link MatchInfo#getSnippetRange()} returns [0, 9]
     *
     * <p>{@link MatchInfo#getSnippet()} returns "Test Name"
     *
@@ -186,52 +242,54 @@ public final class SearchResult {
     *
     * <p>{@link MatchInfo#getFullText()} returns "TestNameJr@gmail.com"
     *
     * <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 20]
     * <p>{@link MatchInfo#getExactMatchRange()} returns [0, 20]
     *
     * <p>{@link MatchInfo#getExactMatch()} returns "TestNameJr@gmail.com"
     *
     * <p>{@link MatchInfo#getSnippetPosition()} returns [0, 20]
     * <p>{@link MatchInfo#getSnippetRange()} returns [0, 20]
     *
     * <p>{@link MatchInfo#getSnippet()} returns "TestNameJr@gmail.com"
     */
    public static final class MatchInfo {
        /** The path of the matching snippet property. */
        private static final String PROPERTY_PATH_FIELD = "propertyPath";

        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";

        private final String mPropertyPath;
        final Bundle mBundle;

        /**
         * The path of the matching snippet property.
         * Document which the match comes from.
         *
         * @hide
         * <p>If this is {@code null}, methods which require access to the document, like {@link
         * #getExactMatch}, will throw {@link NullPointerException}.
         */
        public static final String PROPERTY_PATH_FIELD = "propertyPath";
        @Nullable final GenericDocument mDocument;

        /** @hide */
        public static final String EXACT_MATCH_POSITION_LOWER_FIELD = "exactMatchPositionLower";
        /** Full text of the matched property. Populated on first use. */
        @Nullable private String mFullText;

        /** @hide */
        public static final String EXACT_MATCH_POSITION_UPPER_FIELD = "exactMatchPositionUpper";
        /** Range of property that exactly matched the query. Populated on first use. */
        @Nullable private MatchRange mExactMatchRange;

        /** @hide */
        public static final String WINDOW_POSITION_LOWER_FIELD = "windowPositionLower";

        /** @hide */
        public static final String WINDOW_POSITION_UPPER_FIELD = "windowPositionUpper";
        /** Range of some reasonable amount of context around the query. Populated on first use. */
        @Nullable private MatchRange mWindowRange;

        private final String mFullText;
        private final String mPropertyPath;
        private final Bundle mBundle;
        private MatchRange mExactMatchRange;
        private MatchRange mWindowRange;

        MatchInfo(@NonNull GenericDocument document, @NonNull Bundle bundle) {
        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.
         *
         * <p>Property Path: '.' - delimited sequence of property names indicating which property in
         * the Document these snippets correspond to.
         * <p>A property path is a '.' - delimited sequence of property names indicating which
         * property in the document these snippets correspond to.
         *
         * <p>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.
         *
         * <p>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 {
         * <p>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.
             *
             * <p>A property path is a '.' - delimited sequence of property names indicating which
             * property in the document these snippets correspond to.
             *
             * <p>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) {
+4 −12
Original line number Diff line number Diff line
@@ -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<MigrationFailure> mMigrationFailures = new ArrayList<>();
        private final ArrayList<String> mDeletedTypes = new ArrayList<>();
        private final ArrayList<String> 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;
+17 −5
Original line number Diff line number Diff line
@@ -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 <T> AppSearchResult<T> toAppSearchResult() {
        return AppSearchResult.newFailedResult(mResultCode, getMessage());
Loading