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

Commit 2229c176 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7236705 from d99447b6 to sc-release

Change-Id: Iad2a5df3ef1ab844c6950f47dc230f7266ec15bc
parents 8c1632b5 d99447b6
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -465,6 +465,7 @@ java_library {
    static_libs: [
        "android.net.ipsec.ike.stubs.module_lib",
        "framework-appsearch.stubs.module_lib",
        "framework-connectivity.stubs.module_lib",
        "framework-graphics.stubs.module_lib",
        "framework-media.stubs.module_lib",
        "framework-mediaprovider.stubs.module_lib",
@@ -487,6 +488,7 @@ java_library {
        "android.net.ipsec.ike.impl",
        "framework-minus-apex",
        "framework-appsearch.impl",
        "framework-connectivity.impl",
        "framework-graphics.impl",
        "framework-mediaprovider.impl",
        "framework-permission.impl",
@@ -643,14 +645,17 @@ java_defaults {
    defaults: ["framework-aidl-export-defaults"],
    srcs: [
        ":framework-non-updatable-sources",
        ":framework-connectivity-sources",
        "core/java/**/*.logtags",
    ],
    // See comment on framework-atb-backward-compatibility module below
    exclude_srcs: ["core/java/android/content/pm/AndroidTestBaseUpdater.java"],
    aidl: {
        generate_get_transaction_name: true,
        local_include_dirs: ["media/aidl"],
        local_include_dirs: [
            "media/aidl",
            // TODO: move to include_dirs when migrated to packages/modules
            "packages/Connectivity/framework/aidl-export",
        ],
        include_dirs: ["frameworks/av/aidl"],
    },
    dxflags: [
@@ -703,8 +708,6 @@ java_library {
    apex_available: ["//apex_available:platform"],
    visibility: [
        "//frameworks/base",
        // TODO: remove when framework-connectivity can build against API
        "//frameworks/base/packages/Connectivity/framework",
        // TODO(b/147128803) remove the below lines
        "//frameworks/base/apex/appsearch/framework",
        "//frameworks/base/apex/blobstore/framework",
@@ -743,6 +746,7 @@ java_library {
    static_libs: [
        "app-compat-annotations",
        "framework-minus-apex",
        "framework-connectivity.impl", // TODO(b/182859030): should be removed
        "framework-appsearch.impl", // TODO(b/146218515): should be removed
        "framework-updatable-stubs-module_libs_api",
    ],
@@ -1461,7 +1465,7 @@ java_library {
    ],
    libs: [
        "framework-annotations-lib",
        "framework-connectivity",
        "framework-connectivity.stubs.module_lib",
        "unsupportedappusage",
    ],
    visibility: [
+2 −20
Original line number Diff line number Diff line
@@ -26,10 +26,8 @@ package android.app.appsearch {
  }

  public static final class AppSearchManager.SearchContext.Builder {
    ctor @Deprecated public AppSearchManager.SearchContext.Builder();
    ctor public AppSearchManager.SearchContext.Builder(@NonNull String);
    method @NonNull public android.app.appsearch.AppSearchManager.SearchContext build();
    method @Deprecated @NonNull public android.app.appsearch.AppSearchManager.SearchContext.Builder setDatabaseName(@NonNull String);
  }

  public final class AppSearchResult<ValueType> {
@@ -53,7 +51,6 @@ package android.app.appsearch {
  public final class AppSearchSchema {
    method @NonNull public java.util.List<android.app.appsearch.AppSearchSchema.PropertyConfig> getProperties();
    method @NonNull public String getSchemaType();
    method @Deprecated @IntRange(from=0) public int getVersion();
  }

  public static final class AppSearchSchema.BooleanPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
@@ -69,7 +66,6 @@ package android.app.appsearch {
    ctor public AppSearchSchema.Builder(@NonNull String);
    method @NonNull public android.app.appsearch.AppSearchSchema.Builder addProperty(@NonNull android.app.appsearch.AppSearchSchema.PropertyConfig);
    method @NonNull public android.app.appsearch.AppSearchSchema build();
    method @Deprecated @NonNull public android.app.appsearch.AppSearchSchema.Builder setVersion(@IntRange(from=0) int);
  }

  public static final class AppSearchSchema.BytesPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
@@ -149,7 +145,7 @@ package android.app.appsearch {
    method public void remove(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
    method public void reportUsage(@NonNull android.app.appsearch.ReportUsageRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
    method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec);
    method public void setSchema(@NonNull android.app.appsearch.SetSchemaRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.SetSchemaResponse>>);
    method public void setSchema(@NonNull android.app.appsearch.SetSchemaRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.SetSchemaResponse>>);
  }

  public interface BatchResultCallback<KeyType, ValueType> {
@@ -180,15 +176,12 @@ package android.app.appsearch {
    method public int getScore();
    method public long getTtlMillis();
    method @NonNull public String getUri();
    field @Deprecated public static final String DEFAULT_NAMESPACE = "";
  }

  public static class GenericDocument.Builder<BuilderType extends android.app.appsearch.GenericDocument.Builder> {
    ctor @Deprecated public GenericDocument.Builder(@NonNull String, @NonNull String);
    ctor public GenericDocument.Builder(@NonNull String, @NonNull String, @NonNull String);
    method @NonNull public android.app.appsearch.GenericDocument build();
    method @NonNull public BuilderType setCreationTimestampMillis(long);
    method @Deprecated @NonNull public BuilderType setNamespace(@NonNull String);
    method @NonNull public BuilderType setPropertyBoolean(@NonNull String, @NonNull boolean...);
    method @NonNull public BuilderType setPropertyBytes(@NonNull String, @NonNull byte[]...);
    method @NonNull public BuilderType setPropertyDocument(@NonNull String, @NonNull android.app.appsearch.GenericDocument...);
@@ -207,16 +200,14 @@ package android.app.appsearch {
  }

  public static final class GetByUriRequest.Builder {
    ctor @Deprecated public GetByUriRequest.Builder();
    ctor public GetByUriRequest.Builder(@NonNull String);
    method @NonNull public android.app.appsearch.GetByUriRequest.Builder addProjection(@NonNull String, @NonNull java.util.Collection<java.lang.String>);
    method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUris(@NonNull java.lang.String...);
    method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUris(@NonNull java.util.Collection<java.lang.String>);
    method @NonNull public android.app.appsearch.GetByUriRequest build();
    method @Deprecated @NonNull public android.app.appsearch.GetByUriRequest.Builder setNamespace(@NonNull String);
  }

  public class GetSchemaResponse extends java.util.HashSet<android.app.appsearch.AppSearchSchema> {
  public class GetSchemaResponse {
    method @NonNull public java.util.Set<android.app.appsearch.AppSearchSchema> getSchemas();
    method @IntRange(from=0) public int getVersion();
  }
@@ -264,12 +255,10 @@ package android.app.appsearch {
  }

  public static final class RemoveByUriRequest.Builder {
    ctor @Deprecated public RemoveByUriRequest.Builder();
    ctor public RemoveByUriRequest.Builder(@NonNull String);
    method @NonNull public android.app.appsearch.RemoveByUriRequest.Builder addUris(@NonNull java.lang.String...);
    method @NonNull public android.app.appsearch.RemoveByUriRequest.Builder addUris(@NonNull java.util.Collection<java.lang.String>);
    method @NonNull public android.app.appsearch.RemoveByUriRequest build();
    method @Deprecated @NonNull public android.app.appsearch.RemoveByUriRequest.Builder setNamespace(@NonNull String);
  }

  public final class ReportSystemUsageRequest {
@@ -294,17 +283,14 @@ package android.app.appsearch {
  }

  public static final class ReportUsageRequest.Builder {
    ctor @Deprecated public ReportUsageRequest.Builder();
    ctor public ReportUsageRequest.Builder(@NonNull String);
    method @NonNull public android.app.appsearch.ReportUsageRequest build();
    method @Deprecated @NonNull public android.app.appsearch.ReportUsageRequest.Builder setNamespace(@NonNull String);
    method @NonNull public android.app.appsearch.ReportUsageRequest.Builder setUri(@NonNull String);
    method @NonNull public android.app.appsearch.ReportUsageRequest.Builder setUsageTimeMillis(long);
  }

  public final class SearchResult {
    method @NonNull public String getDatabaseName();
    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();
@@ -321,12 +307,10 @@ package android.app.appsearch {

  public static final class SearchResult.MatchInfo {
    method @NonNull public CharSequence getExactMatch();
    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 @Deprecated @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetPosition();
    method @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetRange();
  }

@@ -404,7 +388,6 @@ package android.app.appsearch {
    method @NonNull public java.util.Map<java.lang.String,android.app.appsearch.Migrator> getMigrators();
    method @NonNull public java.util.Set<android.app.appsearch.AppSearchSchema> getSchemas();
    method @NonNull public java.util.Set<java.lang.String> getSchemasNotDisplayedBySystem();
    method @Deprecated @NonNull public java.util.Set<java.lang.String> getSchemasNotVisibleToSystemUi();
    method @NonNull public java.util.Map<java.lang.String,java.util.Set<android.app.appsearch.PackageIdentifier>> getSchemasVisibleToPackages();
    method @IntRange(from=1) public int getVersion();
    method public boolean isForceOverride();
@@ -420,7 +403,6 @@ package android.app.appsearch {
    method @NonNull public android.app.appsearch.SetSchemaRequest.Builder setMigrators(@NonNull java.util.Map<java.lang.String,android.app.appsearch.Migrator>);
    method @NonNull public android.app.appsearch.SetSchemaRequest.Builder setSchemaTypeDisplayedBySystem(@NonNull String, boolean);
    method @NonNull public android.app.appsearch.SetSchemaRequest.Builder setSchemaTypeVisibilityForPackage(@NonNull String, boolean, @NonNull android.app.appsearch.PackageIdentifier);
    method @Deprecated @NonNull public android.app.appsearch.SetSchemaRequest.Builder setSchemaTypeVisibilityForSystemUi(@NonNull String, boolean);
    method @NonNull public android.app.appsearch.SetSchemaRequest.Builder setVersion(@IntRange(from=1) int);
  }

+1 −44
Original line number Diff line number Diff line
@@ -147,21 +147,9 @@ public class AppSearchManager {

        /** Builder for {@link SearchContext} objects. */
        public static final class Builder {
            private String mDatabaseName;
            private final String mDatabaseName;
            private boolean mBuilt = false;

            /**
             * TODO(b/181887768): This method exists only for dogfooder transition and must be
             * removed.
             *
             * @deprecated Please supply the databaseName in {@link #Builder(String)} instead. This
             *     method exists only for dogfooder transition and must be removed.
             */
            @Deprecated
            public Builder() {
                mDatabaseName = "";
            }

            /**
             * Creates a new {@link SearchContext.Builder}.
             *
@@ -182,37 +170,6 @@ public class AppSearchManager {
                mDatabaseName = databaseName;
            }

            /**
             * Sets the name of the database associated with {@link AppSearchSession}.
             *
             * <p>{@link AppSearchSession} will create or open a database under the given name.
             *
             * <p>Databases with different names are fully separate with distinct types, namespaces,
             * and data.
             *
             * <p>Database name cannot contain {@code '/'}.
             *
             * <p>If not specified, defaults to the empty string.
             *
             * <p>TODO(b/181887768): This method exists only for dogfooder transition and must be
             * removed.
             *
             * @param databaseName The name of the database.
             * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
             * @deprecated Please supply the databaseName in {@link #Builder(String)} instead. This
             *     method exists only for dogfooder transition and must be removed.
             */
            @Deprecated
            @NonNull
            public Builder setDatabaseName(@NonNull String databaseName) {
                Preconditions.checkState(!mBuilt, "Builder has already been used");
                Objects.requireNonNull(databaseName);
                Preconditions.checkArgument(
                        !databaseName.contains("/"), "Database name cannot contain '/'");
                mDatabaseName = databaseName;
                return this;
            }

            /** Builds a {@link SearchContext} instance. */
            @NonNull
            public SearchContext build() {
+256 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.appsearch.exceptions.AppSearchException;
import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;

import com.android.internal.infra.AndroidFuture;

import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

/**
 * The helper class for {@link AppSearchSchema} migration.
 *
 * <p>It will query and migrate {@link GenericDocument} in given type to a new version.
 * @hide
 */
public class AppSearchMigrationHelper implements Closeable {
    private final IAppSearchManager mService;
    private final String mPackageName;
    private final String mDatabaseName;
    private final int mUserId;
    private final File mMigratedFile;
    private final Map<String, Integer> mCurrentVersionMap;
    private final Map<String, Integer> mFinalVersionMap;
    private boolean mAreDocumentsMigrated = false;

    AppSearchMigrationHelper(@NonNull IAppSearchManager service,
            @UserIdInt int userId,
            @NonNull Map<String, Integer> currentVersionMap,
            @NonNull Map<String, Integer> finalVersionMap,
            @NonNull String packageName,
            @NonNull String databaseName) throws IOException {
        mService = Objects.requireNonNull(service);
        mCurrentVersionMap = Objects.requireNonNull(currentVersionMap);
        mFinalVersionMap = Objects.requireNonNull(finalVersionMap);
        mPackageName = Objects.requireNonNull(packageName);
        mDatabaseName = Objects.requireNonNull(databaseName);
        mUserId = userId;
        mMigratedFile = File.createTempFile(/*prefix=*/"appsearch", /*suffix=*/null);
    }

    /**
     * Queries all documents that need to be migrated to a different version and transform
     * documents to that version by passing them to the provided {@link Migrator}.
     *
     * <p>The method will be executed on the executor provided to
     * {@link AppSearchSession#setSchema}.
     *
     * @param schemaType The schema type that needs to be updated and whose {@link GenericDocument}
     *                   need to be migrated.
     * @param migrator The {@link Migrator} that will upgrade or downgrade a {@link
     *     GenericDocument} to new version.
     */
    @WorkerThread
    public void queryAndTransform(@NonNull String schemaType, @NonNull Migrator migrator)
            throws IOException, AppSearchException, InterruptedException, ExecutionException {
        File queryFile = File.createTempFile(/*prefix=*/"appsearch", /*suffix=*/null);
        try (ParcelFileDescriptor fileDescriptor =
                     ParcelFileDescriptor.open(queryFile, MODE_WRITE_ONLY)) {
            AndroidFuture<AppSearchResult<Void>> androidFuture = new AndroidFuture<>();
            mService.writeQueryResultsToFile(mPackageName, mDatabaseName,
                    fileDescriptor,
                    /*queryExpression=*/ "",
                    new SearchSpec.Builder()
                            .addFilterSchemas(schemaType)
                            .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
                            .build().getBundle(),
                    mUserId,
                    new IAppSearchResultCallback.Stub() {
                        @Override
                        public void onResult(AppSearchResult result) throws RemoteException {
                            androidFuture.complete(result);
                        }
                    });
            AppSearchResult<Void> result = androidFuture.get();
            if (!result.isSuccess()) {
                throw new AppSearchException(result.getResultCode(), result.getErrorMessage());
            }
            readAndTransform(queryFile, migrator);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            queryFile.delete();
        }
    }

    /**
     * Puts all {@link GenericDocument} migrated from the previous call to
     * {@link #queryAndTransform} into AppSearch.
     *
     * <p> This method should be only called once.
     *
     * @param responseBuilder a SetSchemaResponse builder whose result will be returned by this
     *                        function with any
     *                        {@link android.app.appsearch.SetSchemaResponse.MigrationFailure}
     *                        added in.
     * @return the {@link SetSchemaResponse} for {@link AppSearchSession#setSchema} call.
     */
    @NonNull
    AppSearchResult<SetSchemaResponse> putMigratedDocuments(
            @NonNull SetSchemaResponse.Builder responseBuilder) {
        if (!mAreDocumentsMigrated) {
            return AppSearchResult.newSuccessfulResult(responseBuilder.build());
        }
        try (ParcelFileDescriptor fileDescriptor =
                     ParcelFileDescriptor.open(mMigratedFile, MODE_READ_ONLY)) {
            AndroidFuture<AppSearchResult<List<Bundle>>> androidFuture = new AndroidFuture<>();
            mService.putDocumentsFromFile(mPackageName, mDatabaseName, fileDescriptor, mUserId,
                    new IAppSearchResultCallback.Stub() {
                        @Override
                        public void onResult(AppSearchResult result) throws RemoteException {
                            androidFuture.complete(result);
                        }
                    });
            AppSearchResult<List<Bundle>> result = androidFuture.get();
            if (!result.isSuccess()) {
                return AppSearchResult.newFailedResult(result);
            }
            List<Bundle> migratedFailureBundles = result.getResultValue();
            for (int i = 0; i < migratedFailureBundles.size(); i++) {
                responseBuilder.addMigrationFailure(
                        new SetSchemaResponse.MigrationFailure(migratedFailureBundles.get(i)));
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (Throwable t) {
            return AppSearchResult.throwableToFailedResult(t);
        } finally {
            mMigratedFile.delete();
        }
        return AppSearchResult.newSuccessfulResult(responseBuilder.build());
    }

    /**
     * Reads all saved {@link GenericDocument}s from the given {@link File}.
     *
     * <p>Transforms those {@link GenericDocument}s to the final version.
     *
     * <p>Save migrated {@link GenericDocument}s to the {@link #mMigratedFile}.
     */
    private void readAndTransform(@NonNull File file, @NonNull Migrator migrator)
            throws IOException {
        try (DataInputStream inputStream = new DataInputStream(new FileInputStream(file));
             DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(
                     mMigratedFile, /*append=*/ true))) {
            GenericDocument document;
            while (true) {
                try {
                    document = readDocumentFromInputStream(inputStream);
                } catch (EOFException e) {
                    break;
                    // Nothing wrong. We just finished reading.
                }

                int currentVersion = mCurrentVersionMap.get(document.getSchemaType());
                int finalVersion = mFinalVersionMap.get(document.getSchemaType());

                GenericDocument newDocument;
                if (currentVersion < finalVersion) {
                    newDocument = migrator.onUpgrade(currentVersion, finalVersion, document);
                } else {
                    // currentVersion == finalVersion case won't trigger migration and get here.
                    newDocument = migrator.onDowngrade(currentVersion, finalVersion, document);
                }
                writeBundleToOutputStream(outputStream, newDocument.getBundle());
            }
            mAreDocumentsMigrated = true;
        }
    }

    /**
     * Reads the {@link Bundle} of a {@link GenericDocument} from given {@link DataInputStream}.
     *
     * @param inputStream The inputStream to read from
     *
     * @throws IOException        on read failure.
     * @throws EOFException       if {@link java.io.InputStream} reaches the end.
     */
    @NonNull
    public static GenericDocument readDocumentFromInputStream(
            @NonNull DataInputStream inputStream) throws IOException {
        int length = inputStream.readInt();
        if (length == 0) {
            throw new EOFException();
        }
        byte[] serializedMessage = new byte[length];
        inputStream.read(serializedMessage);

        Parcel parcel = Parcel.obtain();
        try {
            parcel.unmarshall(serializedMessage, 0, serializedMessage.length);
            parcel.setDataPosition(0);
            Bundle bundle = parcel.readBundle();
            return new GenericDocument(bundle);
        } finally {
            parcel.recycle();
        }
    }

    /**
     * Serializes a {@link Bundle} and writes into the given {@link DataOutputStream}.
     */
    public static void writeBundleToOutputStream(
            @NonNull DataOutputStream outputStream, @NonNull Bundle bundle)
            throws IOException {
        Parcel parcel = Parcel.obtain();
        try {
            parcel.writeBundle(bundle);
            byte[] serializedMessage = parcel.marshall();
            outputStream.writeInt(serializedMessage.length);
            outputStream.write(serializedMessage);
        } finally {
            parcel.recycle();
        }
    }

    @Override
    public void close() throws IOException {
        mMigratedFile.delete();
    }
}
+219 −14

File changed.

Preview size limit exceeded, changes collapsed.

Loading