Defer color events until end of SUW

Color events might recreate activities, disrupting the setup wizard flow

Test: atest ThemeOverlayControllerTest
Test: manual
Bug: 182560740
Change-Id: Id924b3356c37c533dfbcb92048f95295a29a3dfd
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index d317712..fc9a35d 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -19,9 +19,9 @@
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -49,8 +49,10 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.util.settings.SecureSettings;
 
 import org.json.JSONException;
@@ -92,8 +94,9 @@
     private final Executor mMainExecutor;
     private final Handler mBgHandler;
     private final WallpaperManager mWallpaperManager;
-    private final KeyguardStateController mKeyguardStateController;
     private final boolean mIsMonetEnabled;
+    private final UserTracker mUserTracker;
+    private DeviceProvisionedController mDeviceProvisionedController;
     private WallpaperColors mSystemColors;
     // If fabricated overlays were already created for the current theme.
     private boolean mNeedsOverlayCreation;
@@ -107,17 +110,76 @@
     private FabricatedOverlay mNeutralOverlay;
     // If wallpaper color event will be accepted and change the UI colors.
     private boolean mAcceptColorEvents = true;
+    // Defers changing themes until Setup Wizard is done.
+    private boolean mDeferredThemeEvaluation;
+
+    private final DeviceProvisionedListener mDeviceProvisionedListener =
+            new DeviceProvisionedListener() {
+                @Override
+                public void onUserSetupChanged() {
+                    if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+                        return;
+                    }
+                    if (!mDeferredThemeEvaluation) {
+                        return;
+                    }
+                    Log.i(TAG, "Applying deferred theme");
+                    mDeferredThemeEvaluation = false;
+                    reevaluateSystemTheme(true /* forceReload */);
+                }
+            };
+
+    private final OnColorsChangedListener mOnColorsChangedListener = (wallpaperColors, which) -> {
+        if (!mAcceptColorEvents) {
+            Log.i(TAG, "Wallpaper color event rejected: " + wallpaperColors);
+            return;
+        }
+        if (wallpaperColors != null) {
+            mAcceptColorEvents = false;
+        }
+
+        if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+            mSystemColors = wallpaperColors;
+            if (DEBUG) {
+                Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
+            }
+        }
+
+        if (mDeviceProvisionedController != null
+                && !mDeviceProvisionedController.isCurrentUserSetup()) {
+            Log.i(TAG, "Wallpaper color event deferred until setup is finished: "
+                    + wallpaperColors);
+            mDeferredThemeEvaluation = true;
+            return;
+        }
+        reevaluateSystemTheme(false /* forceReload */);
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())
+                    || Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction())) {
+                if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
+                reevaluateSystemTheme(true /* forceReload */);
+            } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) {
+                mAcceptColorEvents = true;
+                Log.i(TAG, "Allowing color events again");
+            }
+        }
+    };
 
     @Inject
     public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher,
             @Background Handler bgHandler, @Main Executor mainExecutor,
             @Background Executor bgExecutor, ThemeOverlayApplier themeOverlayApplier,
             SecureSettings secureSettings, WallpaperManager wallpaperManager,
-            UserManager userManager, KeyguardStateController keyguardStateController,
-            DumpManager dumpManager, FeatureFlags featureFlags) {
+            UserManager userManager, DeviceProvisionedController deviceProvisionedController,
+            UserTracker userTracker, DumpManager dumpManager, FeatureFlags featureFlags) {
         super(context);
 
         mIsMonetEnabled = featureFlags.isMonetEnabled();
+        mDeviceProvisionedController = deviceProvisionedController;
         mBroadcastDispatcher = broadcastDispatcher;
         mUserManager = userManager;
         mBgExecutor = bgExecutor;
@@ -126,7 +188,7 @@
         mThemeManager = themeOverlayApplier;
         mSecureSettings = secureSettings;
         mWallpaperManager = wallpaperManager;
-        mKeyguardStateController = keyguardStateController;
+        mUserTracker = userTracker;
         dumpManager.registerDumpable(TAG, this);
     }
 
@@ -137,19 +199,8 @@
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
         filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
