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

Commit dc9932a2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Batch calls to the Metadata Syncer" into main

parents 283e7869 3c39767a
Loading
Loading
Loading
Loading
+0 −53
Original line number Diff line number Diff line
@@ -16,15 +16,7 @@

package com.android.server.appfunctions;

import android.annotation.NonNull;
import android.os.UserHandle;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -41,50 +33,5 @@ public final class AppFunctionExecutors {
                    /* unit= */ TimeUnit.SECONDS,
                    /* workQueue= */ new LinkedBlockingQueue<>());

    /** A map of per-user executors for queued work. */
    @GuardedBy("sLock")
    private static final SparseArray<ExecutorService> mPerUserExecutorsLocked = new SparseArray<>();

    private static final Object sLock = new Object();

    /**
     * Returns a per-user executor for queued metadata sync request.
     *
     * <p>The work submitted to these executor (Sync request) needs to be synchronous per user hence
     * the use of a single thread.
     *
     * <p>Note: Use a different executor if not calling {@code submitSyncRequest} on a {@code
     * MetadataSyncAdapter}.
     */
    // TODO(b/357551503): Restrict the scope of this executor to the MetadataSyncAdapter itself.
    public static ExecutorService getPerUserSyncExecutor(@NonNull UserHandle user) {
        synchronized (sLock) {
            ExecutorService executor = mPerUserExecutorsLocked.get(user.getIdentifier(), null);
            if (executor == null) {
                executor = Executors.newSingleThreadExecutor();
                mPerUserExecutorsLocked.put(user.getIdentifier(), executor);
            }
            return executor;
        }
    }

    /**
     * Shuts down and removes the per-user executor for queued work.
     *
     * <p>This should be called when the user is removed.
     */
    public static void shutDownAndRemoveUserExecutor(@NonNull UserHandle user)
            throws InterruptedException {
        ExecutorService executor;
        synchronized (sLock) {
            executor = mPerUserExecutorsLocked.get(user.getIdentifier());
            mPerUserExecutorsLocked.remove(user.getIdentifier());
        }
        if (executor != null) {
            executor.shutdown();
            var unused = executor.awaitTermination(30, TimeUnit.SECONDS);
        }
    }

    private AppFunctionExecutors() {}
}
+1 −6
Original line number Diff line number Diff line
@@ -95,12 +95,7 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
    public void onUserStopping(@NonNull TargetUser user) {
        Objects.requireNonNull(user);

        try {
            AppFunctionExecutors.shutDownAndRemoveUserExecutor(user.getUserHandle());
        MetadataSyncPerUser.removeUserSyncAdapter(user.getUserHandle());
        } catch (InterruptedException e) {
            Slog.e(TAG, "Unable to remove data for: " + user.getUserHandle(), e);
        }
    }

    @Override
+34 −8
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
import com.android.server.appfunctions.FutureAppSearchSession.FutureSearchResults;
@@ -52,8 +53,12 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * This class implements helper methods for synchronously interacting with AppSearch while
@@ -63,9 +68,14 @@ import java.util.concurrent.Executor;
 */
public class MetadataSyncAdapter {
    private static final String TAG = MetadataSyncAdapter.class.getSimpleName();
    private final Executor mSyncExecutor;

    private final ExecutorService mExecutor;

    private final AppSearchManager mAppSearchManager;
    private final PackageManager mPackageManager;
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private Future<AndroidFuture<Boolean>> mCurrentSyncTask;

