Loading core/java/android/app/IUiModeManager.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -68,4 +68,9 @@ interface IUiModeManager { * Tells if Night mode is locked or not. */ boolean isNightModeLocked(); /** * @hide */ boolean setNightModeActivated(boolean active); } core/java/android/app/UiModeManager.java +14 −0 Original line number Diff line number Diff line Loading @@ -473,4 +473,18 @@ public class UiModeManager { } return true; } /** * @hide* */ public boolean setNightModeActivated(boolean active) { if (mService != null) { try { return mService.setNightModeActivated(active); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return false; } } packages/SystemUI/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -916,6 +916,10 @@ <string name="quick_settings_ui_mode_night_label">Dark theme</string> <!-- QuickSettings: Label for the dark theme tile when enabled by battery saver. [CHAR LIMIT=40] --> <string name="quick_settings_ui_mode_night_label_battery_saver">Dark theme\nBattery saver</string> <!-- QuickSettings: Secondary text for when the Dark Mode will be enabled at sunset. [CHAR LIMIT=20] --> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset">On at sunset</string> <!-- QuickSettings: Secondary text for when the Dark Mode will be on until sunrise. [CHAR LIMIT=20] --> <string name="quick_settings_dark_mode_secondary_label_until_sunrise">Until sunrise</string> <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] --> <string name="quick_settings_nfc_label">NFC</string> Loading packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +15 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; import android.text.TextUtils; import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.R; Loading Loading @@ -79,24 +79,33 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements return; } boolean newState = !mState.value; mUiModeManager.setNightMode(newState ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO); mUiModeManager.setNightModeActivated(newState); refreshState(newState); } @Override protected void handleUpdateState(BooleanState state, Object arg) { int uiMode = mUiModeManager.getNightMode(); boolean powerSave = mBatteryController.isPowerSave(); boolean isAuto = uiMode == UiModeManager.MODE_NIGHT_AUTO; boolean nightMode = (mContext.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; if (isAuto) { state.secondaryLabel = mContext.getResources().getString(nightMode ? R.string.quick_settings_dark_mode_secondary_label_until_sunrise : R.string.quick_settings_dark_mode_secondary_label_on_at_sunset); } else { state.secondaryLabel = null; } state.value = nightMode; state.label = mContext.getString(powerSave ? R.string.quick_settings_ui_mode_night_label_battery_saver : R.string.quick_settings_ui_mode_night_label); state.contentDescription = state.label; state.icon = mIcon; state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = TextUtils.isEmpty(state.secondaryLabel) ? state.label : TextUtils.concat(state.label, ", ", state.secondaryLabel); if (powerSave) { state.state = Tile.STATE_UNAVAILABLE; } else { Loading services/core/java/com/android/server/UiModeManagerService.java +114 −4 Original line number Diff line number Diff line Loading @@ -56,8 +56,8 @@ import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; import android.util.ArraySet; import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.DisableCarModeActivity; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; Loading @@ -65,6 +65,7 @@ import com.android.internal.util.DumpUtils; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; import com.android.server.wm.WindowManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -72,6 +73,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import static android.content.Intent.ACTION_SCREEN_OFF; final class UiModeManagerService extends SystemService { private static final String TAG = UiModeManager.class.getSimpleName(); private static final boolean LOG = false; Loading @@ -85,6 +88,10 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mNightMode = UiModeManager.MODE_NIGHT_NO; // we use the override auto mode // for example: force night mode off in the night time while in auto mode private int mNightModeOverride = mNightMode; protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE + "_override"; private Map<Integer, String> mCarModePackagePriority = new HashMap<>(); private boolean mCarModeEnabled = false; Loading Loading @@ -119,6 +126,7 @@ final class UiModeManagerService extends SystemService { private TwilightManager mTwilightManager; private NotificationManager mNotificationManager; private StatusBarManager mStatusBarManager; private WindowManagerInternal mWindowManager; private PowerManager.WakeLock mWakeLock; Loading @@ -128,6 +136,17 @@ final class UiModeManagerService extends SystemService { super(context); } @VisibleForTesting protected UiModeManagerService(Context context, WindowManagerInternal wm, PowerManager.WakeLock wl, TwilightManager tm, boolean setupWizardComplete) { super(context); mWindowManager = wm; mWakeLock = wl; mTwilightManager = tm; mSetupWizardComplete = setupWizardComplete; } private static Intent buildHomeIntent(String category) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(category); Loading Loading @@ -189,8 +208,23 @@ final class UiModeManagerService extends SystemService { public void onTwilightStateChanged(@Nullable TwilightState state) { synchronized (mLock) { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { updateComputedNightModeLocked(); final IntentFilter intentFilter = new IntentFilter(ACTION_SCREEN_OFF); getContext().registerReceiver(mOnScreenOffHandler, intentFilter); } } } }; private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { updateLocked(0, 0); try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { // we ignore this exception if the receiver is unregistered already. } } } Loading Loading @@ -229,6 +263,8 @@ final class UiModeManagerService extends SystemService { public void onChange(boolean selfChange, Uri uri) { int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mNightMode, 0); mode = mode == UiModeManager.MODE_NIGHT_AUTO ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode)); } }; Loading @@ -247,6 +283,7 @@ final class UiModeManagerService extends SystemService { final PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); mWindowManager = LocalServices.getService(WindowManagerInternal.class); // If setup isn't complete for this user listen for completion so we can unblock // being able to send a night mode configuration change event Loading Loading @@ -313,6 +350,16 @@ final class UiModeManagerService extends SystemService { false, mDarkThemeObserver, 0); } @VisibleForTesting protected IUiModeManager getService() { return mService; } @VisibleForTesting protected Configuration getConfiguration() { return mConfiguration; } // Records whether setup wizard has happened or not and adds an observer for this user if not. private void verifySetupWizardCompleted() { final Context context = getContext(); Loading Loading @@ -347,8 +394,11 @@ final class UiModeManagerService extends SystemService { if (mSetupWizardComplete) { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); mNightModeOverride = Secure.getIntForUser(context.getContentResolver(), OVERRIDE_NIGHT_MODE, defaultNightMode, userId); } else { mNightMode = defaultNightMode; mNightModeOverride = defaultNightMode; } return oldNightMode != mNightMode; Loading Loading @@ -474,14 +524,30 @@ final class UiModeManagerService extends SystemService { try { synchronized (mLock) { if (mNightMode != mode) { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { // we ignore this exception if the receiver is unregistered already. } } // Only persist setting if not in car mode if (!mCarModeEnabled) { Secure.putIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mode, user); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); } mNightMode = mode; mNightModeOverride = mode; //on screen off will update configuration instead if (mNightMode != UiModeManager.MODE_NIGHT_AUTO) { updateLocked(0, 0); } else { getContext().registerReceiver( mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF)); } } } } finally { Loading Loading @@ -521,6 +587,34 @@ final class UiModeManagerService extends SystemService { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; dumpImpl(pw); } @Override public boolean setNightModeActivated(boolean active) { synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { } mNightModeOverride = active ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; } else if (mNightMode == UiModeManager.MODE_NIGHT_NO && active) { mNightMode = UiModeManager.MODE_NIGHT_YES; } else if (mNightMode == UiModeManager.MODE_NIGHT_YES && !active) { mNightMode = UiModeManager.MODE_NIGHT_NO; } updateConfigurationLocked(); sendConfigurationLocked(); return true; } finally { Binder.restoreCallingIdentity(ident); } } } }; void dumpImpl(PrintWriter pw) { Loading Loading @@ -772,6 +866,8 @@ final class UiModeManagerService extends SystemService { if (!mHoldingConfiguration) { mConfiguration.uiMode = uiMode; } // load splash screen instead of screenshot mWindowManager.clearSnapshotCache(); } private void sendConfigurationLocked() { Loading Loading @@ -1022,6 +1118,20 @@ final class UiModeManagerService extends SystemService { if (state != null) { mComputedNightMode = state.isNight(); } if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) { mComputedNightMode = true; return; } if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) { mComputedNightMode = false; return; } mNightModeOverride = mNightMode; final int user = UserHandle.getCallingUserId(); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); } } Loading Loading
core/java/android/app/IUiModeManager.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -68,4 +68,9 @@ interface IUiModeManager { * Tells if Night mode is locked or not. */ boolean isNightModeLocked(); /** * @hide */ boolean setNightModeActivated(boolean active); }
core/java/android/app/UiModeManager.java +14 −0 Original line number Diff line number Diff line Loading @@ -473,4 +473,18 @@ public class UiModeManager { } return true; } /** * @hide* */ public boolean setNightModeActivated(boolean active) { if (mService != null) { try { return mService.setNightModeActivated(active); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return false; } }
packages/SystemUI/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -916,6 +916,10 @@ <string name="quick_settings_ui_mode_night_label">Dark theme</string> <!-- QuickSettings: Label for the dark theme tile when enabled by battery saver. [CHAR LIMIT=40] --> <string name="quick_settings_ui_mode_night_label_battery_saver">Dark theme\nBattery saver</string> <!-- QuickSettings: Secondary text for when the Dark Mode will be enabled at sunset. [CHAR LIMIT=20] --> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset">On at sunset</string> <!-- QuickSettings: Secondary text for when the Dark Mode will be on until sunrise. [CHAR LIMIT=20] --> <string name="quick_settings_dark_mode_secondary_label_until_sunrise">Until sunrise</string> <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] --> <string name="quick_settings_nfc_label">NFC</string> Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +15 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; import android.text.TextUtils; import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.R; Loading Loading @@ -79,24 +79,33 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements return; } boolean newState = !mState.value; mUiModeManager.setNightMode(newState ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO); mUiModeManager.setNightModeActivated(newState); refreshState(newState); } @Override protected void handleUpdateState(BooleanState state, Object arg) { int uiMode = mUiModeManager.getNightMode(); boolean powerSave = mBatteryController.isPowerSave(); boolean isAuto = uiMode == UiModeManager.MODE_NIGHT_AUTO; boolean nightMode = (mContext.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; if (isAuto) { state.secondaryLabel = mContext.getResources().getString(nightMode ? R.string.quick_settings_dark_mode_secondary_label_until_sunrise : R.string.quick_settings_dark_mode_secondary_label_on_at_sunset); } else { state.secondaryLabel = null; } state.value = nightMode; state.label = mContext.getString(powerSave ? R.string.quick_settings_ui_mode_night_label_battery_saver : R.string.quick_settings_ui_mode_night_label); state.contentDescription = state.label; state.icon = mIcon; state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = TextUtils.isEmpty(state.secondaryLabel) ? state.label : TextUtils.concat(state.label, ", ", state.secondaryLabel); if (powerSave) { state.state = Tile.STATE_UNAVAILABLE; } else { Loading
services/core/java/com/android/server/UiModeManagerService.java +114 −4 Original line number Diff line number Diff line Loading @@ -56,8 +56,8 @@ import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; import android.util.ArraySet; import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.DisableCarModeActivity; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; Loading @@ -65,6 +65,7 @@ import com.android.internal.util.DumpUtils; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; import com.android.server.wm.WindowManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -72,6 +73,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import static android.content.Intent.ACTION_SCREEN_OFF; final class UiModeManagerService extends SystemService { private static final String TAG = UiModeManager.class.getSimpleName(); private static final boolean LOG = false; Loading @@ -85,6 +88,10 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mNightMode = UiModeManager.MODE_NIGHT_NO; // we use the override auto mode // for example: force night mode off in the night time while in auto mode private int mNightModeOverride = mNightMode; protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE + "_override"; private Map<Integer, String> mCarModePackagePriority = new HashMap<>(); private boolean mCarModeEnabled = false; Loading Loading @@ -119,6 +126,7 @@ final class UiModeManagerService extends SystemService { private TwilightManager mTwilightManager; private NotificationManager mNotificationManager; private StatusBarManager mStatusBarManager; private WindowManagerInternal mWindowManager; private PowerManager.WakeLock mWakeLock; Loading @@ -128,6 +136,17 @@ final class UiModeManagerService extends SystemService { super(context); } @VisibleForTesting protected UiModeManagerService(Context context, WindowManagerInternal wm, PowerManager.WakeLock wl, TwilightManager tm, boolean setupWizardComplete) { super(context); mWindowManager = wm; mWakeLock = wl; mTwilightManager = tm; mSetupWizardComplete = setupWizardComplete; } private static Intent buildHomeIntent(String category) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(category); Loading Loading @@ -189,8 +208,23 @@ final class UiModeManagerService extends SystemService { public void onTwilightStateChanged(@Nullable TwilightState state) { synchronized (mLock) { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { updateComputedNightModeLocked(); final IntentFilter intentFilter = new IntentFilter(ACTION_SCREEN_OFF); getContext().registerReceiver(mOnScreenOffHandler, intentFilter); } } } }; private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { updateLocked(0, 0); try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { // we ignore this exception if the receiver is unregistered already. } } } Loading Loading @@ -229,6 +263,8 @@ final class UiModeManagerService extends SystemService { public void onChange(boolean selfChange, Uri uri) { int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mNightMode, 0); mode = mode == UiModeManager.MODE_NIGHT_AUTO ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode)); } }; Loading @@ -247,6 +283,7 @@ final class UiModeManagerService extends SystemService { final PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); mWindowManager = LocalServices.getService(WindowManagerInternal.class); // If setup isn't complete for this user listen for completion so we can unblock // being able to send a night mode configuration change event Loading Loading @@ -313,6 +350,16 @@ final class UiModeManagerService extends SystemService { false, mDarkThemeObserver, 0); } @VisibleForTesting protected IUiModeManager getService() { return mService; } @VisibleForTesting protected Configuration getConfiguration() { return mConfiguration; } // Records whether setup wizard has happened or not and adds an observer for this user if not. private void verifySetupWizardCompleted() { final Context context = getContext(); Loading Loading @@ -347,8 +394,11 @@ final class UiModeManagerService extends SystemService { if (mSetupWizardComplete) { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); mNightModeOverride = Secure.getIntForUser(context.getContentResolver(), OVERRIDE_NIGHT_MODE, defaultNightMode, userId); } else { mNightMode = defaultNightMode; mNightModeOverride = defaultNightMode; } return oldNightMode != mNightMode; Loading Loading @@ -474,14 +524,30 @@ final class UiModeManagerService extends SystemService { try { synchronized (mLock) { if (mNightMode != mode) { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { // we ignore this exception if the receiver is unregistered already. } } // Only persist setting if not in car mode if (!mCarModeEnabled) { Secure.putIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mode, user); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); } mNightMode = mode; mNightModeOverride = mode; //on screen off will update configuration instead if (mNightMode != UiModeManager.MODE_NIGHT_AUTO) { updateLocked(0, 0); } else { getContext().registerReceiver( mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF)); } } } } finally { Loading Loading @@ -521,6 +587,34 @@ final class UiModeManagerService extends SystemService { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; dumpImpl(pw); } @Override public boolean setNightModeActivated(boolean active) { synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { try { getContext().unregisterReceiver(mOnScreenOffHandler); } catch (IllegalArgumentException e) { } mNightModeOverride = active ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; } else if (mNightMode == UiModeManager.MODE_NIGHT_NO && active) { mNightMode = UiModeManager.MODE_NIGHT_YES; } else if (mNightMode == UiModeManager.MODE_NIGHT_YES && !active) { mNightMode = UiModeManager.MODE_NIGHT_NO; } updateConfigurationLocked(); sendConfigurationLocked(); return true; } finally { Binder.restoreCallingIdentity(ident); } } } }; void dumpImpl(PrintWriter pw) { Loading Loading @@ -772,6 +866,8 @@ final class UiModeManagerService extends SystemService { if (!mHoldingConfiguration) { mConfiguration.uiMode = uiMode; } // load splash screen instead of screenshot mWindowManager.clearSnapshotCache(); } private void sendConfigurationLocked() { Loading Loading @@ -1022,6 +1118,20 @@ final class UiModeManagerService extends SystemService { if (state != null) { mComputedNightMode = state.isNight(); } if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) { mComputedNightMode = true; return; } if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) { mComputedNightMode = false; return; } mNightModeOverride = mNightMode; final int user = UserHandle.getCallingUserId(); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); } } Loading