Add support for user-selectable dark/light theme

Updates Settings to use the DayNight theme (real name TBD) and fixes
several colors that were pinned to non-theme values. Adds a setting for
switching theme between light/dark/auto.

Bug: 19368658
Bug: 19369392
Change-Id: I7cd23b7ad38bdb25a01b92e67ff1ee1cdd8a3958
diff --git a/res/drawable/preference_background.xml b/res/drawable/preference_background.xml
index 7f7b560..12bdea8 100644
--- a/res/drawable/preference_background.xml
+++ b/res/drawable/preference_background.xml
@@ -14,9 +14,5 @@
      limitations under the License.
 -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:inset="0dip">
-
-    <color android:color="?android:attr/colorBackground" />
-
-</inset>
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+       android:color="?android:attr/colorBackground" />
diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
index 01afa5d..bee063e 100644
--- a/res/layout/dashboard_category.xml
+++ b/res/layout/dashboard_category.xml
@@ -21,7 +21,7 @@
         android:paddingStart="@dimen/dashboard_category_padding_start"
         android:paddingEnd="@dimen/dashboard_category_padding_end"
         android:orientation="vertical"
-        android:background="@android:color/white"
+        android:background="@color/card_background"
         android:layout_marginBottom="8dip"
         android:elevation="@dimen/dashboard_category_elevation">
 
diff --git a/res/layout/settings_main_dashboard.xml b/res/layout/settings_main_dashboard.xml
index 56f2737..36c8aa2 100644
--- a/res/layout/settings_main_dashboard.xml
+++ b/res/layout/settings_main_dashboard.xml
@@ -21,5 +21,5 @@
              android:id="@+id/main_content"
              android:layout_height="match_parent"
              android:layout_width="match_parent"
-             android:background="@color/dashboard_background_color"
+             android:background="?android:attr/colorBackground"
              />
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
new file mode 100644
index 0000000..81d7347
--- /dev/null
+++ b/res/values-night/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="card_background">#ff424242</color>
+</resources>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index b542d3b..a0afbc3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1288,4 +1288,26 @@
         <item>midi</item>
     </string-array>
 
+    <!-- Possible values for user theme in Display Settings.
+         Do not translate. -->
+    <string-array name="night_mode_entries" translatable="false">
+        <!-- Do not translate. -->
+        <item>@string/night_mode_no</item>
+        <!-- Do not translate. -->
+        <item>@string/night_mode_yes</item>
+        <!-- Do not translate. -->
+        <item>@string/night_mode_auto</item>
+    </string-array>
+
+    <!-- These values should match up with the MODE_NIGHT constants in UiModeManager.
+         Do not translate. -->
+    <string-array name="night_mode_values" translatable="false">
+        <!-- Do not translate. -->
+        <item>1</item>
+        <!-- Do not translate. -->
+        <item>2</item>
+        <!-- Do not translate. -->
+        <item>0</item>
+    </string-array>
+
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9e374e6..6f97f40 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -64,12 +64,13 @@
     <color name="running_processes_apps_ram">#ff009587</color>
     <color name="running_processes_free_ram">#ffced7db</color>
 
+    <color name="card_background">#ffffffff</color>
+
     <!-- Palette colors referenced by top-level themes. -->
     <color name="theme_primary">#ff263238</color>
     <color name="theme_primary_dark">#ff21272b</color>
     <color name="theme_accent">#ff009688</color>
 
-    <color name="dashboard_background_color">#ffe1e1e0</color>
     <color name="switchbar_background_color">#ff37474f</color>
     <color name="switch_accent_color">#ff7fcac3</color>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ee02364..6e560c1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1889,6 +1889,16 @@
     <string name="auto_brightness_title">Adaptive brightness</string>
     <!-- Sound & display settings screen, setting option summary to enable adaptive brightness [CHAR LIMIT=100] -->
     <string name="auto_brightness_summary">Optimize brightness level for available light</string>
