diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b9f5348027e6e..495b37cb5944d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -660,6 +660,22 @@ public final class Settings { public static final String ACTION_NIGHT_DISPLAY_SETTINGS = "android.settings.NIGHT_DISPLAY_SETTINGS"; + /** + * Activity Action: Show settings to allow configuration of Dark theme. + *

+ * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + *

+ * Input: Nothing. + *

+ * Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_DARK_THEME_SETTINGS = + "android.settings.DARK_THEME_SETTINGS"; + /** * Activity Action: Show settings to allow configuration of locale. *

diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index dc9a2ce1beef5..54fbaf3617459 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -91,7 +91,7 @@ public class UiModeNightTile extends QSTileImpl implements boolean nightMode = (mContext.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; - if (isAuto) { + if (isAuto && !powerSave) { 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); @@ -121,7 +121,7 @@ public class UiModeNightTile extends QSTileImpl implements @Override public Intent getLongClickIntent() { - return new Intent(Settings.ACTION_DISPLAY_SETTINGS); + return new Intent(Settings.ACTION_DARK_THEME_SETTINGS); } @Override diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 7215389055218..978cc577f1eb0 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -16,8 +16,6 @@ package com.android.server; -import static android.content.Intent.ACTION_SCREEN_OFF; - import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; @@ -91,6 +89,10 @@ final class UiModeManagerService extends SystemService { private boolean mCarModeEnabled = false; private boolean mCharging = false; private boolean mPowerSave = false; + // Do not change configuration now. wait until screen turns off. + // This prevents jank and activity restart when the user + // is actively using the device + private boolean mWaitForScreenOff = false; private int mDefaultUiModeType; private boolean mCarModeKeepsScreenOn; private boolean mDeskModeKeepsScreenOn; @@ -206,25 +208,24 @@ final class UiModeManagerService extends SystemService { if (mCar) { updateLocked(0, 0); } else { - final IntentFilter intentFilter = - new IntentFilter(ACTION_SCREEN_OFF); - getContext().registerReceiver(mOnScreenOffHandler, intentFilter); + registerScreenOffEvent(); } } } } }; + /** + * DO NOT USE DIRECTLY + * see register registerScreenOffEvent and unregisterScreenOffEvent + */ private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { + // must unregister first before updating + unregisterScreenOffEvent(); updateLocked(0, 0); - try { - getContext().unregisterReceiver(mOnScreenOffHandler); - } catch (IllegalArgumentException e) { - // we ignore this exception if the receiver is unregistered already. - } } } }; @@ -263,7 +264,7 @@ final class UiModeManagerService extends SystemService { 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; + ? UiModeManager.MODE_NIGHT_YES : mode; SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode)); } }; @@ -335,7 +336,7 @@ final class UiModeManagerService extends SystemService { SystemServerInitThreadPool.get().submit(() -> { synchronized (mLock) { updateConfigurationLocked(); - sendConfigurationLocked(); + applyConfigurationExternallyLocked(); } }, TAG + ".onStart"); @@ -404,6 +405,22 @@ final class UiModeManagerService extends SystemService { return oldNightMode != mNightMode; } + private void registerScreenOffEvent() { + mWaitForScreenOff = true; + final IntentFilter intentFilter = + new IntentFilter(Intent.ACTION_SCREEN_OFF); + getContext().registerReceiver(mOnScreenOffHandler, intentFilter); + } + + private void unregisterScreenOffEvent() { + mWaitForScreenOff = false; + try { + getContext().unregisterReceiver(mOnScreenOffHandler); + } catch (IllegalArgumentException e) { + // we ignore this exception if the receiver is unregistered already. + } + } + private final IUiModeManager.Stub mService = new IUiModeManager.Stub() { @Override public void enableCarMode(int flags) { @@ -482,28 +499,21 @@ final class UiModeManagerService extends SystemService { 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); + unregisterScreenOffEvent(); } mNightMode = mode; mNightModeOverride = mode; - //on screen off will update configuration instead + + // Only persist setting if not in car mode + if (!mCarModeEnabled) { + persistNightMode(user); + } + // on screen off will update configuration instead if (mNightMode != UiModeManager.MODE_NIGHT_AUTO || mCar) { updateLocked(0, 0); } else { - getContext().registerReceiver( - mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF)); + registerScreenOffEvent(); } } } @@ -548,13 +558,11 @@ final class UiModeManagerService extends SystemService { @Override public boolean setNightModeActivated(boolean active) { synchronized (mLock) { + final int user = UserHandle.getCallingUserId(); final long ident = Binder.clearCallingIdentity(); try { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { - try { - getContext().unregisterReceiver(mOnScreenOffHandler); - } catch (IllegalArgumentException e) { - } + unregisterScreenOffEvent(); mNightModeOverride = active ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; } else if (mNightMode == UiModeManager.MODE_NIGHT_NO @@ -565,7 +573,8 @@ final class UiModeManagerService extends SystemService { mNightMode = UiModeManager.MODE_NIGHT_NO; } updateConfigurationLocked(); - sendConfigurationLocked(); + applyConfigurationExternallyLocked(); + persistNightMode(user); return true; } finally { Binder.restoreCallingIdentity(ident); @@ -651,6 +660,13 @@ final class UiModeManagerService extends SystemService { } } + private void persistNightMode(int user) { + Secure.putIntForUser(getContext().getContentResolver(), + Secure.UI_NIGHT_MODE, mNightMode, user); + Secure.putIntForUser(getContext().getContentResolver(), + OVERRIDE_NIGHT_MODE, mNightModeOverride, user); + } + private void updateConfigurationLocked() { int uiMode = mDefaultUiModeType; if (mUiModeLocked) { @@ -696,15 +712,14 @@ final class UiModeManagerService extends SystemService { } mCurUiMode = uiMode; - if (!mHoldingConfiguration) { + if (!mHoldingConfiguration || !mWaitForScreenOff) { mConfiguration.uiMode = uiMode; } } - private void sendConfigurationLocked() { + private void applyConfigurationExternallyLocked() { if (mSetUiMode != mConfiguration.uiMode) { mSetUiMode = mConfiguration.uiMode; - try { ActivityTaskManager.getService().updateConfiguration(mConfiguration); } catch (RemoteException e) { @@ -884,7 +899,7 @@ final class UiModeManagerService extends SystemService { } // Send the new configuration. - sendConfigurationLocked(); + applyConfigurationExternallyLocked(); // If we did not start a dock app, then start dreaming if supported. if (category != null && !dockAppStarted) { @@ -962,7 +977,6 @@ final class UiModeManagerService extends SystemService { final int user = UserHandle.getCallingUserId(); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); - } }