From c500b2741e31ce52356ff66e3b4943a98ae3ff8c Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Thu, 2 May 2019 14:32:12 -0700 Subject: [PATCH] Prevent dark mode backup from applying in before setup This CL makes it so that UIModeManager will not allow dark mode to be changed prior to initial setup wizard being completed. Additionally, it makes it so that when UIModeManager starts it will try to start in light mode prior to setup wizard completing regardless of what the backed up value is. We also register for an observer if when we start UIModeManager we notice that setup wizard has not run and defer updating dark mode to the true value until we see that setup wizard completes. Test: Manual Bug: 119666724 Change-Id: Ie9cf36c8483d9cdd9e7aadd3aae4cc0ef15e8d45 --- core/java/android/provider/Settings.java | 5 ++ .../android/provider/SettingsBackupTest.java | 1 - .../android/server/UiModeManagerService.java | 67 +++++++++++++++++-- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ced6115a2f2af..7183b13419ee2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7710,6 +7710,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 @@ -8856,6 +8859,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, @@ -9049,6 +9053,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 f4d3c8163e9ce..922857726e530 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -693,7 +693,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;