Add factories and framework specific implementations for AppSearchConfig and AppSearchExecutor.

Test: minor refactor, existing test passes.
Bug: 232959004

Change-Id: I4b93c8db87df708abbc56b0d06367a422553a16b
diff --git a/service/java/com/android/server/appsearch/AppSearchEnvironment.java b/service/java/com/android/server/appsearch/AppSearchEnvironment.java
index 0ddde8f..af0dcba 100644
--- a/service/java/com/android/server/appsearch/AppSearchEnvironment.java
+++ b/service/java/com/android/server/appsearch/AppSearchEnvironment.java
@@ -3,7 +3,11 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.os.UserHandle;
+
 import java.io.File;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 
 /** An interface which exposes environment specific methods for AppSearch. */
 public interface AppSearchEnvironment {
@@ -13,5 +17,17 @@
 
   /** Returns the correct context for the user based on the environment. */
   public Context createContextAsUser(@NonNull Context context, @NonNull UserHandle userHandle);
+
+  /** Returns an ExecutorService based on given parameters. */
+  public ExecutorService createExecutorService(
+      int corePoolSize,
+      int maxConcurrency,
+      long keepAliveTime,
+      TimeUnit unit,
+      BlockingQueue<Runnable> workQueue,
+      int priority);
+
+  /** Returns an ExecutorService with a single thread. */
+  public ExecutorService createSingleThreadExecutor();
 }
 
diff --git a/service/java/com/android/server/appsearch/AppSearchEnvironmentFactory.java b/service/java/com/android/server/appsearch/AppSearchEnvironmentFactory.java
index 55280ea..c350020 100644
--- a/service/java/com/android/server/appsearch/AppSearchEnvironmentFactory.java
+++ b/service/java/com/android/server/appsearch/AppSearchEnvironmentFactory.java
@@ -1,23 +1,40 @@
 package com.android.server.appsearch;
 
