diff options
3 files changed, 177 insertions, 1 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index bbbcbbb03480..3ce077431095 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7114,6 +7114,35 @@ public final class Settings { public static final String UI_NIGHT_MODE = "ui_night_mode"; /** + * The current device UI theme mode effect SystemUI and Launcher.<br/> + * <b>Values:</b><br/> + * 0 - The mode that theme will controlled by wallpaper color.<br/> + * 1 - The mode that will always light theme.<br/> + * 2 - The mode that will always dark theme.<br/> + * + * @hide + */ + public static final String THEME_MODE = "theme_mode"; + + /** + * THEME_MODE value for wallpaper mode. + * @hide + */ + public static final int THEME_MODE_WALLPAPER = 0; + + /** + * THEME_MODE value for light theme mode. + * @hide + */ + public static final int THEME_MODE_LIGHT = 1; + + /** + * THEME_MODE value for dark theme mode. + * @hide + */ + public static final int THEME_MODE_DARK = 2; + + /** * Whether screensavers are enabled. * @hide */ diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 5b7fc6efee95..932ffec56ee6 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -591,6 +591,7 @@ public class SettingsBackupTest { Settings.Secure.SHOW_ROTATION_SUGGESTIONS, Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate? Settings.Secure.SMS_DEFAULT_APPLICATION, + Settings.Secure.THEME_MODE, Settings.Secure.TRUST_AGENTS_INITIALIZED, Settings.Secure.TV_INPUT_CUSTOM_LABELS, Settings.Secure.TV_INPUT_HIDDEN_INPUTS, diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index a7c203dca03b..288612621f2c 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -51,6 +51,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; @@ -75,6 +76,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; @@ -336,6 +338,102 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + /** + * Observes changes of theme settings. It will check whether to call + * notifyWallpaperColorsChanged by the current theme and updated theme. + * The light theme and dark theme are controlled by the hint values in Wallpaper colors, + * threrfore, if light theme mode is chosen, HINT_SUPPORTS_DARK_THEME in hint will be + * removed and then notify listeners. + */ + private class ThemeSettingsObserver extends ContentObserver { + + public ThemeSettingsObserver(Handler handler) { + super(handler); + } + + public void startObserving(Context context) { + context.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.THEME_MODE), + false, + this); + } + + public void stopObserving(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + onThemeSettingsChanged(); + } + } + + /** + * Check whether to call notifyWallpaperColorsChanged. Assumed that the theme mode + * was wallpaper theme mode and dark wallpaper was set, therefoe, the theme was dark. + * Then theme mode changing to dark theme mode, however, theme should not update since + * theme was dark already. + */ + private boolean needUpdateLocked(WallpaperColors colors, int themeMode) { + if (colors == null) { + return false; + } + + if (themeMode == mThemeMode) { + return false; + } + + boolean result = true; + boolean supportDarkTheme = + (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; + switch (themeMode) { + case Settings.Secure.THEME_MODE_WALLPAPER: + if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) { + result = supportDarkTheme; + } else { + result = !supportDarkTheme; + } + break; + case Settings.Secure.THEME_MODE_LIGHT: + if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) { + result = supportDarkTheme; + } + break; + case Settings.Secure.THEME_MODE_DARK: + if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) { + result = !supportDarkTheme; + } + break; + default: + Slog.w(TAG, "unkonwn theme mode " + themeMode); + return false; + } + mThemeMode = themeMode; + return result; + } + + void onThemeSettingsChanged() { + WallpaperData wallpaper; + synchronized (mLock) { + wallpaper = mWallpaperMap.get(mCurrentUserId); + int updatedThemeMode = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.THEME_MODE, + Settings.Secure.THEME_MODE_WALLPAPER); + + if (DEBUG) { + Slog.v(TAG, "onThemeSettingsChanged, mode = " + updatedThemeMode); + } + + if (!needUpdateLocked(wallpaper.primaryColors, updatedThemeMode)) { + return; + } + } + + if (wallpaper != null) { + notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM); + } + } + void notifyLockWallpaperChanged() { final IWallpaperManagerCallback cb = mKeyguardListener; if (cb != null) { @@ -413,6 +511,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } userAllColorListeners.finishBroadcast(); } + wallpaperColors = getThemeColorsLocked(wallpaperColors); } final int count = colorListeners.size(); @@ -481,6 +580,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } /** + * We can easily change theme by modified colors hint. This function will check + * current theme mode and return the WallpaperColors fit current theme mode. + * If color need modified, it will return a copied WallpaperColors which + * its ColorsHint is modified to fit current theme mode. + * + * @param colors a wallpaper primary colors representation + */ + private WallpaperColors getThemeColorsLocked(WallpaperColors colors) { + if (colors == null) { + Slog.w(TAG, "Cannot get theme colors because WallpaperColors is null."); + return null; + } + + int colorHints = colors.getColorHints(); + boolean supportDarkTheme = (colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; + if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER || + (mThemeMode == Settings.Secure.THEME_MODE_LIGHT && !supportDarkTheme) || + (mThemeMode == Settings.Secure.THEME_MODE_DARK && supportDarkTheme)) { + return colors; + } + + WallpaperColors themeColors = new WallpaperColors(colors.getPrimaryColor(), + colors.getSecondaryColor(), colors.getTertiaryColor()); + + if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) { + colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_THEME; + } else if (mThemeMode == Settings.Secure.THEME_MODE_DARK) { + colorHints |= WallpaperColors.HINT_SUPPORTS_DARK_THEME; + } + themeColors.setColorHints(colorHints); + return themeColors; + } + + /** * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped * for display. */ @@ -676,6 +809,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>(); int mCurrentUserId = UserHandle.USER_NULL; boolean mInAmbientMode; + int mThemeMode; static class WallpaperData { @@ -734,6 +868,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub long lastDiedTime; boolean wallpaperUpdating; WallpaperObserver wallpaperObserver; + ThemeSettingsObserver themeSettingsObserver; /** * List of callbacks registered they should each be notified when the wallpaper is changed. @@ -1279,6 +1414,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub wallpaper.wallpaperObserver.stopWatching(); wallpaper.wallpaperObserver = null; } + if (wallpaper.themeSettingsObserver != null) { + wallpaper.themeSettingsObserver.stopObserving(mContext); + wallpaper.themeSettingsObserver = null; + } } } @@ -1362,6 +1501,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper); systemWallpaper.wallpaperObserver.startWatching(); } + if (systemWallpaper.themeSettingsObserver == null) { + systemWallpaper.themeSettingsObserver = new ThemeSettingsObserver(null); + systemWallpaper.themeSettingsObserver.startObserving(mContext); + } + mThemeMode = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.THEME_MODE, + Settings.Secure.THEME_MODE_WALLPAPER); switchWallpaper(systemWallpaper, reply); } @@ -1835,7 +1981,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } synchronized (mLock) { - return wallpaperData.primaryColors; + return getThemeColorsLocked(wallpaperData.primaryColors); } } |