+    <!-- Sound & display settings screen, setting option name to change the user interface theme [CHAR LIMIT=30] -->
+    <string name="night_mode_title">Theme</string>
+    <!-- Sound & display settings screen, setting option summary to change the user interface theme [CHAR LIMIT=100] -->
+    <string name="night_mode_summary">%s</string>
+    <!-- Sound & display settings screen, theme setting value to prefer a light-colored user interface [CHAR LIMIT=30] -->
+    <string name="night_mode_no">Light</string>
+    <!-- Sound & display settings screen, theme setting value to prefer a dark-colored user interface [CHAR LIMIT=30] -->
+    <string name="night_mode_yes">Dark</string>
+    <!-- Sound & display settings screen, theme setting value to automatically switch between a light- or dark-colored user interface [CHAR LIMIT=30] -->
+    <string name="night_mode_auto">Automatic</string>
     <!-- Sound & display settings screen, setting option name to change screen timeout -->
     <string name="screen_timeout">Sleep</string>
     <!-- Sound & display settings screen, setting option name to change screen timeout [CHAR LIMIT=30] -->
@@ -5484,7 +5494,8 @@
     <string name="keywords_display">screen touchscreen</string>
     <string name="keywords_display_brightness_level">dim screen touchscreen battery</string>
     <string name="keywords_display_auto_brightness">dim screen touchscreen battery</string>
-    <string name="keywords_display_wallpaper">background personalize customize diplay</string>
+    <string name="keywords_display_night_mode">dark theme night mode dim screen invert brightness</string>
+    <string name="keywords_display_wallpaper">background personalize customize display</string>
     <string name="keywords_display_font_size">text size</string>
     <string name="keywords_display_cast_screen">project</string>
     <string name="keywords_storage">space disk hard drive device usage</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 83d02d6..82f447f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -351,8 +351,4 @@
 
     <style name="TextAppearance.ResultTitle" parent="TextAppearance.CategoryTitle">
     </style>
-
-    <style name="Widget.TimePicker" parent="@*android:style/Widget.Material.Light.TimePicker">
-        <item name="@android:numbersBackgroundColor">@android:color/white</item>
-    </style>
 </resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 4fa0c9f..b569004 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -137,9 +137,6 @@
         <item name="@*android:regularColor">@color/lock_pattern_view_regular_color</item>
         <item name="@*android:successColor">@color/lock_pattern_view_success_color</item>
         <item name="@*android:errorColor">@color/lock_pattern_view_error_color</item>
-
-        <!-- For the TimePicker -->
-        <item name="@android:timePickerStyle">@style/Widget.TimePicker</item>
     </style>
 
     <style name="Theme.SubSettings" parent="Theme.Settings">
@@ -149,7 +146,7 @@
         <item name="switchBarTheme">@style/Theme.SwitchBar.SubSettings</item>
     </style>
 
-    <style name="Theme.ActionBar" parent="@android:style/Widget.Material.Light.ActionBar.Solid">
+    <style name="Theme.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid">
         <item name="android:contentInsetStart">@dimen/actionbar_contentInsetStart</item>
     </style>
 
@@ -157,27 +154,17 @@
         <item name="android:contentInsetStart">@dimen/actionbar_subsettings_contentInsetStart</item>
     </style>
 
-    <style name="Theme.SwitchBar.Settings" parent="@android:style/Theme.Material">
+    <style name="Theme.SwitchBar.Settings" parent="@android:style/Theme.Material.Settings">
         <item name="switchBarMarginStart">@dimen/switchbar_margin_start</item>
         <item name="switchBarMarginEnd">@dimen/switchbar_margin_end</item>
     </style>
 
-    <style name="Theme.SwitchBar.SubSettings" parent="@android:style/Theme.Material">
+    <style name="Theme.SwitchBar.SubSettings" parent="@android:style/Theme.Material.Settings">
         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
     </style>
 
-    <style name="Theme.DialogWhenLarge" parent="@android:style/Theme.Material.Light.DialogWhenLarge">
-        <!-- Explicitly override the background color. -->
-        <item name="android:colorBackground">@android:color/white</item>
-
-        <!-- Used by the ActionBar -->
-        <item name="android:colorPrimary">@color/theme_primary</item>
-        <!-- Used by the StatusBar -->
-        <item name="android:colorPrimaryDark">@color/theme_primary_dark</item>
-        <!-- Used by controls, e.g. CheckBox, ProgressBar, etc. -->
-        <item name="android:colorAccent">@color/theme_accent</item>
-
+    <style name="Theme.DialogWhenLarge" parent="@android:style/Theme.Material.DayNight.DialogWhenLarge">
         <!-- Redefine the ActionBar style for contentInsetStart -->
         <item name="android:actionBarStyle">@style/Theme.ActionBar</item>
 
