diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 75b40fd489f22..7c5a1fb5f787a 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7762,6 +7762,9 @@ public final class Settings { */ public static final String UI_NIGHT_MODE = "ui_night_mode"; + private static final Validator UI_NIGHT_MODE_VALIDATOR = + new SettingsValidators.InclusiveIntegerRangeValidator(0, 2); + /** * Whether screensavers are enabled. * @hide @@ -8908,6 +8911,7 @@ public final class Settings { ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NOTIFICATION_NEW_INTERRUPTION_MODEL, TRUST_AGENTS_EXTEND_UNLOCK, + UI_NIGHT_MODE, LOCK_SCREEN_WHEN_TRUST_LOST, SKIP_GESTURE, SILENCE_GESTURE, @@ -9101,6 +9105,7 @@ public final class Settings { VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR); VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR); + VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR); } /** diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 61fb8112dbfc4..e76754582fe91 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -695,7 +695,6 @@ public class SettingsBackupTest { Settings.Secure.TV_INPUT_CUSTOM_LABELS, Settings.Secure.TV_INPUT_HIDDEN_INPUTS, Settings.Secure.TV_USER_SETUP_COMPLETE, - Settings.Secure.UI_NIGHT_MODE, // candidate? Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 3a50aa8d74a01..0eb3a8438ae3b 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -33,6 +33,8 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; +import android.database.ContentObserver; +import android.net.Uri; import android.os.BatteryManager; import android.os.Binder; import android.os.Handler; @@ -45,7 +47,7 @@ import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; import android.os.UserHandle; -import android.provider.Settings; +import android.provider.Settings.Secure; import android.service.dreams.Sandman; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; @@ -87,6 +89,7 @@ final class UiModeManagerService extends SystemService { private boolean mVrHeadset; private boolean mComputedNightMode; private int mCarModeEnableFlags; + private boolean mSetupWizardComplete; // flag set by resource, whether to enable Car dock launch when starting car mode. private boolean mEnableCarDockLaunch = true; @@ -196,6 +199,29 @@ final class UiModeManagerService extends SystemService { } }; + private final ContentObserver mSetupWizardObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + // setup wizard is done now so we can unblock + if (setupWizardCompleteForCurrentUser()) { + mSetupWizardComplete = true; + getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver); + // update night mode + Context context = getContext(); + updateNightModeFromSettings(context, context.getResources(), + UserHandle.getCallingUserId()); + updateLocked(0, 0); + } + } + }; + + @Override + public void onSwitchUser(int userHandle) { + super.onSwitchUser(userHandle); + getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver); + verifySetupWizardCompleted(); + } + @Override public void onStart() { final Context context = getContext(); @@ -204,6 +230,10 @@ final class UiModeManagerService extends SystemService { (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); + // 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 + verifySetupWizardCompleted(); + context.registerReceiver(mDockModeReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT)); IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); @@ -262,6 +292,25 @@ final class UiModeManagerService extends SystemService { context.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler); } + // Records whether setup wizard has happened or not and adds an observer for this user if not. + private void verifySetupWizardCompleted() { + final Context context = getContext(); + final int userId = UserHandle.getCallingUserId(); + if (!setupWizardCompleteForCurrentUser()) { + mSetupWizardComplete = false; + context.getContentResolver().registerContentObserver( + Secure.getUriFor( + Secure.USER_SETUP_COMPLETE), false, mSetupWizardObserver, userId); + } else { + mSetupWizardComplete = true; + } + } + + private boolean setupWizardCompleteForCurrentUser() { + return Secure.getIntForUser(getContext().getContentResolver(), + Secure.USER_SETUP_COMPLETE, 0, UserHandle.getCallingUserId()) == 1; + } + /** * Updates the night mode setting in Settings.Global and returns if the value was successfully * changed. @@ -274,8 +323,12 @@ final class UiModeManagerService extends SystemService { final int defaultNightMode = res.getInteger( com.android.internal.R.integer.config_defaultNightMode); int oldNightMode = mNightMode; - mNightMode = Settings.Secure.getIntForUser(context.getContentResolver(), - Settings.Secure.UI_NIGHT_MODE, defaultNightMode, userId); + if (mSetupWizardComplete) { + mNightMode = Secure.getIntForUser(context.getContentResolver(), + Secure.UI_NIGHT_MODE, defaultNightMode, userId); + } else { + mNightMode = defaultNightMode; + } // false if night mode stayed the same, true otherwise. return !(oldNightMode == mNightMode); @@ -340,6 +393,10 @@ final class UiModeManagerService extends SystemService { Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission"); return; } + if (!mSetupWizardComplete) { + Slog.d(TAG, "Night mode cannot be changed before setup wizard completes."); + return; + } switch (mode) { case UiModeManager.MODE_NIGHT_NO: case UiModeManager.MODE_NIGHT_YES: @@ -356,8 +413,8 @@ final class UiModeManagerService extends SystemService { if (mNightMode != mode) { // Only persist setting if not in car mode if (!mCarModeEnabled) { - Settings.Secure.putIntForUser(getContext().getContentResolver(), - Settings.Secure.UI_NIGHT_MODE, mode, user); + Secure.putIntForUser(getContext().getContentResolver(), + Secure.UI_NIGHT_MODE, mode, user); } mNightMode = mode;