Add support for user-selectable night mode

Adds a Material theme that automatically selects light or dark UI based
on the night mode resource qualifier.

Removes restriction that night mode only works when car mode is enabled
or the device is docked, which was applied inconsistently anyway and
only actually worked when in car mode (regardless of docked state).
Night mode is now always applied according to the system preference.

Change-Id: I526807c907eb29a2ab588d15932afe3e6ab180c2
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index d1b4569..aeacd45 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -31,6 +31,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Handler;
@@ -63,7 +64,7 @@
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
     private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-    int mNightMode = UiModeManager.MODE_NIGHT_NO;
+    private int mNightMode = UiModeManager.MODE_NIGHT_NO;
 
     private boolean mCarModeEnabled = false;
     private boolean mCharging = false;
@@ -157,6 +158,7 @@
     public void onStart() {
         final Context context = getContext();
         mTwilightManager = getLocalService(TwilightManager.class);
+
         final PowerManager powerManager =
                 (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
@@ -168,20 +170,23 @@
 
         mConfiguration.setToDefaults();
 
-        mDefaultUiModeType = context.getResources().getInteger(
+        final Resources res = context.getResources();
+        mDefaultUiModeType = res.getInteger(
                 com.android.internal.R.integer.config_defaultUiModeType);
-        mCarModeKeepsScreenOn = (context.getResources().getInteger(
+        mCarModeKeepsScreenOn = (res.getInteger(
                 com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
-        mDeskModeKeepsScreenOn = (context.getResources().getInteger(
+        mDeskModeKeepsScreenOn = (res.getInteger(
                 com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
-        mTelevision = context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_TELEVISION) ||
-            context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_LEANBACK);
-        mWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
 
+        final PackageManager pm = context.getPackageManager();
+        mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+                || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+
+        final int defaultNightMode = res.getInteger(
+                com.android.internal.R.integer.config_defaultNightMode);
         mNightMode = Settings.Secure.getInt(context.getContentResolver(),
-                Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
+                Settings.Secure.UI_NIGHT_MODE, defaultNightMode);
 
         mTwilightManager.registerListener(mTwilightListener, mHandler);
 
@@ -245,7 +250,7 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    if (isDoingNightModeLocked() && mNightMode != mode) {
+                    if (mNightMode != mode) {
                         Settings.Secure.putInt(getContext().getContentResolver(),
                                 Settings.Secure.UI_NIGHT_MODE, mode);
                         mNightMode = mode;
@@ -309,10 +314,6 @@
         }
     }
 
-    boolean isDoingNightModeLocked() {
-        return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
-    }
-
     void setCarModeLocked(boolean enabled, int flags) {
         if (mCarModeEnabled != enabled) {
             mCarModeEnabled = enabled;
@@ -354,17 +355,13 @@
         } else if (isDeskDockState(mDockState)) {
             uiMode = Configuration.UI_MODE_TYPE_DESK;
         }
-        if (mCarModeEnabled) {
-            if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                updateComputedNightModeLocked();
-                uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
-                        : Configuration.UI_MODE_NIGHT_NO;
-            } else {
-                uiMode |= mNightMode << 4;
-            }
+
+        if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+            updateComputedNightModeLocked();
+            uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
+                    : Configuration.UI_MODE_NIGHT_NO;
         } else {
-            // Disabling the car mode clears the night mode.
-            uiMode = (uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | Configuration.UI_MODE_NIGHT_NO;
+            uiMode |= mNightMode << 4;
         }
 
         if (LOG) {
@@ -618,7 +615,7 @@
 
     void updateTwilight() {
         synchronized (mLock) {
-            if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+            if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
                 updateComputedNightModeLocked();
                 updateLocked(0, 0);
             }