Loading services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java +0 −53 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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() {} } services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +1 −6 Original line number Diff line number Diff line Loading @@ -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 Loading services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java +34 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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. Loading @@ -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(); } /** Loading @@ -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( Loading @@ -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 Loading services/appfunctions/java/com/android/server/appfunctions/MetadataSyncPerUser.java +7 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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()); } } } } services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt +3 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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( Loading Loading
services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java +0 −53 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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() {} }
services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +1 −6 Original line number Diff line number Diff line Loading @@ -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 Loading
services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java +34 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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. Loading @@ -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(); } /** Loading @@ -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( Loading @@ -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 Loading
services/appfunctions/java/com/android/server/appfunctions/MetadataSyncPerUser.java +7 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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()); } } } }
services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt +3 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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( Loading