Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java +41 −40 Original line number Diff line number Diff line Loading @@ -26,30 +26,32 @@ import java.util.Collections; import java.util.Map; /** * Provides access to multiple results from a batch operation accepting multiple inputs. * Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple * inputs. * * @param <KeyType> The type of the keys for {@link #getResults} and {@link #getFailures}. * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}. * @param <ValueType> The type of result objects associated with the keys. * @hide */ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { @NonNull private final Map<KeyType, ValueType> mResults; @NonNull private final Map<KeyType, Throwable> mFailures; @NonNull private final Map<KeyType, AppSearchResult<ValueType>> mSuccesses; @NonNull private final Map<KeyType, AppSearchResult<ValueType>> mFailures; private AppSearchBatchResult( @NonNull Map<KeyType, ValueType> results, @NonNull Map<KeyType, Throwable> failures) { mResults = results; @NonNull Map<KeyType, AppSearchResult<ValueType>> successes, @NonNull Map<KeyType, AppSearchResult<ValueType>> failures) { mSuccesses = successes; mFailures = failures; } private AppSearchBatchResult(@NonNull Parcel in) { mResults = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); mSuccesses = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); mFailures = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeMap(mResults); dest.writeMap(mSuccesses); dest.writeMap(mFailures); } Loading @@ -59,23 +61,24 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { } /** * Returns a {@link Map} of all successful keys mapped to the results they produced. * Returns a {@link Map} of all successful keys mapped to the successful * {@link AppSearchResult}s they produced. * * <p>The values of the {@link Map} may be {@code null}. * <p>The values of the {@link Map} will not be {@code null}. */ @NonNull public Map<KeyType, ValueType> getResults() { return mResults; public Map<KeyType, AppSearchResult<ValueType>> getSuccesses() { return mSuccesses; } /** * Returns a {@link Map} of all failed keys mapped to a {@link Throwable} representing the cause * of failure. * Returns a {@link Map} of all failed keys mapped to the failed {@link AppSearchResult}s they * produced. * * <p>The values of the {@link Map} may be {@code null}. * <p>The values of the {@link Map} will not be {@code null}. */ @NonNull public Map<KeyType, Throwable> getFailures() { public Map<KeyType, AppSearchResult<ValueType>> getFailures() { return mFailures; } Loading @@ -99,15 +102,6 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { } }; /** * Creates a new {@link Builder} for this {@link AppSearchBatchResult}. * @hide */ @NonNull public static <KeyType, ValueType> Builder<KeyType, ValueType> newBuilder() { return new Builder<>(); } /** * Builder for {@link AppSearchBatchResult} objects. * Loading @@ -116,35 +110,42 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { * @hide */ public static final class Builder<KeyType, ValueType> { @NonNull private final Map<KeyType, ValueType> mResults = new ArrayMap<>(); @NonNull private final Map<KeyType, Throwable> mFailures = new ArrayMap<>(); private final Map<KeyType, AppSearchResult<ValueType>> mSuccesses = new ArrayMap<>(); private final Map<KeyType, AppSearchResult<ValueType>> mFailures = new ArrayMap<>(); private Builder() {} /** Creates a new {@link Builder} for this {@link AppSearchBatchResult}. */ public Builder() {} /** * Registers that the {@code key} was processed successfully and associates it with * {@code value}. Any previous mapping for a key, whether success or failure, is deleted. * Associates the {@code key} with the given successful return value. * * <p>Any previous mapping for a key, whether success or failure, is deleted. */ public Builder setSuccess(@NonNull KeyType key, @Nullable ValueType value) { mResults.put(key, value); mFailures.remove(key); return this; public Builder setSuccess(@NonNull KeyType key, @Nullable ValueType result) { return setResult(key, AppSearchResult.newSuccessfulResult(result)); } /** * Registers that the {@code key} failed and associates it with {@code throwable}. Any * previous mapping for a key, whether success or failure, is deleted. * Associates the {@code key} with the given {@code result}. * * <p>Any previous mapping for a key, whether success or failure, is deleted. */ public Builder setFailure(@NonNull KeyType key, @Nullable Throwable throwable) { mFailures.put(key, throwable); mResults.remove(key); @NonNull public Builder setResult(@NonNull KeyType key, @NonNull AppSearchResult<ValueType> result) { if (result.isSuccess()) { mSuccesses.put(key, result); mFailures.remove(key); } else { mFailures.put(key, result); mSuccesses.remove(key); } return this; } /** Builds an {@link AppSearchBatchResult} from the contents of this {@link Builder}. */ @NonNull public AppSearchBatchResult<KeyType, ValueType> build() { return new AppSearchBatchResult<>(mResults, mFailures); return new AppSearchBatchResult<>(mSuccesses, mFailures); } } } apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +19 −15 Original line number Diff line number Diff line Loading @@ -75,9 +75,7 @@ public class AppSearchManager { * REPEATED} property. * </ul> * * <p>The following types of schema changes are not backwards-compatible. Supplying a schema * with such changes will result in this call throwing an {@link IllegalSchemaException} * describing the incompatibility, and the previously set schema will remain active: * <p>The following types of schema changes are not backwards-compatible: * <ul> * <li>Removal of an existing type * <li>Removal of a property from a type Loading @@ -93,6 +91,10 @@ public class AppSearchManager { * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED * REQUIRED} property. * </ul> * <p>Supplying a schema with such changes will result in this call returning an * {@link AppSearchResult} with a code of {@link AppSearchResult#RESULT_INVALID_SCHEMA} and an * error message describing the incompatibility. In this case the previously set schema will * remain active. * * <p>If you need to make non-backwards-compatible changes as described above, instead use the * {@link #setSchema(List, boolean)} method with the {@code forceOverride} parameter set to Loading @@ -102,13 +104,13 @@ public class AppSearchManager { * efficiently. * * @param schemas The schema configs for the types used by the calling app. * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the * previous schema. * @return the result of performing this operation. * * @hide */ public void setSchema(@NonNull AppSearchSchema... schemas) { setSchema(Arrays.asList(schemas), /*forceOverride=*/false); @NonNull public AppSearchResult<Void> setSchema(@NonNull AppSearchSchema... schemas) { return setSchema(Arrays.asList(schemas), /*forceOverride=*/false); } /** Loading @@ -116,20 +118,22 @@ public class AppSearchManager { * * <p>This method is similar to {@link #setSchema(AppSearchSchema...)}, except for the * {@code forceOverride} parameter. If a backwards-incompatible schema is specified but the * {@code forceOverride} parameter is set to {@code true}, instead of throwing an * {@link IllegalSchemaException}, all documents which are not compatible with the new schema * will be deleted and the incompatible schema will be applied. * {@code forceOverride} parameter is set to {@code true}, instead of returning an * {@link AppSearchResult} with the {@link AppSearchResult#RESULT_INVALID_SCHEMA} code, all * documents which are not compatible with the new schema will be deleted and the incompatible * schema will be applied. * * @param schemas The schema configs for the types used by the calling app. * @param forceOverride Whether to force the new schema to be applied even if there are * incompatible changes versus the previously set schema. Documents which are incompatible * with the new schema will be deleted. * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the * previous schema and the {@code forceOverride} parameter is set to {@code false}. * @return the result of performing this operation. * * @hide */ public void setSchema(@NonNull List<AppSearchSchema> schemas, boolean forceOverride) { @NonNull public AppSearchResult<Void> setSchema( @NonNull List<AppSearchSchema> schemas, boolean forceOverride) { // Prepare the merged schema for transmission. SchemaProto.Builder schemaProtoBuilder = SchemaProto.newBuilder(); for (AppSearchSchema schema : schemas) { Loading @@ -140,13 +144,13 @@ public class AppSearchManager { // TODO: This should use com.android.internal.infra.RemoteStream or another mechanism to // avoid binder limits. byte[] schemaBytes = schemaProtoBuilder.build().toByteArray(); AndroidFuture<Void> future = new AndroidFuture<>(); AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { mService.setSchema(schemaBytes, forceOverride, future); } catch (RemoteException e) { future.completeExceptionally(e); } getFutureOrThrow(future); return getFutureOrThrow(future); } /** Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java 0 → 100644 +216 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Information about the success or failure of an AppSearch call. * * @param <ValueType> The type of result object for successful calls. * @hide */ public class AppSearchResult<ValueType> implements Parcelable { /** Result codes from {@link AppSearchManager} methods. */ @IntDef(prefix = {"RESULT_"}, value = { RESULT_OK, RESULT_UNKNOWN_ERROR, RESULT_INTERNAL_ERROR, RESULT_INVALID_ARGUMENT, RESULT_IO_ERROR, RESULT_OUT_OF_SPACE, RESULT_NOT_FOUND, RESULT_INVALID_SCHEMA, }) @Retention(RetentionPolicy.SOURCE) public @interface ResultCode {} /** The call was successful. */ public static final int RESULT_OK = 0; /** An unknown error occurred while processing the call. */ public static final int RESULT_UNKNOWN_ERROR = 1; /** * An internal error occurred within AppSearch, which the caller cannot address. * * * This error may be considered similar to {@link IllegalStateException} */ public static final int RESULT_INTERNAL_ERROR = 2; /** * The caller supplied invalid arguments to the call. * * This error may be considered similar to {@link IllegalArgumentException}. */ public static final int RESULT_INVALID_ARGUMENT = 3; /** * An issue occurred reading or writing to storage. The call might succeed if repeated. * * This error may be considered similar to {@link java.io.IOException}. */ public static final int RESULT_IO_ERROR = 4; /** Storage is out of space, and no more space could be reclaimed. */ public static final int RESULT_OUT_OF_SPACE = 5; /** An entity the caller requested to interact with does not exist in the system. */ public static final int RESULT_NOT_FOUND = 6; /** The caller supplied a schema which is invalid or incompatible with the previous schema. */ public static final int RESULT_INVALID_SCHEMA = 7; private final @ResultCode int mResultCode; @Nullable private final ValueType mResultValue; @Nullable private final String mErrorMessage; private AppSearchResult( @ResultCode int resultCode, @Nullable ValueType resultValue, @Nullable String errorMessage) { mResultCode = resultCode; mResultValue = resultValue; mErrorMessage = errorMessage; } private AppSearchResult(@NonNull Parcel in) { mResultCode = in.readInt(); mResultValue = (ValueType) in.readValue(/*loader=*/ null); mErrorMessage = in.readString(); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mResultCode); dest.writeValue(mResultValue); dest.writeString(mErrorMessage); } /** Returns {@code true} if {@link #getResultCode} equals {@link AppSearchResult#RESULT_OK}. */ public boolean isSuccess() { return getResultCode() == RESULT_OK; } /** Returns one of the {@code RESULT} constants defined in {@link AppSearchResult}. */ public @ResultCode int getResultCode() { return mResultCode; } /** * Returns the returned value associated with this result. * * <p>If {@link #isSuccess} is {@code false}, the result value is always {@code null}. The value * may be {@code null} even if {@link #isSuccess} is {@code true}. See the documentation of the * particular {@link AppSearchManager} call producing this {@link AppSearchResult} for what is * returned by {@link #getResultValue}. */ @Nullable public ValueType getResultValue() { return mResultValue; } /** * Returns the error message associated with this result. * * <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}. The error * message may be {@code null} even if {@link #isSuccess} is {@code false}. See the * documentation of the particular {@link AppSearchManager} call producing this * {@link AppSearchResult} for what is returned by {@link #getErrorMessage}. */ @Nullable public String getErrorMessage() { return mErrorMessage; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof AppSearchResult)) { return false; } AppSearchResult<?> otherResult = (AppSearchResult) other; return mResultCode == otherResult.mResultCode && Objects.equals(mResultValue, otherResult.mResultValue) && Objects.equals(mErrorMessage, otherResult.mErrorMessage); } @Override public int hashCode() { return Objects.hash(mResultCode, mResultValue, mErrorMessage); } @Override @NonNull public String toString() { if (isSuccess()) { return "AppSearchResult [SUCCESS]: " + mResultValue; } return "AppSearchResult [FAILURE(" + mResultCode + ")]: " + mErrorMessage; } @Override public int describeContents() { return 0; } public static final Creator<AppSearchResult> CREATOR = new Creator<AppSearchResult>() { @NonNull @Override public AppSearchResult createFromParcel(@NonNull Parcel in) { return new AppSearchResult(in); } @NonNull @Override public AppSearchResult[] newArray(int size) { return new AppSearchResult[size]; } }; /** * Creates a new successful {@link AppSearchResult}. * @hide */ @NonNull public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult( @Nullable ValueType value) { return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null); } /** * Creates a new failed {@link AppSearchResult}. * @hide */ @NonNull public static <ValueType> AppSearchResult<ValueType> newFailedResult( @ResultCode int resultCode, @Nullable String errorMessage) { return new AppSearchResult<>(resultCode, /*resultValue=*/ null, errorMessage); } } apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.appsearch; import com.android.internal.infra.AndroidFuture; parcelable AppSearchResult; parcelable AppSearchBatchResult; /** {@hide} */ Loading @@ -27,11 +28,11 @@ interface IAppSearchManager { * @param schemaBytes Serialized SchemaProto. * @param forceOverride Whether to apply the new schema even if it is incompatible. All * incompatible documents will be deleted. * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with * {@code null} upon successful completion of the setSchema call, or completed * exceptionally if setSchema fails. * @param callback {@link AndroidFuture}<{@link AppSearchResult}<{@link Void}>>. * The results of the call. */ void setSchema(in byte[] schemaBytes, boolean forceOverride, in AndroidFuture callback); void setSchema( in byte[] schemaBytes, boolean forceOverride, in AndroidFuture<AppSearchResult> callback); /** * Inserts documents into the index. Loading apex/appsearch/service/java/com/android/server/appsearch/AppSearchException.java 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appsearch; import android.annotation.Nullable; import android.app.appsearch.AppSearchResult; /** * An exception thrown by {@link com.android.server.appsearch.AppSearchManagerService} or a * subcomponent. * * <p>These exceptions can be converted into a failed {@link android.app.appsearch.AppSearchResult} * for propagating to the client. */ public class AppSearchException extends Exception { private final @AppSearchResult.ResultCode int mResultCode; /** Initializes an {@link com.android.server.appsearch.AppSearchException} with no message. */ public AppSearchException(@AppSearchResult.ResultCode int resultCode) { this(resultCode, /*message=*/ null); } public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message) { this(resultCode, message, /*cause=*/ null); } public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message, @Nullable Throwable cause) { super(message, cause); mResultCode = resultCode; } /** * Converts this {@link java.lang.Exception} into a failed * {@link android.app.appsearch.AppSearchResult} */ public <T> AppSearchResult<T> toAppSearchResult() { return AppSearchResult.newFailedResult(mResultCode, getMessage()); } } Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java +41 −40 Original line number Diff line number Diff line Loading @@ -26,30 +26,32 @@ import java.util.Collections; import java.util.Map; /** * Provides access to multiple results from a batch operation accepting multiple inputs. * Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple * inputs. * * @param <KeyType> The type of the keys for {@link #getResults} and {@link #getFailures}. * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}. * @param <ValueType> The type of result objects associated with the keys. * @hide */ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { @NonNull private final Map<KeyType, ValueType> mResults; @NonNull private final Map<KeyType, Throwable> mFailures; @NonNull private final Map<KeyType, AppSearchResult<ValueType>> mSuccesses; @NonNull private final Map<KeyType, AppSearchResult<ValueType>> mFailures; private AppSearchBatchResult( @NonNull Map<KeyType, ValueType> results, @NonNull Map<KeyType, Throwable> failures) { mResults = results; @NonNull Map<KeyType, AppSearchResult<ValueType>> successes, @NonNull Map<KeyType, AppSearchResult<ValueType>> failures) { mSuccesses = successes; mFailures = failures; } private AppSearchBatchResult(@NonNull Parcel in) { mResults = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); mSuccesses = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); mFailures = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeMap(mResults); dest.writeMap(mSuccesses); dest.writeMap(mFailures); } Loading @@ -59,23 +61,24 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { } /** * Returns a {@link Map} of all successful keys mapped to the results they produced. * Returns a {@link Map} of all successful keys mapped to the successful * {@link AppSearchResult}s they produced. * * <p>The values of the {@link Map} may be {@code null}. * <p>The values of the {@link Map} will not be {@code null}. */ @NonNull public Map<KeyType, ValueType> getResults() { return mResults; public Map<KeyType, AppSearchResult<ValueType>> getSuccesses() { return mSuccesses; } /** * Returns a {@link Map} of all failed keys mapped to a {@link Throwable} representing the cause * of failure. * Returns a {@link Map} of all failed keys mapped to the failed {@link AppSearchResult}s they * produced. * * <p>The values of the {@link Map} may be {@code null}. * <p>The values of the {@link Map} will not be {@code null}. */ @NonNull public Map<KeyType, Throwable> getFailures() { public Map<KeyType, AppSearchResult<ValueType>> getFailures() { return mFailures; } Loading @@ -99,15 +102,6 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { } }; /** * Creates a new {@link Builder} for this {@link AppSearchBatchResult}. * @hide */ @NonNull public static <KeyType, ValueType> Builder<KeyType, ValueType> newBuilder() { return new Builder<>(); } /** * Builder for {@link AppSearchBatchResult} objects. * Loading @@ -116,35 +110,42 @@ public class AppSearchBatchResult<KeyType, ValueType> implements Parcelable { * @hide */ public static final class Builder<KeyType, ValueType> { @NonNull private final Map<KeyType, ValueType> mResults = new ArrayMap<>(); @NonNull private final Map<KeyType, Throwable> mFailures = new ArrayMap<>(); private final Map<KeyType, AppSearchResult<ValueType>> mSuccesses = new ArrayMap<>(); private final Map<KeyType, AppSearchResult<ValueType>> mFailures = new ArrayMap<>(); private Builder() {} /** Creates a new {@link Builder} for this {@link AppSearchBatchResult}. */ public Builder() {} /** * Registers that the {@code key} was processed successfully and associates it with * {@code value}. Any previous mapping for a key, whether success or failure, is deleted. * Associates the {@code key} with the given successful return value. * * <p>Any previous mapping for a key, whether success or failure, is deleted. */ public Builder setSuccess(@NonNull KeyType key, @Nullable ValueType value) { mResults.put(key, value); mFailures.remove(key); return this; public Builder setSuccess(@NonNull KeyType key, @Nullable ValueType result) { return setResult(key, AppSearchResult.newSuccessfulResult(result)); } /** * Registers that the {@code key} failed and associates it with {@code throwable}. Any * previous mapping for a key, whether success or failure, is deleted. * Associates the {@code key} with the given {@code result}. * * <p>Any previous mapping for a key, whether success or failure, is deleted. */ public Builder setFailure(@NonNull KeyType key, @Nullable Throwable throwable) { mFailures.put(key, throwable); mResults.remove(key); @NonNull public Builder setResult(@NonNull KeyType key, @NonNull AppSearchResult<ValueType> result) { if (result.isSuccess()) { mSuccesses.put(key, result); mFailures.remove(key); } else { mFailures.put(key, result); mSuccesses.remove(key); } return this; } /** Builds an {@link AppSearchBatchResult} from the contents of this {@link Builder}. */ @NonNull public AppSearchBatchResult<KeyType, ValueType> build() { return new AppSearchBatchResult<>(mResults, mFailures); return new AppSearchBatchResult<>(mSuccesses, mFailures); } } }
apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +19 −15 Original line number Diff line number Diff line Loading @@ -75,9 +75,7 @@ public class AppSearchManager { * REPEATED} property. * </ul> * * <p>The following types of schema changes are not backwards-compatible. Supplying a schema * with such changes will result in this call throwing an {@link IllegalSchemaException} * describing the incompatibility, and the previously set schema will remain active: * <p>The following types of schema changes are not backwards-compatible: * <ul> * <li>Removal of an existing type * <li>Removal of a property from a type Loading @@ -93,6 +91,10 @@ public class AppSearchManager { * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED * REQUIRED} property. * </ul> * <p>Supplying a schema with such changes will result in this call returning an * {@link AppSearchResult} with a code of {@link AppSearchResult#RESULT_INVALID_SCHEMA} and an * error message describing the incompatibility. In this case the previously set schema will * remain active. * * <p>If you need to make non-backwards-compatible changes as described above, instead use the * {@link #setSchema(List, boolean)} method with the {@code forceOverride} parameter set to Loading @@ -102,13 +104,13 @@ public class AppSearchManager { * efficiently. * * @param schemas The schema configs for the types used by the calling app. * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the * previous schema. * @return the result of performing this operation. * * @hide */ public void setSchema(@NonNull AppSearchSchema... schemas) { setSchema(Arrays.asList(schemas), /*forceOverride=*/false); @NonNull public AppSearchResult<Void> setSchema(@NonNull AppSearchSchema... schemas) { return setSchema(Arrays.asList(schemas), /*forceOverride=*/false); } /** Loading @@ -116,20 +118,22 @@ public class AppSearchManager { * * <p>This method is similar to {@link #setSchema(AppSearchSchema...)}, except for the * {@code forceOverride} parameter. If a backwards-incompatible schema is specified but the * {@code forceOverride} parameter is set to {@code true}, instead of throwing an * {@link IllegalSchemaException}, all documents which are not compatible with the new schema * will be deleted and the incompatible schema will be applied. * {@code forceOverride} parameter is set to {@code true}, instead of returning an * {@link AppSearchResult} with the {@link AppSearchResult#RESULT_INVALID_SCHEMA} code, all * documents which are not compatible with the new schema will be deleted and the incompatible * schema will be applied. * * @param schemas The schema configs for the types used by the calling app. * @param forceOverride Whether to force the new schema to be applied even if there are * incompatible changes versus the previously set schema. Documents which are incompatible * with the new schema will be deleted. * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the * previous schema and the {@code forceOverride} parameter is set to {@code false}. * @return the result of performing this operation. * * @hide */ public void setSchema(@NonNull List<AppSearchSchema> schemas, boolean forceOverride) { @NonNull public AppSearchResult<Void> setSchema( @NonNull List<AppSearchSchema> schemas, boolean forceOverride) { // Prepare the merged schema for transmission. SchemaProto.Builder schemaProtoBuilder = SchemaProto.newBuilder(); for (AppSearchSchema schema : schemas) { Loading @@ -140,13 +144,13 @@ public class AppSearchManager { // TODO: This should use com.android.internal.infra.RemoteStream or another mechanism to // avoid binder limits. byte[] schemaBytes = schemaProtoBuilder.build().toByteArray(); AndroidFuture<Void> future = new AndroidFuture<>(); AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { mService.setSchema(schemaBytes, forceOverride, future); } catch (RemoteException e) { future.completeExceptionally(e); } getFutureOrThrow(future); return getFutureOrThrow(future); } /** Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java 0 → 100644 +216 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Information about the success or failure of an AppSearch call. * * @param <ValueType> The type of result object for successful calls. * @hide */ public class AppSearchResult<ValueType> implements Parcelable { /** Result codes from {@link AppSearchManager} methods. */ @IntDef(prefix = {"RESULT_"}, value = { RESULT_OK, RESULT_UNKNOWN_ERROR, RESULT_INTERNAL_ERROR, RESULT_INVALID_ARGUMENT, RESULT_IO_ERROR, RESULT_OUT_OF_SPACE, RESULT_NOT_FOUND, RESULT_INVALID_SCHEMA, }) @Retention(RetentionPolicy.SOURCE) public @interface ResultCode {} /** The call was successful. */ public static final int RESULT_OK = 0; /** An unknown error occurred while processing the call. */ public static final int RESULT_UNKNOWN_ERROR = 1; /** * An internal error occurred within AppSearch, which the caller cannot address. * * * This error may be considered similar to {@link IllegalStateException} */ public static final int RESULT_INTERNAL_ERROR = 2; /** * The caller supplied invalid arguments to the call. * * This error may be considered similar to {@link IllegalArgumentException}. */ public static final int RESULT_INVALID_ARGUMENT = 3; /** * An issue occurred reading or writing to storage. The call might succeed if repeated. * * This error may be considered similar to {@link java.io.IOException}. */ public static final int RESULT_IO_ERROR = 4; /** Storage is out of space, and no more space could be reclaimed. */ public static final int RESULT_OUT_OF_SPACE = 5; /** An entity the caller requested to interact with does not exist in the system. */ public static final int RESULT_NOT_FOUND = 6; /** The caller supplied a schema which is invalid or incompatible with the previous schema. */ public static final int RESULT_INVALID_SCHEMA = 7; private final @ResultCode int mResultCode; @Nullable private final ValueType mResultValue; @Nullable private final String mErrorMessage; private AppSearchResult( @ResultCode int resultCode, @Nullable ValueType resultValue, @Nullable String errorMessage) { mResultCode = resultCode; mResultValue = resultValue; mErrorMessage = errorMessage; } private AppSearchResult(@NonNull Parcel in) { mResultCode = in.readInt(); mResultValue = (ValueType) in.readValue(/*loader=*/ null); mErrorMessage = in.readString(); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mResultCode); dest.writeValue(mResultValue); dest.writeString(mErrorMessage); } /** Returns {@code true} if {@link #getResultCode} equals {@link AppSearchResult#RESULT_OK}. */ public boolean isSuccess() { return getResultCode() == RESULT_OK; } /** Returns one of the {@code RESULT} constants defined in {@link AppSearchResult}. */ public @ResultCode int getResultCode() { return mResultCode; } /** * Returns the returned value associated with this result. * * <p>If {@link #isSuccess} is {@code false}, the result value is always {@code null}. The value * may be {@code null} even if {@link #isSuccess} is {@code true}. See the documentation of the * particular {@link AppSearchManager} call producing this {@link AppSearchResult} for what is * returned by {@link #getResultValue}. */ @Nullable public ValueType getResultValue() { return mResultValue; } /** * Returns the error message associated with this result. * * <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}. The error * message may be {@code null} even if {@link #isSuccess} is {@code false}. See the * documentation of the particular {@link AppSearchManager} call producing this * {@link AppSearchResult} for what is returned by {@link #getErrorMessage}. */ @Nullable public String getErrorMessage() { return mErrorMessage; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof AppSearchResult)) { return false; } AppSearchResult<?> otherResult = (AppSearchResult) other; return mResultCode == otherResult.mResultCode && Objects.equals(mResultValue, otherResult.mResultValue) && Objects.equals(mErrorMessage, otherResult.mErrorMessage); } @Override public int hashCode() { return Objects.hash(mResultCode, mResultValue, mErrorMessage); } @Override @NonNull public String toString() { if (isSuccess()) { return "AppSearchResult [SUCCESS]: " + mResultValue; } return "AppSearchResult [FAILURE(" + mResultCode + ")]: " + mErrorMessage; } @Override public int describeContents() { return 0; } public static final Creator<AppSearchResult> CREATOR = new Creator<AppSearchResult>() { @NonNull @Override public AppSearchResult createFromParcel(@NonNull Parcel in) { return new AppSearchResult(in); } @NonNull @Override public AppSearchResult[] newArray(int size) { return new AppSearchResult[size]; } }; /** * Creates a new successful {@link AppSearchResult}. * @hide */ @NonNull public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult( @Nullable ValueType value) { return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null); } /** * Creates a new failed {@link AppSearchResult}. * @hide */ @NonNull public static <ValueType> AppSearchResult<ValueType> newFailedResult( @ResultCode int resultCode, @Nullable String errorMessage) { return new AppSearchResult<>(resultCode, /*resultValue=*/ null, errorMessage); } }
apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.appsearch; import com.android.internal.infra.AndroidFuture; parcelable AppSearchResult; parcelable AppSearchBatchResult; /** {@hide} */ Loading @@ -27,11 +28,11 @@ interface IAppSearchManager { * @param schemaBytes Serialized SchemaProto. * @param forceOverride Whether to apply the new schema even if it is incompatible. All * incompatible documents will be deleted. * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with * {@code null} upon successful completion of the setSchema call, or completed * exceptionally if setSchema fails. * @param callback {@link AndroidFuture}<{@link AppSearchResult}<{@link Void}>>. * The results of the call. */ void setSchema(in byte[] schemaBytes, boolean forceOverride, in AndroidFuture callback); void setSchema( in byte[] schemaBytes, boolean forceOverride, in AndroidFuture<AppSearchResult> callback); /** * Inserts documents into the index. Loading
apex/appsearch/service/java/com/android/server/appsearch/AppSearchException.java 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appsearch; import android.annotation.Nullable; import android.app.appsearch.AppSearchResult; /** * An exception thrown by {@link com.android.server.appsearch.AppSearchManagerService} or a * subcomponent. * * <p>These exceptions can be converted into a failed {@link android.app.appsearch.AppSearchResult} * for propagating to the client. */ public class AppSearchException extends Exception { private final @AppSearchResult.ResultCode int mResultCode; /** Initializes an {@link com.android.server.appsearch.AppSearchException} with no message. */ public AppSearchException(@AppSearchResult.ResultCode int resultCode) { this(resultCode, /*message=*/ null); } public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message) { this(resultCode, message, /*cause=*/ null); } public AppSearchException( @AppSearchResult.ResultCode int resultCode, @Nullable String message, @Nullable Throwable cause) { super(message, cause); mResultCode = resultCode; } /** * Converts this {@link java.lang.Exception} into a failed * {@link android.app.appsearch.AppSearchResult} */ public <T> AppSearchResult<T> toAppSearchResult() { return AppSearchResult.newFailedResult(mResultCode, getMessage()); } }