-/** This is a factory class that returns implementation for AppSearchEnvironment. */
-public class AppSearchEnvironmentFactory {
+import java.util.concurrent.Executor;
 
-  private static volatile AppSearchEnvironment mInstance;
+/** This is a factory provider class that holds all factories needed by AppSearch. */
+public final class AppSearchEnvironmentFactory {
+    private static volatile AppSearchEnvironment mEnvironmentInstance;
+    private static volatile AppSearchConfig mConfigInstance;
 
-  public static AppSearchEnvironment getInstance() {
-    AppSearchEnvironment localRef = mInstance;
-    if (localRef == null) {
-      synchronized (AppSearchEnvironmentFactory.class) {
-        localRef = mInstance;
-        if (localRef == null) {
-            mInstance = localRef = new FrameworkAppSearchEnvironment();
+    public static AppSearchEnvironment getEnvironmentInstance() {
+      AppSearchEnvironment localRef = mEnvironmentInstance;
+      if (localRef == null) {
+        synchronized (AppSearchEnvironmentFactory.class) {
+          localRef = mEnvironmentInstance;
+          if (localRef == null) {
+              mEnvironmentInstance = localRef =
+                      new FrameworkAppSearchEnvironment();
+          }
         }
       }
+      return localRef;
     }
-    return localRef;
-  }
 
-  private AppSearchEnvironmentFactory() {}
+    public static AppSearchConfig getConfigInstance(Executor executor) {
+      AppSearchConfig localRef = mConfigInstance;
+      if (localRef == null) {
+        synchronized (AppSearchEnvironmentFactory.class) {
+          localRef = mConfigInstance;
+          if (localRef == null) {
+              mConfigInstance = localRef = FrameworkAppSearchConfig
+                              .getInstance(executor);
+          }
+        }
+      }
+      return localRef;
+    }
+
+    private AppSearchEnvironmentFactory() {}
 }
 
diff --git a/service/java/com/android/server/appsearch/AppSearchManagerService.java b/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 73bcd3a..aed752d 100644
--- a/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -133,7 +133,8 @@
     public AppSearchManagerService(Context context) {
         super(context);
         mContext = context;
-        mAppSearchEnvironment = AppSearchEnvironmentFactory.getInstance();
+        mAppSearchEnvironment = AppSearchEnvironmentFactory
+            .getEnvironmentInstance();
     }
 
     @Override
@@ -259,7 +260,7 @@
                             mAppSearchUserInstanceManager.getOrCreateUserInstance(
                                     userContext,
                                     userHandle,
-                                    FrameworkAppSearchConfig.getInstance(SHARED_EXECUTOR));
+                                    AppSearchEnvironmentFactory.getConfigInstance(SHARED_EXECUTOR));
                     instance.getAppSearchImpl().clearPackageData(packageName);
                     dispatchChangeNotifications(instance);
                     instance.getLogger().removeCachedUidForPackage(packageName);
@@ -285,7 +286,7 @@
                             mAppSearchUserInstanceManager.getOrCreateUserInstance(
                                     userContext,
                                     userHandle,
-                                    FrameworkAppSearchConfig.getInstance(SHARED_EXECUTOR));
+                                    AppSearchEnvironmentFactory.getConfigInstance(SHARED_EXECUTOR));
                     List<PackageInfo> installedPackageInfos = userContext
                             .getPackageManager()
                             .getInstalledPackages(/* flags= */ 0);
@@ -1572,7 +1573,7 @@
                     instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
                             targetUserContext,
                             targetUser,
-                            FrameworkAppSearchConfig.getInstance(SHARED_EXECUTOR));
+                            AppSearchEnvironmentFactory.getConfigInstance(SHARED_EXECUTOR));
                     ++operationSuccessCount;
                     invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
                 } catch (Throwable t) {
diff --git a/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java b/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java
index add02ca..341f87e 100644
--- a/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java
+++ b/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java
@@ -180,7 +180,8 @@
         synchronized (mStorageInfoLocked) {
             UserStorageInfo userStorageInfo = mStorageInfoLocked.get(userHandle);
             if (userStorageInfo == null) {
-                File appSearchDir = AppSearchEnvironmentFactory.getInstance()
+                File appSearchDir = AppSearchEnvironmentFactory
+                    .getEnvironmentInstance()
                     .getAppSearchDir(userContext, userHandle);
                 userStorageInfo = new UserStorageInfo(appSearchDir);
                 mStorageInfoLocked.put(userHandle, userStorageInfo);
@@ -213,7 +214,8 @@
         // Initialize the classes that make up AppSearchUserInstance
         PlatformLogger logger = new PlatformLogger(userContext, config);
 
-        File appSearchDir = AppSearchEnvironmentFactory.getInstance()
+        File appSearchDir = AppSearchEnvironmentFactory
+            .getEnvironmentInstance()
             .getAppSearchDir(userContext, userHandle);
         File icingDir = new File(appSearchDir, "icing");
         Log.i(TAG, "Creating new AppSearch instance at: " + icingDir);
diff --git a/service/java/com/android/server/appsearch/FrameworkAppSearchEnvironment.java b/service/java/com/android/server/appsearch/FrameworkAppSearchEnvironment.java
index 4b7c709..7646949 100644
--- a/service/java/com/android/server/appsearch/FrameworkAppSearchEnvironment.java
+++ b/service/java/com/android/server/appsearch/FrameworkAppSearchEnvironment.java
@@ -6,6 +6,11 @@
 import android.os.UserHandle;
 
 import java.io.File;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 import java.util.Objects;
 
 /** Contains utility methods for Framework implementation of AppSearch. */
@@ -33,5 +38,28 @@
     Objects.requireNonNull(userHandle);
     return context.createContextAsUser(userHandle, /*flags=*/ 0);
   }
+
+  /** Creates and returns a ThreadPoolExecutor for given parameters. */
+  @Override
+  public ExecutorService createExecutorService(
+      int corePoolSize,
+      int maxConcurrency,
+      long keepAliveTime,
+      TimeUnit unit,
+      BlockingQueue<Runnable> workQueue,
+      int priority) {
+    return new ThreadPoolExecutor(
+        corePoolSize,
+        maxConcurrency,
+        keepAliveTime,
+        unit,
+        workQueue);
+  }
+
+  /** Createsand returns an ExecutorService with a single thread. */
+  @Override
+  public ExecutorService createSingleThreadExecutor() {
+    return Executors.newSingleThreadExecutor();
+  }
 }
 
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
index b00bbaf..344c23b 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerManagerService.java
@@ -36,8 +36,8 @@
 
 import com.android.server.LocalManagerRegistry;
 import com.android.server.SystemService;
+import com.android.server.appsearch.AppSearchEnvironment;
 import com.android.server.appsearch.AppSearchEnvironmentFactory;
-import com.android.server.appsearch.AppSearchModule;
 
 import java.io.File;
 import java.util.List;
@@ -89,9 +89,11 @@
             int userId = userHandle.getIdentifier();
             ContactsIndexerUserInstance instance = mContactsIndexersLocked.get(userId);
             if (instance == null) {
-                Context userContext = AppSearchEnvironmentFactory.getInstance()
+                AppSearchEnvironment appSearchEnvironment = AppSearchEnvironmentFactory
+                    .getEnvironmentInstance();
+                Context userContext = appSearchEnvironment
                     .createContextAsUser(mContext, userHandle);
-                File appSearchDir = AppSearchEnvironmentFactory.getInstance()
+                File appSearchDir = appSearchEnvironment
                     .getAppSearchDir(userContext, userHandle);
                 File contactsDir = new File(appSearchDir, "contacts");
                 try {
diff --git a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
index 8928343..50a6144 100644
--- a/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
+++ b/service/java/com/android/server/appsearch/contactsindexer/ContactsIndexerUserInstance.java
@@ -30,6 +30,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.appsearch.AppSearchEnvironmentFactory;
 import com.android.server.appsearch.stats.AppSearchStatsLog;
 
 import java.io.File;
@@ -41,7 +42,6 @@
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -104,7 +104,8 @@
         Objects.requireNonNull(contactsDir);
         Objects.requireNonNull(contactsIndexerConfig);
 
-        ExecutorService singleThreadedExecutor = Executors.newSingleThreadExecutor();
+        ExecutorService singleThreadedExecutor = AppSearchEnvironmentFactory
+            .getEnvironmentInstance().createSingleThreadExecutor();
         return createInstance(userContext, contactsDir, contactsIndexerConfig,
                 singleThreadedExecutor);
     }
diff --git a/service/java/com/android/server/appsearch/util/ExecutorManager.java b/service/java/com/android/server/appsearch/util/ExecutorManager.java
index 19c64c8..ec2f97c 100644
--- a/service/java/com/android/server/appsearch/util/ExecutorManager.java
+++ b/service/java/com/android/server/appsearch/util/ExecutorManager.java
@@ -20,13 +20,13 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 
+import com.android.server.appsearch.AppSearchEnvironmentFactory;
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -51,9 +51,14 @@
      */
     @NonNull
     public static ExecutorService createDefaultExecutorService() {
-        return new ThreadPoolExecutor(/*corePoolSize=*/1,
-                Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
-                new LinkedBlockingQueue<>());
+        return AppSearchEnvironmentFactory.getEnvironmentInstance()
+          .createExecutorService(
+              /*corePoolSize=*/ 1,
+              /*maxConcurrency=*/ Runtime.getRuntime().availableProcessors(),
+              /*keepAliveTime=*/ 60L,
+              /*unit=*/ TimeUnit.SECONDS,
+              /*workQueue=*/ new LinkedBlockingQueue<>(),
+              /*priority=*/ 0); // priority is unused.
     }
 
     /**
diff --git a/service/java/com/android/server/appsearch/util/ServiceImplHelper.java b/service/java/com/android/server/appsearch/util/ServiceImplHelper.java
index b6b9544..d27a519 100644
--- a/service/java/com/android/server/appsearch/util/ServiceImplHelper.java
+++ b/service/java/com/android/server/appsearch/util/ServiceImplHelper.java
@@ -188,7 +188,8 @@
         // Obtain the user where the client is running in. Note that this could be different from
         // the userHandle where the client wants to run the AppSearch operation in.
         UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
-        Context callingUserContext = AppSearchEnvironmentFactory.getInstance()
+        Context callingUserContext = AppSearchEnvironmentFactory
+            .getEnvironmentInstance()
             .createContextAsUser(mContext, callingUserHandle);
         String callingPackageName =
             Objects.requireNonNull(callerAttributionSource.getPackageName());