diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ad8d553137951..165c2843301c8 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -647,6 +647,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 9fe9703e41816..d79e38332af5f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -92,7 +92,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); @@ -123,7 +123,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 b1e2c0fe9586a..a4a6f23fc8943 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -56,6 +56,7 @@ 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; @@ -73,7 +74,6 @@ 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(); @@ -97,6 +97,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; @@ -208,24 +212,23 @@ final class UiModeManagerService extends SystemService { public void onTwilightStateChanged(@Nullable TwilightState state) { synchronized (mLock) { if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) { - 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. - } } } }; @@ -335,7 +338,7 @@ final class UiModeManagerService extends SystemService { SystemServerInitThreadPool.submit(() -> { synchronized (mLock) { updateConfigurationLocked(); - sendConfigurationLocked(); + applyConfigurationExternallyLocked(); } }, TAG + ".onStart"); @@ -404,6 +407,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(@UiModeManager.EnableCarMode int flags, @@ -525,11 +544,7 @@ 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. - } + unregisterScreenOffEvent(); } // Only persist setting if not in car mode if (!mCarModeEnabled) { @@ -541,12 +556,11 @@ final class UiModeManagerService extends SystemService { mNightMode = mode; mNightModeOverride = mode; - //on screen off will update configuration instead + // 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)); + registerScreenOffEvent(); } } } @@ -594,10 +608,7 @@ final class UiModeManagerService extends SystemService { 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 @@ -608,7 +619,7 @@ final class UiModeManagerService extends SystemService { mNightMode = UiModeManager.MODE_NIGHT_NO; } updateConfigurationLocked(); - sendConfigurationLocked(); + applyConfigurationExternallyLocked(); return true; } finally { Binder.restoreCallingIdentity(ident); @@ -863,12 +874,12 @@ 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; // load splash screen instead of screenshot @@ -1052,7 +1063,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) { @@ -1130,7 +1141,6 @@ final class UiModeManagerService extends SystemService { final int user = UserHandle.getCallingUserId(); Secure.putIntForUser(getContext().getContentResolver(), OVERRIDE_NIGHT_MODE, mNightModeOverride, user); - } }