Fixes flaky test to avoid demotion

Makes background executor injectable from tests, and uses direct
executor in test to run code synchronously

Fixes: 333668441
Flag: NA
Test: Tests pass without flakes
Change-Id: I8447d7464b978054d0d594223762534c30b78fec
diff --git a/src/com/android/customization/model/color/ColorCustomizationManager.java b/src/com/android/customization/model/color/ColorCustomizationManager.java
index 5bd302b..9acbc4f 100644
--- a/src/com/android/customization/model/color/ColorCustomizationManager.java
+++ b/src/com/android/customization/model/color/ColorCustomizationManager.java
@@ -66,7 +66,6 @@
 public class ColorCustomizationManager implements CustomizationManager<ColorOption> {
 
     private static final String TAG = "ColorCustomizationManager";
-    private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
 
     private static final Set<String> COLOR_OVERLAY_SETTINGS = new HashSet<>();
     static {
@@ -80,8 +79,8 @@
 
     private final ColorOptionsProvider mProvider;
     private final OverlayManagerCompat mOverlayManagerCompat;
+    private final ExecutorService mExecutorService;
     private final ContentResolver mContentResolver;
-    private final ContentObserver mObserver;
 
     private Map<String, String> mCurrentOverlays;
     @ColorSource private String mCurrentSource;
@@ -92,22 +91,31 @@
     /** Returns the {@link ColorCustomizationManager} instance. */
     public static ColorCustomizationManager getInstance(Context context,
             OverlayManagerCompat overlayManagerCompat) {
+        return getInstance(context, overlayManagerCompat, Executors.newSingleThreadExecutor());
+    }
+
+    /** Returns the {@link ColorCustomizationManager} instance. */
+    @VisibleForTesting
+    static ColorCustomizationManager getInstance(Context context,
+            OverlayManagerCompat overlayManagerCompat, ExecutorService executorService) {
         if (sColorCustomizationManager == null) {
             Context appContext = context.getApplicationContext();
             sColorCustomizationManager = new ColorCustomizationManager(
                     new ColorProvider(appContext,
                             appContext.getString(R.string.themes_stub_package)),
-                    appContext.getContentResolver(), overlayManagerCompat);
+                    appContext.getContentResolver(), overlayManagerCompat,
+                    executorService);
         }
         return sColorCustomizationManager;
     }
 
     @VisibleForTesting
     ColorCustomizationManager(ColorOptionsProvider provider, ContentResolver contentResolver,
-            OverlayManagerCompat overlayManagerCompat) {
+            OverlayManagerCompat overlayManagerCompat, ExecutorService executorService) {
         mProvider = provider;
         mContentResolver = contentResolver;
-        mObserver = new ContentObserver(/* handler= */ null) {
+        mExecutorService = executorService;
+        ContentObserver observer = new ContentObserver(/* handler= */ null) {
             @Override
             public void onChange(boolean selfChange, Uri uri) {
                 super.onChange(selfChange, uri);
@@ -122,7 +130,7 @@
             }
         };
         mContentResolver.registerContentObserver(
-                Settings.Secure.CONTENT_URI, /* notifyForDescendants= */ true, mObserver);
+                Settings.Secure.CONTENT_URI, /* notifyForDescendants= */ true, observer);
         mOverlayManagerCompat = overlayManagerCompat;
     }
 
@@ -137,7 +145,7 @@
     }
 
     private void applyOverlays(ColorOption colorOption, Callback callback) {
-        sExecutorService.submit(() -> {
+        mExecutorService.submit(() -> {
             String currentStoredOverlays = getStoredOverlays();
             if (TextUtils.isEmpty(currentStoredOverlays)) {
                 currentStoredOverlays = "{}";
diff --git a/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt b/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
index e9f4683..0776cc8 100644
--- a/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
+++ b/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
@@ -32,6 +32,7 @@
 import com.android.customization.picker.color.shared.model.ColorType
 import com.android.systemui.monet.Style
 import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
 import org.json.JSONObject
 import org.junit.Before
 import org.junit.Rule
@@ -58,7 +59,13 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         val application = ApplicationProvider.getApplicationContext<Context>()
-        manager = ColorCustomizationManager(provider, application.contentResolver, mockOM)
+        manager =
+            ColorCustomizationManager(
+                provider,
+                application.contentResolver,
+                mockOM,
+                MoreExecutors.newDirectExecutorService()
+            )
     }
 
     @Test
@@ -103,8 +110,6 @@
             }
         )
 
-        Thread.sleep(100)
-
         val overlaysJson = JSONObject(manager.storedOverlays)
 
         assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
@@ -126,8 +131,6 @@
             }
         )
 
-        Thread.sleep(100)
-
         val overlaysJson = JSONObject(manager.storedOverlays)
         assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
     }
@@ -171,8 +174,6 @@
             }
         )
 
-        Thread.sleep(100)
-
         val overlaysJson = JSONObject(manager.storedOverlays)
         assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("1")
     }
@@ -191,8 +192,6 @@
             }
         )
 
-        Thread.sleep(100)
-
         val overlaysJson = JSONObject(manager.storedOverlays)
         assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("0")
     }