Add theme mode design let user can choose theme self

Add a ContentObserver on WallpaperManagerService to
listen THEME_MODE value change. When changed, call
notifyWallpaperColorsChanged and set WallpaperColors
color hint by the current mode.

Bug: 63903361
Test: manual
Change-Id: I4f7aa7b184565b1bb23c7f4f1f07fc310dac7546
This commit is contained in:
Tony Huang
2018-05-02 10:53:52 +08:00
committed by Lucas Dupin
parent 118b1e3bb8
commit f0800fa3bd
3 changed files with 177 additions and 1 deletions

View File

@@ -7113,6 +7113,35 @@ public final class Settings {
*/ */
public static final String UI_NIGHT_MODE = "ui_night_mode"; 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. * Whether screensavers are enabled.
* @hide * @hide

View File

@@ -591,6 +591,7 @@ public class SettingsBackupTest {
Settings.Secure.SHOW_ROTATION_SUGGESTIONS, Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate? Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
Settings.Secure.SMS_DEFAULT_APPLICATION, Settings.Secure.SMS_DEFAULT_APPLICATION,
Settings.Secure.THEME_MODE,
Settings.Secure.TRUST_AGENTS_INITIALIZED, Settings.Secure.TRUST_AGENTS_INITIALIZED,
Settings.Secure.TV_INPUT_CUSTOM_LABELS, Settings.Secure.TV_INPUT_CUSTOM_LABELS,
Settings.Secure.TV_INPUT_HIDDEN_INPUTS, Settings.Secure.TV_INPUT_HIDDEN_INPUTS,

View File

@@ -51,6 +51,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder; import android.graphics.BitmapRegionDecoder;
@@ -75,6 +76,7 @@ import android.os.ServiceManager;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService; 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() { void notifyLockWallpaperChanged() {
final IWallpaperManagerCallback cb = mKeyguardListener; final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) { if (cb != null) {
@@ -413,6 +511,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
} }
userAllColorListeners.finishBroadcast(); userAllColorListeners.finishBroadcast();
} }
wallpaperColors = getThemeColorsLocked(wallpaperColors);
} }
final int count = colorListeners.size(); final int count = colorListeners.size();
@@ -480,6 +579,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 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display. * for display.
@@ -676,6 +809,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>(); final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
int mCurrentUserId = UserHandle.USER_NULL; int mCurrentUserId = UserHandle.USER_NULL;
boolean mInAmbientMode; boolean mInAmbientMode;
int mThemeMode;
static class WallpaperData { static class WallpaperData {
@@ -734,6 +868,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
long lastDiedTime; long lastDiedTime;
boolean wallpaperUpdating; boolean wallpaperUpdating;
WallpaperObserver wallpaperObserver; WallpaperObserver wallpaperObserver;
ThemeSettingsObserver themeSettingsObserver;
/** /**
* List of callbacks registered they should each be notified when the wallpaper is changed. * 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.stopWatching();
wallpaper.wallpaperObserver = null; 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 = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching(); 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); switchWallpaper(systemWallpaper, reply);
} }
@@ -1835,7 +1981,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
} }
synchronized (mLock) { synchronized (mLock) {
return wallpaperData.primaryColors; return getThemeColorsLocked(wallpaperData.primaryColors);
} }
} }