From c1716e057a167c606f31a147689852aec81b3651 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 22 Mar 2022 16:00:21 -0700 Subject: [PATCH] Skip theme application if it's already current Test: manually change themes Test: atest ThemeOverlayControllerTest Bug: 202673948 Change-Id: I3e6ec65f58dcfb3e35b565e76d86147b913f2668 --- .../theme/ThemeOverlayController.java | 66 ++++++++++++++----- .../theme/ThemeOverlayControllerTest.java | 29 ++++++-- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index fb8055199d612..c06b8e67c2f8a 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -38,6 +38,7 @@ import android.content.om.FabricatedOverlay; import android.content.om.OverlayIdentifier; import android.content.pm.UserInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Color; import android.net.Uri; @@ -53,6 +54,7 @@ import android.util.SparseIntArray; import android.util.TypedValue; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.systemui.CoreStartable; @@ -114,10 +116,12 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { private final boolean mIsMonetEnabled; private final UserTracker mUserTracker; private final DeviceProvisionedController mDeviceProvisionedController; + private final Resources mResources; // Current wallpaper colors associated to a user. private final SparseArray mCurrentColors = new SparseArray<>(); private final WallpaperManager mWallpaperManager; - private ColorScheme mColorScheme; + @VisibleForTesting + protected ColorScheme mColorScheme; // If fabricated overlays were already created for the current theme. private boolean mNeedsOverlayCreation; // Dominant color extracted from wallpaper, NOT the color used on the overlay @@ -344,7 +348,7 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { SecureSettings secureSettings, WallpaperManager wallpaperManager, UserManager userManager, DeviceProvisionedController deviceProvisionedController, UserTracker userTracker, DumpManager dumpManager, FeatureFlags featureFlags, - WakefulnessLifecycle wakefulnessLifecycle) { + @Main Resources resources, WakefulnessLifecycle wakefulnessLifecycle) { super(context); mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET); @@ -358,6 +362,7 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { mSecureSettings = secureSettings; mWallpaperManager = wallpaperManager; mUserTracker = userTracker; + mResources = resources; mWakefulnessLifecycle = wakefulnessLifecycle; dumpManager.registerDumpable(TAG, this); } @@ -466,8 +471,13 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { mMainWallpaperColor = mainColor; if (mIsMonetEnabled) { + mThemeStyle = fetchThemeStyleFromSetting(); mSecondaryOverlay = getOverlay(mMainWallpaperColor, ACCENT, mThemeStyle); mNeutralOverlay = getOverlay(mMainWallpaperColor, NEUTRAL, mThemeStyle); + if (colorSchemeIsApplied()) { + Log.d(TAG, "Skipping overlay creation. Theme was already: " + mColorScheme); + return; + } mNeedsOverlayCreation = true; if (DEBUG) { Log.d(TAG, "fetched overlays. accent: " + mSecondaryOverlay @@ -493,7 +503,7 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { * Given a color candidate, return an overlay definition. */ protected @Nullable FabricatedOverlay getOverlay(int color, int type, Style style) { - boolean nightMode = (mContext.getResources().getConfiguration().uiMode + boolean nightMode = (mResources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; mColorScheme = new ColorScheme(color, nightMode, style); @@ -525,6 +535,23 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { return overlay.build(); } + /** + * Checks if the color scheme in mColorScheme matches the current system palettes. + */ + private boolean colorSchemeIsApplied() { + return mResources.getColor( + android.R.color.system_accent1_500, mContext.getTheme()) + == mColorScheme.getAccent1().get(6) + && mResources.getColor(android.R.color.system_accent2_500, mContext.getTheme()) + == mColorScheme.getAccent2().get(6) + && mResources.getColor(android.R.color.system_accent3_500, mContext.getTheme()) + == mColorScheme.getAccent3().get(6) + && mResources.getColor(android.R.color.system_neutral1_500, mContext.getTheme()) + == mColorScheme.getNeutral1().get(6) + && mResources.getColor(android.R.color.system_neutral2_500, mContext.getTheme()) + == mColorScheme.getNeutral2().get(6); + } + private void updateThemeOverlays() { final int currentUser = mUserTracker.getUserId(); final String overlayPackageJson = mSecureSettings.getStringForUser( @@ -532,7 +559,6 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { currentUser); if (DEBUG) Log.d(TAG, "updateThemeOverlays. Setting: " + overlayPackageJson); final Map categoryToPackage = new ArrayMap<>(); - Style newStyle = mThemeStyle; if (!TextUtils.isEmpty(overlayPackageJson)) { try { JSONObject object = new JSONObject(overlayPackageJson); @@ -543,25 +569,11 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { categoryToPackage.put(category, identifier); } } - - try { - newStyle = Style.valueOf( - object.getString(ThemeOverlayApplier.OVERLAY_CATEGORY_THEME_STYLE)); - } catch (IllegalArgumentException e) { - newStyle = Style.TONAL_SPOT; - } } catch (JSONException e) { Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e); } } - if (mIsMonetEnabled && newStyle != mThemeStyle) { - mThemeStyle = newStyle; - mNeutralOverlay = getOverlay(mMainWallpaperColor, NEUTRAL, mThemeStyle); - mSecondaryOverlay = getOverlay(mMainWallpaperColor, ACCENT, mThemeStyle); - mNeedsOverlayCreation = true; - } - // Let's generate system overlay if the style picker decided to override it. OverlayIdentifier systemPalette = categoryToPackage.get(OVERLAY_CATEGORY_SYSTEM_PALETTE); if (mIsMonetEnabled && systemPalette != null && systemPalette.getPackageName() != null) { @@ -626,6 +638,24 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable { } } + private Style fetchThemeStyleFromSetting() { + Style style = mThemeStyle; + final String overlayPackageJson = mSecureSettings.getStringForUser( + Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, + mUserTracker.getUserId()); + if (!TextUtils.isEmpty(overlayPackageJson)) { + try { + JSONObject object = new JSONObject(overlayPackageJson); + style = Style.valueOf( + object.getString(ThemeOverlayApplier.OVERLAY_CATEGORY_THEME_STYLE)); + } catch (JSONException | IllegalArgumentException e) { + Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e); + style = Style.TONAL_SPOT; + } + } + return style; + } + @Override public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { pw.println("mSystemColors=" + mCurrentColors); 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 f804d83a66a64..b8f66fc41f04f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -39,6 +39,7 @@ import android.content.BroadcastReceiver; import android.content.Intent; import android.content.om.FabricatedOverlay; import android.content.om.OverlayIdentifier; +import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Color; import android.os.Handler; @@ -56,6 +57,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.monet.ColorScheme; import com.android.systemui.monet.Style; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -108,6 +110,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlags; @Mock + private Resources mResources; + @Mock private WakefulnessLifecycle mWakefulnessLifecycle; @Captor private ArgumentCaptor mBroadcastReceiver; @@ -129,10 +133,20 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { when(mFeatureFlags.isEnabled(Flags.MONET)).thenReturn(true); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true); - mThemeOverlayController = new ThemeOverlayController(null /* context */, + when(mResources.getColor(eq(android.R.color.system_accent1_500), any())) + .thenReturn(Color.RED); + when(mResources.getColor(eq(android.R.color.system_accent2_500), any())) + .thenReturn(Color.GREEN); + when(mResources.getColor(eq(android.R.color.system_accent3_500), any())) + .thenReturn(Color.BLUE); + when(mResources.getColor(eq(android.R.color.system_neutral1_500), any())) + .thenReturn(Color.YELLOW); + when(mResources.getColor(eq(android.R.color.system_neutral2_500), any())) + .thenReturn(Color.BLACK); + mThemeOverlayController = new ThemeOverlayController(mContext, mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, - mUserTracker, mDumpManager, mFeatureFlags, mWakefulnessLifecycle) { + mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle) { @Nullable @Override protected FabricatedOverlay getOverlay(int color, int type, Style style) { @@ -140,6 +154,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { when(overlay.getIdentifier()) .thenReturn(new OverlayIdentifier(Integer.toHexString(color | 0xff000000))); mCurrentStyle = style; + mColorScheme = new ColorScheme(color, false /* nightMode */, style); return overlay; } }; @@ -643,16 +658,17 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { Executor executor = MoreExecutors.directExecutor(); - mThemeOverlayController = new ThemeOverlayController(null /* context */, + mThemeOverlayController = new ThemeOverlayController(mContext, mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, - mUserTracker, mDumpManager, mFeatureFlags, mWakefulnessLifecycle) { + mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle) { @Nullable @Override protected FabricatedOverlay getOverlay(int color, int type, Style style) { FabricatedOverlay overlay = mock(FabricatedOverlay.class); when(overlay.getIdentifier()) .thenReturn(new OverlayIdentifier("com.thebest.livewallpaperapp.ever")); + mColorScheme = new ColorScheme(color, false /* nightMode */, style); return overlay; } @@ -679,16 +695,17 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { .thenReturn(new WallpaperColors(Color.valueOf(Color.GRAY), null, null)); Executor executor = MoreExecutors.directExecutor(); - mThemeOverlayController = new ThemeOverlayController(null /* context */, + mThemeOverlayController = new ThemeOverlayController(mContext, mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, - mUserTracker, mDumpManager, mFeatureFlags, mWakefulnessLifecycle) { + mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle) { @Nullable @Override protected FabricatedOverlay getOverlay(int color, int type, Style style) { FabricatedOverlay overlay = mock(FabricatedOverlay.class); when(overlay.getIdentifier()) .thenReturn(new OverlayIdentifier(Integer.toHexString(color | 0xff000000))); + mColorScheme = new ColorScheme(color, false /* nightMode */, style); return overlay; } };