@@ -203,19 +190,9 @@
         <item name="preferenceBackgroundColor">@drawable/preference_background</item>
     </style>
 
-    <style name="Theme.AlertDialog" parent="@*android:style/Theme.Material.Light.Dialog.Alert">
+    <style name="Theme.AlertDialog" parent="@*android:style/Theme.Material.DayNight.Dialog.Alert">
         <item name="android:windowSoftInputMode">adjustResize</item>
 
-        <!-- Explicitly override the background color. -->
-        <item name="android:colorBackground">@android:color/white</item>
-
-        <!-- Used by the ActionBar -->
-        <item name="android:colorPrimary">@color/theme_primary</item>
-        <!-- Used by the StatusBar -->
-        <item name="android:colorPrimaryDark">@color/theme_primary_dark</item>
-        <!-- Used by controls, e.g. CheckBox, ProgressBar, etc. -->
-        <item name="android:colorAccent">@color/theme_accent</item>
-
         <!-- Redefine the ActionBar style for contentInsetStart -->
         <item name="android:actionBarStyle">@style/Theme.ActionBar</item>
     </style>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 6cfad2d..db650f3 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -33,6 +33,15 @@
                 android:summary="@string/auto_brightness_summary"
                 android:persistent="false" />
 
+        <ListPreference
+            android:key="night_mode"
+            android:title="@string/night_mode_title"
+            settings:keywords="@string/keywords_display_night_mode"
+            android:summary="@string/night_mode_summary"
+            android:persistent="false"
+            android:entries="@array/night_mode_entries"
+            android:entryValues="@array/night_mode_values" />
+
         <PreferenceScreen
                 android:key="wallpaper"
                 android:title="@string/wallpaper_settings_title"
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index ddd6728..337ec23 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -32,6 +32,7 @@
 import android.app.Activity;
 import android.app.ActivityManagerNative;
 import android.app.Dialog;
+import android.app.UiModeManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -70,6 +71,7 @@
     private static final String KEY_DOZE = "doze";
     private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
     private static final String KEY_AUTO_ROTATE = "auto_rotate";
+    private static final String KEY_NIGHT_MODE = "night_mode";
 
     private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
 
@@ -78,6 +80,7 @@
     private final Configuration mCurConfig = new Configuration();
 
     private ListPreference mScreenTimeoutPreference;
+    private ListPreference mNightModePreference;
     private Preference mScreenSaverPreference;
     private SwitchPreference mLiftToWakePreference;
     private SwitchPreference mDozePreference;
@@ -165,6 +168,13 @@
         } else {
             removePreference(KEY_AUTO_ROTATE);
         }
+
+        mNightModePreference = (ListPreference) findPreference(KEY_NIGHT_MODE);
+        final UiModeManager uiManager = (UiModeManager) getSystemService(
+                Context.UI_MODE_SERVICE);
+        final int currentNightMode = uiManager.getNightMode();
+        mNightModePreference.setValue(String.valueOf(currentNightMode));
+        mNightModePreference.setOnPreferenceChangeListener(this);
     }
 
     private static boolean allowAllRotations(Context context) {
@@ -381,6 +391,16 @@
             boolean value = (Boolean) objValue;
             Settings.Secure.putInt(getContentResolver(), DOZE_ENABLED, value ? 1 : 0);
         }
+        if (preference == mNightModePreference) {
+            try {
+                final int value = Integer.parseInt((String) objValue);
+                final UiModeManager uiManager = (UiModeManager) getSystemService(
+                        Context.UI_MODE_SERVICE);
+                uiManager.setNightMode(value);
+            } catch (NumberFormatException e) {
+                Log.e(TAG, "could not persist night mode setting", e);
+            }
+        }
         return true;
     }