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);
-
}
}