-        mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())
-                        || Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction())) {
-                    if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
-                    reevaluateSystemTheme(true /* forceReload */);
-                } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) {
-                    mAcceptColorEvents = true;
-                    Log.i(TAG, "Allowing color events again");
-                }
-            }
-        }, filter, mMainExecutor, UserHandle.ALL);
+        mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mMainExecutor,
+                UserHandle.ALL);
         mSecureSettings.registerContentObserverForUser(
                 Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
                 false,
@@ -158,12 +209,19 @@
                     public void onChange(boolean selfChange, Collection<Uri> collection, int flags,
                             int userId) {
                         if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId);
-                        if (ActivityManager.getCurrentUser() == userId) {
-                            reevaluateSystemTheme(true /* forceReload */);
+                        if (mUserTracker.getUserId() != userId) {
+                            return;
                         }
+                        if (!mDeviceProvisionedController.isUserSetup(userId)) {
+                            Log.i(TAG, "Theme application deferred when setting changed.");
+                            mDeferredThemeEvaluation = true;
+                            return;
+                        }
+                        reevaluateSystemTheme(true /* forceReload */);
                     }
                 },
                 UserHandle.USER_ALL);
+        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
 
         // Upon boot, make sure we have the most up to date colors
         mBgExecutor.execute(() -> {
@@ -174,23 +232,8 @@
                 reevaluateSystemTheme(false /* forceReload */);
             });
         });
-        mWallpaperManager.addOnColorsChangedListener((wallpaperColors, which) -> {
-            if (!mAcceptColorEvents) {
-                Log.i(TAG, "Wallpaper color event rejected: " + wallpaperColors);
-                return;
-            }
-            if (wallpaperColors != null && mAcceptColorEvents) {
-                mAcceptColorEvents = false;
-            }
-
-            if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
-                mSystemColors = wallpaperColors;
-                if (DEBUG) {
-                    Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
-                }
-            }
-            reevaluateSystemTheme(false /* forceReload */);
-        }, null, UserHandle.USER_ALL);
+        mWallpaperManager.addOnColorsChangedListener(mOnColorsChangedListener, null,
+                UserHandle.USER_ALL);
     }
 
     private void reevaluateSystemTheme(boolean forceReload) {
@@ -252,7 +295,7 @@
     }
 
     private void updateThemeOverlays() {
-        final int currentUser = ActivityManager.getCurrentUser();
+        final int currentUser = mUserTracker.getUserId();
         final String overlayPackageJson = mSecureSettings.getStringForUser(
                 Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
                 currentUser);
@@ -360,5 +403,6 @@
         pw.println("mIsMonetEnabled=" + mIsMonetEnabled);
         pw.println("mNeedsOverlayCreation=" + mNeedsOverlayCreation);
         pw.println("mAcceptColorEvents=" + mAcceptColorEvents);
+        pw.println("mDeferredThemeEvaluation=" + mDeferredThemeEvaluation);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 4e7e0a3..ddf0537 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -26,6 +26,8 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
@@ -49,8 +51,10 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
@@ -86,24 +90,29 @@
     @Mock
     private UserManager mUserManager;
     @Mock
-    private KeyguardStateController mKeyguardStateController;
+    private UserTracker mUserTracker;
     @Mock
     private DumpManager mDumpManager;
     @Mock
+    private DeviceProvisionedController mDeviceProvisionedController;
+    @Mock
     private FeatureFlags mFeatureFlags;
     @Captor
     private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiver;
     @Captor
     private ArgumentCaptor<WallpaperManager.OnColorsChangedListener> mColorsListener;
+    @Captor
+    private ArgumentCaptor<DeviceProvisionedListener> mDeviceProvisionedListener;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         when(mFeatureFlags.isMonetEnabled()).thenReturn(true);
+        when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
         mThemeOverlayController = new ThemeOverlayController(null /* context */,
                 mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier,
-                mSecureSettings, mWallpaperManager, mUserManager, mKeyguardStateController,
-                mDumpManager, mFeatureFlags) {
+                mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
+                mUserTracker, mDumpManager, mFeatureFlags) {
             @Nullable
             @Override
             protected FabricatedOverlay getOverlay(int color, int type) {
@@ -120,6 +129,7 @@
         verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiver.capture(), any(),
                 eq(mMainExecutor), any());
         verify(mDumpManager).registerDumpable(any(), any());
+        verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture());
     }
 
     @Test
@@ -191,6 +201,22 @@
     }
 
     @Test
+    public void onWallpaperColorsChanged_defersUntilSetupIsCompleted() {
+        reset(mDeviceProvisionedController);
+        WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+                Color.valueOf(Color.BLUE), null);
+        mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+        verify(mThemeOverlayApplier, never())
+                .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+
+        when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
+        mDeviceProvisionedListener.getValue().onUserSetupChanged();
+
+        verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any());
+    }
+
+    @Test
     public void onWallpaperColorsChanged_parsesColorsFromWallpaperPicker() {
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
                 Color.valueOf(Color.BLUE), null);