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

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

Switch setSchema API to be synchronous, based on discussion with API council.

Bug: 145635424
Test: Presubmit
Change-Id: I1419ca809eacea38bb8efd272771c0853d91efec
parent e2e63a57
Loading
Loading
Loading
Loading
+51 −21
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@ import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.StatusProto;
import com.google.android.icing.protobuf.InvalidProtocolBufferException;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -73,7 +75,7 @@ public class AppSearchManager {
     * </ul>
     *
     * <p>The following types of schema changes are not backwards-compatible. Supplying a schema
     * with such changes will result in the provided callback being called with a {@link Throwable}
     * with such changes will result in this call throwing an {@link IllegalSchemaException}
     * describing the incompatibility, and the previously set schema will remain active:
     * <ul>
     *     <li>Removal of an existing type
@@ -91,33 +93,44 @@ public class AppSearchManager {
     *             REQUIRED} property.
     * </ul>
     *
     * <p>If you need to make non-backwards-compatible changes as described above, you may set the
     * {@code force} parameter to {@code true}. In this case, all documents which are not compatible
     * with the new schema will be deleted.
     *
     * <p>This operation is performed asynchronously. On success, the provided callback will be
     * called with {@code null}. On failure, the provided callback will be called with a
     * {@link Throwable} describing the failure.
     * <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
     * {@code true}.
     *
     * <p>It is a no-op to set the same schema as has been previously set; this is handled
     * efficiently.
     *
     * @param schemas The schema configs for the types used by the calling app.
     * @param force 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.
     * @param executor Executor on which to invoke the callback.
     * @param callback Callback to receive errors resulting from setting the schema. If the
     *                 operation succeeds, the callback will be invoked with {@code null}.
     * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the
     *     previous schema.
     *
     * @hide
     */
    // TODO(b/143789408): linkify #put after that API is created
    public void setSchema(
            List<AppSearchSchema> schemas,
            boolean force,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<? super Throwable> callback) {
    public void setSchema(@NonNull AppSearchSchema... schemas) {
        setSchema(Arrays.asList(schemas), /*forceOverride=*/false);
    }

    /**
     * Sets the schema being used by documents provided to the #put method.
     *
     * <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.
     *
     * @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}.
     *
     * @hide
     */
    // TODO(b/143789408): linkify #put after that API is created
    public void setSchema(@NonNull List<AppSearchSchema> schemas, boolean forceOverride) {
        // Prepare the merged schema for transmission.
        SchemaProto.Builder schemaProtoBuilder = SchemaProto.newBuilder();
        for (AppSearchSchema schema : schemas) {
@@ -130,11 +143,11 @@ public class AppSearchManager {
        byte[] schemaBytes = schemaProtoBuilder.build().toByteArray();
        AndroidFuture<Void> future = new AndroidFuture<>();
        try {
            mService.setSchema(schemaBytes, force, future);
            mService.setSchema(schemaBytes, forceOverride, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
        future.whenCompleteAsync((noop, err) -> callback.accept(err), executor);
        getFutureOrThrow(future);
    }

    /**
@@ -256,4 +269,21 @@ public class AppSearchManager {
            future.completeExceptionally(e);
        }
    }

    private static <T> T getFutureOrThrow(@NonNull AndroidFuture<T> future) {
        try {
            return future.get();
        } catch (Throwable e) {
            if (e instanceof ExecutionException) {
                e = e.getCause();
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            if (e instanceof Error) {
                throw (Error) e;
            }
            throw new RuntimeException(e);
        }
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -23,13 +23,13 @@ interface IAppSearchManager {
     * Sets the schema.
     *
     * @param schemaProto Serialized SchemaProto.
     * @param force Whether to apply the new schema even if it is incompatible. All incompatible
           documents will be deleted.
     * @param forceOverride Whether to apply the new schema even if it is incompatible. All
     *     incompatible documents will be deleted.
     * @param callback {@link AndroidFuture}&lt;{@link Void}&gt;. Will be completed with
     *     {@code null} upon successful completion of the setSchema call, or completed exceptionally
     *     if setSchema fails.
     *     {@code null} upon successful completion of the setSchema call, or completed
     *     exceptionally if setSchema fails.
     */
    void setSchema(in byte[] schemaProto, boolean force, in AndroidFuture callback);
    void setSchema(in byte[] schemaProto, boolean forceOverride, in AndroidFuture callback);
    void put(in byte[] documentBytes, in AndroidFuture callback);
    /**
     * Searches a document based on a given query string.
+2 −2
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public class AppSearchManagerService extends SystemService {

    private class Stub extends IAppSearchManager.Stub {
        @Override
        public void setSchema(byte[] schemaBytes, boolean force, AndroidFuture callback) {
        public void setSchema(byte[] schemaBytes, boolean forceOverride, AndroidFuture callback) {
            Preconditions.checkNotNull(schemaBytes);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
@@ -61,7 +61,7 @@ public class AppSearchManagerService extends SystemService {
            try {
                SchemaProto schema = SchemaProto.parseFrom(schemaBytes);
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                impl.setSchema(callingUid, schema, force);
                impl.setSchema(callingUid, schema, forceOverride);
                callback.complete(null);
            } catch (Throwable t) {
                callback.completeExceptionally(t);
+3 −3
Original line number Diff line number Diff line
@@ -45,10 +45,10 @@ public final class AppSearchImpl {
     *
     * @param callingUid The uid of the app calling AppSearch.
     * @param origSchema The schema to set for this app.
     * @param force Whether to force-apply the schema even if it is incompatible. Documents which do
     *     not comply with the new schema will be deleted.
     * @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents
     *     which do not comply with the new schema will be deleted.
     */
    public void setSchema(int callingUid, @NonNull SchemaProto origSchema, boolean force) {
    public void setSchema(int callingUid, @NonNull SchemaProto origSchema, boolean forceOverride) {
        // Rewrite schema type names to include the calling app's package and uid.
        String typePrefix = getTypePrefix(callingUid);
        SchemaProto.Builder schemaBuilder = origSchema.toBuilder();
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ public class AppSearchImplTest {
                () -> impl.setSchema(
                        /*callingUid=*/Integer.MAX_VALUE,
                        SchemaProto.getDefaultInstance(),
                        /*force=*/false));
                        /*forceOverride=*/false));
        assertThat(e).hasMessageThat().contains("Failed to look up package name");
    }
}