    // Hidden constants in {@link SetSchemaRequest} that restricts runtime metadata visibility
    // by permissions.
@@ -73,12 +83,10 @@ public class MetadataSyncAdapter {
    public static final int EXECUTE_APP_FUNCTIONS_TRUSTED = 10;

    public MetadataSyncAdapter(
            @NonNull Executor syncExecutor,
            @NonNull PackageManager packageManager,
            @NonNull AppSearchManager appSearchManager) {
        mSyncExecutor = Objects.requireNonNull(syncExecutor);
            @NonNull PackageManager packageManager, @NonNull AppSearchManager appSearchManager) {
        mPackageManager = Objects.requireNonNull(packageManager);
        mAppSearchManager = Objects.requireNonNull(appSearchManager);
        mExecutor = Executors.newSingleThreadExecutor();
    }

    /**
@@ -97,7 +105,7 @@ public class MetadataSyncAdapter {
                                AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_METADATA_DB)
                        .build();
        AndroidFuture<Boolean> settableSyncStatus = new AndroidFuture<>();
        mSyncExecutor.execute(
        Callable<AndroidFuture<Boolean>> callableTask =
                () -> {
                    try (FutureAppSearchSession staticMetadataSearchSession =
                                    new FutureAppSearchSessionImpl(
@@ -117,8 +125,26 @@ public class MetadataSyncAdapter {
                    } catch (Exception ex) {
                        settableSyncStatus.completeExceptionally(ex);
                    }
                });
                    return settableSyncStatus;
                };

        synchronized (mLock) {
            if (mCurrentSyncTask != null && !mCurrentSyncTask.isDone()) {
                boolean cancel = mCurrentSyncTask.cancel(false);
            }
            mCurrentSyncTask = mExecutor.submit(callableTask);
        }

        return settableSyncStatus;
    }

    /** This method shuts down the {@link MetadataSyncAdapter} scheduler. */
    public void shutDown() {
        try {
            var unused = mExecutor.awaitTermination(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Slog.e(TAG, "Error shutting down MetadataSyncAdapter scheduler", e);
        }
    }

    @WorkerThread
+7 −5
Original line number Diff line number Diff line
@@ -55,10 +55,7 @@ public final class MetadataSyncPerUser {
                PackageManager perUserPackageManager = userContext.getPackageManager();
                if (perUserAppSearchManager != null) {
                    metadataSyncAdapter =
                            new MetadataSyncAdapter(
                                    AppFunctionExecutors.getPerUserSyncExecutor(user),
                                    perUserPackageManager,
                                    perUserAppSearchManager);
                            new MetadataSyncAdapter(perUserPackageManager, perUserAppSearchManager);
                    sPerUserMetadataSyncAdapter.put(user.getIdentifier(), metadataSyncAdapter);
                    return metadataSyncAdapter;
                }
@@ -74,7 +71,12 @@ public final class MetadataSyncPerUser {
     */
    public static void removeUserSyncAdapter(UserHandle user) {
        synchronized (sLock) {
            MetadataSyncAdapter metadataSyncAdapter =
                    sPerUserMetadataSyncAdapter.get(user.getIdentifier(), null);
            if (metadataSyncAdapter != null) {
                metadataSyncAdapter.shutDown();
                sPerUserMetadataSyncAdapter.remove(user.getIdentifier());
            }
        }
    }
}
+3 −8
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.infra.AndroidFuture
import com.android.server.appfunctions.FutureAppSearchSession.FutureSearchResults
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors
import java.util.concurrent.atomic.AtomicBoolean
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,7 +45,6 @@ import org.junit.runners.JUnit4
class MetadataSyncAdapterTest {
    private val context = InstrumentationRegistry.getInstrumentation().targetContext
    private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
    private val testExecutor = MoreExecutors.directExecutor()
    private val packageManager = context.packageManager

    @Test
@@ -138,8 +136,7 @@ class MetadataSyncAdapterTest {
            PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build()
        runtimeSearchSession.put(putDocumentsRequest).get()
        staticSearchSession.put(putDocumentsRequest).get()
        val metadataSyncAdapter =
            MetadataSyncAdapter(testExecutor, packageManager, appSearchManager)
        val metadataSyncAdapter = MetadataSyncAdapter(packageManager, appSearchManager)

        val submitSyncRequest =
            metadataSyncAdapter.trySyncAppFunctionMetadataBlocking(
@@ -180,8 +177,7 @@ class MetadataSyncAdapterTest {
        val putDocumentsRequest: PutDocumentsRequest =
            PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build()
        staticSearchSession.put(putDocumentsRequest).get()
        val metadataSyncAdapter =
            MetadataSyncAdapter(testExecutor, packageManager, appSearchManager)
        val metadataSyncAdapter = MetadataSyncAdapter(packageManager, appSearchManager)

        val submitSyncRequest =
            metadataSyncAdapter.trySyncAppFunctionMetadataBlocking(
@@ -236,8 +232,7 @@ class MetadataSyncAdapterTest {
        val putDocumentsRequest: PutDocumentsRequest =
            PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build()
        runtimeSearchSession.put(putDocumentsRequest).get()
        val metadataSyncAdapter =
            MetadataSyncAdapter(testExecutor, packageManager, appSearchManager)
        val metadataSyncAdapter = MetadataSyncAdapter(packageManager, appSearchManager)

        val submitSyncRequest =
            metadataSyncAdapter.trySyncAppFunctionMetadataBlocking(