summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Marcelo Arteiro <arteiro@google.com> 2025-02-14 06:27:12 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-14 06:27:12 -0800
commitc26379f212e327cbf9ee93b3f72fb08be07a1b82 (patch)
treef9c1c8ca188b868c491c8ef4679e9b6f1b60bd1e
parent2acac35dbd01c4369daeb0d5f7fb4d5a77dacea6 (diff)
parentec69a7e5bb221c0daf5067e7cf31e0a68f871c0b (diff)
Merge "Add new default CMF Styles array in config.xml" into main
-rw-r--r--core/res/res/values/config.xml9
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig10
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColorRule.java39
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColors.java30
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java194
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java122
7 files changed, 311 insertions, 96 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1a311d572e0b..2188469bdf03 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2643,6 +2643,15 @@
<!-- MMS user agent prolfile url -->
<string name="config_mms_user_agent_profile_url" translatable="false"></string>
+ <!-- The default list of possible CMF Names|Style|ColorSource. This array can be
+ overridden device-specific resources. A wildcard (fallback) must be supplied.
+ Name - Read from `ro.boot.hardware.color` sysprop. Fallback (*) required.
+ Styles - frameworks/libs/systemui/monet/src/com/android/systemui/monet/Style.java
+ Color - `home_wallpaper` (for color extraction) or a hexadecimal int (#FFcc99) -->
+ <string-array name="theming_defaults">
+ <item>*|TONAL_SPOT|home_wallpaper</item>
+ </string-array>
+
<!-- National Language Identifier codes for the following two config items.
(from 3GPP TS 23.038 V9.1.1 Table 6.2.1.2.4.1):
0 - reserved
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4974285d3a35..ffcfce9c420e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5903,6 +5903,9 @@
<java-symbol type="drawable" name="ic_notification_summarization" />
<java-symbol type="dimen" name="notification_collapsed_height_with_summarization" />
+ <!-- Device CMF Theming Settings -->
+ <java-symbol type="array" name="theming_defaults" />
+
<!-- Advanced Protection Service USB feature -->
<java-symbol type="string" name="usb_apm_usb_plugged_in_when_locked_notification_title" />
<java-symbol type="string" name="usb_apm_usb_plugged_in_when_locked_notification_text" />
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 3e241bfe6447..082fb5108f8e 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1977,6 +1977,16 @@ flag {
}
flag {
+ name: "hardware_color_styles"
+ namespace: "systemui"
+ description: "Enables loading initial colors based ion hardware color"
+ bug: "347286986"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "shade_launch_accessibility"
namespace: "systemui"
description: "Intercept accessibility focus events for the Shade during launch animations to avoid stray TalkBack events."
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColorRule.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColorRule.java
new file mode 100644
index 000000000000..ecd04a47b8ae
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColorRule.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.theme;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+
+public class HardwareColorRule implements TestRule {
+ public String color = "";
+ public String[] options = {};
+ public boolean isTesting = false;
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ HardwareColors hardwareColors = description.getAnnotation(HardwareColors.class);
+ if (hardwareColors != null) {
+ color = hardwareColors.color();
+ options = hardwareColors.options();
+ isTesting = true;
+ }
+ return base;
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColors.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColors.java
new file mode 100644
index 000000000000..0b8df2e2670e
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/HardwareColors.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.theme;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface HardwareColors {
+ String color();
+ String[] options();
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 5cd0846ded7e..9a0b8125fb25 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -64,6 +64,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.monet.DynamicColors;
@@ -77,6 +78,7 @@ import com.android.systemui.util.settings.SecureSettings;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -98,6 +100,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
private static final UserHandle MANAGED_USER_HANDLE = UserHandle.of(100);
private static final UserHandle PRIVATE_USER_HANDLE = UserHandle.of(101);
+ @Rule
+ public HardwareColorRule rule = new HardwareColorRule();
+
@Mock
private JavaAdapter mJavaAdapter;
@Mock
@@ -148,13 +153,17 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
@Captor
private ArgumentCaptor<ContentObserver> mSettingsObserver;
+ @Mock
+ private SystemPropertiesHelper mSystemProperties;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+
when(mFeatureFlags.isEnabled(Flags.MONET)).thenReturn(true);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
when(mUiModeManager.getContrast()).thenReturn(0.5f);
- when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
+
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()))
@@ -166,11 +175,20 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
when(mResources.getColor(eq(android.R.color.system_neutral2_500), any()))
.thenReturn(Color.BLACK);
+ when(mResources.getStringArray(com.android.internal.R.array.theming_defaults))
+ .thenReturn(rule.options);
+
+ // should fallback to `*|TONAL_SPOT|home_wallpaper`
+ when(mSystemProperties.get("ro.boot.hardware.color")).thenReturn(rule.color);
+ // will try set hardware colors as boot ONLY if user is not set yet
+ when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(!rule.isTesting);
+
mThemeOverlayController = new ThemeOverlayController(mContext,
mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier,
mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
- mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) {
+ mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager,
+ mSystemProperties) {
@VisibleForTesting
protected boolean isNightMode() {
return false;
@@ -214,11 +232,58 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
public void start_checksWallpaper() {
ArgumentCaptor<Runnable> registrationRunnable = ArgumentCaptor.forClass(Runnable.class);
verify(mBgExecutor).execute(registrationRunnable.capture());
+ registrationRunnable.getValue().run();
+ verify(mWallpaperManager).getWallpaperColors(eq(WallpaperManager.FLAG_SYSTEM));
+ }
+
+ @Test
+ @HardwareColors(color = "BLK", options = {
+ "BLK|MONOCHROMATIC|#FF0000",
+ "*|VIBRANT|home_wallpaper"
+ })
+ @EnableFlags(com.android.systemui.Flags.FLAG_HARDWARE_COLOR_STYLES)
+ public void start_checkHardwareColor() {
+ // getWallpaperColors should not be called
+ ArgumentCaptor<Runnable> registrationRunnable = ArgumentCaptor.forClass(Runnable.class);
+ verify(mMainExecutor).execute(registrationRunnable.capture());
+ registrationRunnable.getValue().run();
+ verify(mWallpaperManager, never()).getWallpaperColors(anyInt());
+
+ assertThat(mThemeOverlayController.mThemeStyle).isEqualTo(Style.MONOCHROMATIC);
+ assertThat(mThemeOverlayController.mCurrentColors.get(0).getMainColors().get(
+ 0).toArgb()).isEqualTo(Color.RED);
+ }
+
+ @Test
+ @HardwareColors(color = "", options = {
+ "BLK|MONOCHROMATIC|#FF0000",
+ "*|VIBRANT|home_wallpaper"
+ })
+ @EnableFlags(com.android.systemui.Flags.FLAG_HARDWARE_COLOR_STYLES)
+ public void start_wildcardColor() {
+ // getWallpaperColors will be called because we srt wildcard to `home_wallpaper`
+ ArgumentCaptor<Runnable> registrationRunnable = ArgumentCaptor.forClass(Runnable.class);
+ verify(mMainExecutor).execute(registrationRunnable.capture());
+ registrationRunnable.getValue().run();
+ verify(mWallpaperManager).getWallpaperColors(eq(WallpaperManager.FLAG_SYSTEM));
+ assertThat(mThemeOverlayController.mThemeStyle).isEqualTo(Style.VIBRANT);
+ }
+
+ @Test
+ @HardwareColors(color = "NONEXISTENT", options = {})
+ @EnableFlags(com.android.systemui.Flags.FLAG_HARDWARE_COLOR_STYLES)
+ public void start_fallbackColor() {
+ // getWallpaperColors will be called because we default color source is `home_wallpaper`
+ ArgumentCaptor<Runnable> registrationRunnable = ArgumentCaptor.forClass(Runnable.class);
+ verify(mMainExecutor).execute(registrationRunnable.capture());
registrationRunnable.getValue().run();
verify(mWallpaperManager).getWallpaperColors(eq(WallpaperManager.FLAG_SYSTEM));
+
+ assertThat(mThemeOverlayController.mThemeStyle).isEqualTo(Style.TONAL_SPOT);
}
+
@Test
public void onWallpaperColorsChanged_setsTheme_whenForeground() {
// Should ask for a new theme when wallpaper colors change
@@ -287,9 +352,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"preset\"}";
+ String jsonString = createJsonString(TestColorSource.preset, "override.package.name",
+ "TONAL_SPOT");
+
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -313,11 +378,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -348,11 +409,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -381,11 +438,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"lock_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.lock_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -404,11 +457,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"lock_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.lock_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -455,8 +504,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
@Test
public void onSettingChanged_invalidStyle() {
when(mDeviceProvisionedController.isUserSetup(anyInt())).thenReturn(true);
- String jsonString = "{\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.theme_style\":\"some_invalid_name\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper, "A16B00",
+ "some_invalid_name");
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -473,11 +522,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -506,11 +551,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -537,11 +578,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -570,11 +607,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -599,7 +632,6 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
}
-
@Test
@EnableFlags(com.android.systemui.shared.Flags.FLAG_NEW_CUSTOMIZATION_PICKER_UI)
public void onWallpaperColorsChanged_homeWallpaperWithSameColor_shouldKeepThemeAndReapply() {
@@ -608,11 +640,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(0xffa16b00), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -642,11 +670,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -676,11 +700,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -711,11 +731,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(0xffa16b00), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -745,11 +761,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.color_source\":\"home_wallpaper\","
- + "\"android.theme.customization.system_palette\":\"A16B00\","
- + "\"android.theme.customization.accent_color\":\"A16B00\","
- + "\"android.theme.customization.color_index\":\"2\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper);
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -886,7 +898,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier,
mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
- mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) {
+ mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager,
+ mSystemProperties) {
@VisibleForTesting
protected boolean isNightMode() {
return false;
@@ -926,7 +939,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier,
mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
- mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) {
+ mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager,
+ mSystemProperties) {
@VisibleForTesting
protected boolean isNightMode() {
return false;
@@ -992,7 +1006,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
clearInvocations(mThemeOverlayApplier);
// Device went to sleep and second set of colors was applied.
- mainColors = new WallpaperColors(Color.valueOf(Color.BLUE),
+ mainColors = new WallpaperColors(Color.valueOf(Color.BLUE),
Color.valueOf(Color.RED), null);
mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM,
USER_SYSTEM);
@@ -1018,7 +1032,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
clearInvocations(mThemeOverlayApplier);
// Device went to sleep and second set of colors was applied.
- mainColors = new WallpaperColors(Color.valueOf(Color.BLUE),
+ mainColors = new WallpaperColors(Color.valueOf(Color.BLUE),
Color.valueOf(Color.RED), null);
mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM,
USER_SYSTEM);
@@ -1034,8 +1048,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
- String jsonString =
- "{\"android.theme.customization.system_palette\":\"00FF00\"}";
+ String jsonString = createJsonString(TestColorSource.home_wallpaper, "00FF00",
+ "TONAL_SPOT");
+
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
.thenReturn(jsonString);
@@ -1115,4 +1130,25 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
+ DynamicColors.getCustomColorsMapped(false).size() * 2)
).setResourceValue(any(String.class), eq(TYPE_INT_COLOR_ARGB8), anyInt(), eq(null));
}
+
+ private enum TestColorSource {
+ preset,
+ home_wallpaper,
+ lock_wallpaper
+ }
+
+ private String createJsonString(TestColorSource colorSource, String seedColorHex,
+ String style) {
+ return "{\"android.theme.customization.color_source\":\"" + colorSource.toString() + "\","
+ + "\"android.theme.customization.system_palette\":\"" + seedColorHex + "\","
+ + "\"android.theme.customization.accent_color\":\"" + seedColorHex + "\","
+ + "\"android.theme.customization.color_index\":\"2\","
+ + "\"android.theme.customization.theme_style\":\"" + style + "\"}";
+ }
+
+ private String createJsonString(TestColorSource colorSource) {
+ return createJsonString(colorSource, "A16B00", "TONAL_SPOT");
+ }
+
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 28cf78f6777e..9f60fe212567 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -18,8 +18,10 @@ package com.android.systemui.theme;
import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
+import static com.android.systemui.Flags.hardwareColorStyles;
import static com.android.systemui.Flags.themeOverlayControllerWakefulnessDeprecation;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.monet.ColorScheme.GOOGLE_BLUE;
import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_HOME;
import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_LOCK;
import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_PRESET;
@@ -73,6 +75,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -99,6 +102,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -136,9 +140,11 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
private final DeviceProvisionedController mDeviceProvisionedController;
private final Resources mResources;
// Current wallpaper colors associated to a user.
- private final SparseArray<WallpaperColors> mCurrentColors = new SparseArray<>();
+ @VisibleForTesting
+ protected final SparseArray<WallpaperColors> mCurrentColors = new SparseArray<>();
private final WallpaperManager mWallpaperManager;
private final ActivityManager mActivityManager;
+ protected final SystemPropertiesHelper mSystemPropertiesHelper;
@VisibleForTesting
protected ColorScheme mColorScheme;
// If fabricated overlays were already created for the current theme.
@@ -423,7 +429,9 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
JavaAdapter javaAdapter,
KeyguardTransitionInteractor keyguardTransitionInteractor,
UiModeManager uiModeManager,
- ActivityManager activityManager) {
+ ActivityManager activityManager,
+ SystemPropertiesHelper systemPropertiesHelper
+ ) {
mContext = context;
mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET);
mIsFidelityEnabled = featureFlags.isEnabled(Flags.COLOR_FIDELITY);
@@ -443,6 +451,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mUiModeManager = uiModeManager;
mActivityManager = activityManager;
+ mSystemPropertiesHelper = systemPropertiesHelper;
dumpManager.registerDumpable(TAG, this);
Flow<Boolean> isFinishedInAsleepStateFlow = mKeyguardTransitionInteractor
@@ -498,29 +507,38 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
mUserTracker.addCallback(mUserTrackerCallback, mMainExecutor);
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+ WallpaperColors systemColor;
+ if (hardwareColorStyles() && !mDeviceProvisionedController.isCurrentUserSetup()) {
+ Pair<Integer, Color> defaultSettings = getThemeSettingsDefaults();
+ mThemeStyle = defaultSettings.first;
+ Color seedColor = defaultSettings.second;
+
+ // we only use the first color anyway, so we can pass only the single color we have
+ systemColor = new WallpaperColors(
+ /*primaryColor*/ seedColor,
+ /*secondaryColor*/ seedColor,
+ /*tertiaryColor*/ seedColor
+ );
+ } else {
+ systemColor = mWallpaperManager.getWallpaperColors(
+ getDefaultWallpaperColorsSource(mUserTracker.getUserId()));
+ }
+
// Upon boot, make sure we have the most up to date colors
Runnable updateColors = () -> {
- WallpaperColors systemColor = mWallpaperManager.getWallpaperColors(
- getDefaultWallpaperColorsSource(mUserTracker.getUserId()));
- Runnable applyColors = () -> {
- if (DEBUG) Log.d(TAG, "Boot colors: " + systemColor);
- mCurrentColors.put(mUserTracker.getUserId(), systemColor);
- reevaluateSystemTheme(false /* forceReload */);
- };
- if (mDeviceProvisionedController.isCurrentUserSetup()) {
- mMainExecutor.execute(applyColors);
- } else {
- applyColors.run();
- }
+ if (DEBUG) Log.d(TAG, "Boot colors: " + systemColor);
+ mCurrentColors.put(mUserTracker.getUserId(), systemColor);
+ reevaluateSystemTheme(false /* forceReload */);
};
// Whenever we're going directly to setup wizard, we need to process colors synchronously,
// otherwise we'll see some jank when the activity is recreated.
if (!mDeviceProvisionedController.isCurrentUserSetup()) {
- updateColors.run();
+ mMainExecutor.execute(updateColors);
} else {
mBgExecutor.execute(updateColors);
}
+
mWallpaperManager.addOnColorsChangedListener(mOnColorsChangedListener, null,
UserHandle.USER_ALL);
@@ -604,7 +622,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
@VisibleForTesting
protected boolean isPrivateProfile(UserHandle userHandle) {
- Context usercontext = mContext.createContextAsUser(userHandle,0);
+ Context usercontext = mContext.createContextAsUser(userHandle, 0);
return usercontext.getSystemService(UserManager.class).isPrivateProfile();
}
@@ -720,6 +738,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
return true;
}
+ @SuppressWarnings("StringCaseLocaleUsage") // Package name is not localized
private void updateThemeOverlays() {
final int currentUser = mUserTracker.getUserId();
final String overlayPackageJson = mSecureSettings.getStringForUser(
@@ -746,7 +765,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
OverlayIdentifier systemPalette = categoryToPackage.get(OVERLAY_CATEGORY_SYSTEM_PALETTE);
if (mIsMonetEnabled && systemPalette != null && systemPalette.getPackageName() != null) {
try {
- String colorString = systemPalette.getPackageName().toLowerCase();
+ String colorString = systemPalette.getPackageName().toLowerCase();
if (!colorString.startsWith("#")) {
colorString = "#" + colorString;
}
@@ -856,6 +875,75 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
return style;
}
+ protected Pair<Integer, String> getHardwareColorSetting() {
+ String deviceColorProperty = "ro.boot.hardware.color";
+
+ String[] themeData = mResources.getStringArray(
+ com.android.internal.R.array.theming_defaults);
+
+ // Color can be hex (`#FF0000`) or `home_wallpaper`
+ Map<String, Pair<Integer, String>> themeMap = new HashMap<>();
+
+ // extract all theme settings
+ for (String themeEntry : themeData) {
+ String[] themeComponents = themeEntry.split("\\|");
+ if (themeComponents.length != 3) continue;
+ themeMap.put(themeComponents[0],
+ new Pair<>(Style.valueOf(themeComponents[1]), themeComponents[2]));
+ }
+
+ Pair<Integer, String> fallbackTheme = themeMap.get("*");
+ if (fallbackTheme == null) {
+ Log.d(TAG, "Theming wildcard not found. Fallback to TONAL_SPOT|" + COLOR_SOURCE_HOME);
+ fallbackTheme = new Pair<>(Style.TONAL_SPOT, COLOR_SOURCE_HOME);
+ }
+
+ String deviceColorPropertyValue = mSystemPropertiesHelper.get(deviceColorProperty);
+ Pair<Integer, String> selectedTheme = themeMap.get(deviceColorPropertyValue);
+ if (selectedTheme == null) {
+ Log.d(TAG, "Sysprop `" + deviceColorProperty + "` of value '" + deviceColorPropertyValue
+ + "' not found in theming_defaults: " + Arrays.toString(themeData));
+ selectedTheme = fallbackTheme;
+ }
+
+ return selectedTheme;
+ }
+
+ @VisibleForTesting
+ protected Pair<Integer, Color> getThemeSettingsDefaults() {
+
+ Pair<Integer, String> selectedTheme = getHardwareColorSetting();
+
+ // Last fallback color
+ Color defaultSeedColor = Color.valueOf(GOOGLE_BLUE);
+
+ // defaultColor will come from wallpaper or be parsed from a string
+ boolean isWallpaper = selectedTheme.second.equals(COLOR_SOURCE_HOME);
+
+ if (isWallpaper) {
+ WallpaperColors wallpaperColors = mWallpaperManager.getWallpaperColors(
+ getDefaultWallpaperColorsSource(mUserTracker.getUserId()));
+
+ if (wallpaperColors != null) {
+ defaultSeedColor = wallpaperColors.getPrimaryColor();
+ }
+
+ Log.d(TAG, "Default seed color read from home wallpaper: " + Integer.toHexString(
+ defaultSeedColor.toArgb()));
+ } else {
+ try {
+ defaultSeedColor = Color.valueOf(Color.parseColor(selectedTheme.second));
+ Log.d(TAG, "Default seed color read from resource: " + Integer.toHexString(
+ defaultSeedColor.toArgb()));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Error parsing color: " + selectedTheme.second, e);
+ // defaultSeedColor remains unchanged in this case
+ }
+ }
+
+ return new Pair<>(selectedTheme.first, defaultSeedColor);
+ }
+
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("mSystemColors=" + mCurrentColors);