Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1716e05 authored by Lucas Dupin's avatar Lucas Dupin
Browse files

Skip theme application if it's already current

Test: manually change themes
Test: atest ThemeOverlayControllerTest
Bug: 202673948
Change-Id: I3e6ec65f58dcfb3e35b565e76d86147b913f2668
parent 74807869
Loading
Loading
Loading
Loading
+48 −18
Original line number Diff line number Diff line
@@ -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<WallpaperColors> 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<String, OverlayIdentifier> 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);
+23 −6
Original line number Diff line number Diff line
@@ -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<BroadcastReceiver> 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;
            }
        };