Merge "Add free space precondition check for copy job."
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 3917bfa..145b1d0 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -267,6 +267,10 @@
      * @param cameraId The unique identifier of the camera device to open
      * @param callback The callback for the camera. Must not be null.
      * @param handler  The handler to invoke the callback on. Must not be null.
+     * @param uid      The UID of the application actually opening the camera.
+     *                 Must be USE_CALLING_UID unless the caller is a service
+     *                 that is trusted to open the device on behalf of an
+     *                 application and to forward the real UID.
      *
      * @throws CameraAccessException if the camera is disabled by device policy,
      * too many camera devices are already open, or the cameraId does not match
@@ -281,7 +285,7 @@
      * @see android.app.admin.DevicePolicyManager#setCameraDisabled
      */
     private CameraDevice openCameraDeviceUserAsync(String cameraId,
-            CameraDevice.StateCallback callback, Handler handler)
+            CameraDevice.StateCallback callback, Handler handler, final int uid)
             throws CameraAccessException {
         CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
         CameraDevice device = null;
@@ -317,7 +321,7 @@
                             "Camera service is currently unavailable");
                     }
                     cameraUser = cameraService.connectDevice(callbacks, id,
-                            mContext.getOpPackageName(), USE_CALLING_UID);
+                            mContext.getOpPackageName(), uid);
                 } else {
                     // Use legacy camera implementation for HAL1 devices
                     Log.i(TAG, "Using legacy camera HAL.");
@@ -434,6 +438,29 @@
             @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
             throws CameraAccessException {
 
+        openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
+    }
+
+    /**
+     * Open a connection to a camera with the given ID, on behalf of another application
+     * specified by clientUid.
+     *
+     * <p>The behavior of this method matches that of {@link #openCamera}, except that it allows
+     * the caller to specify the UID to use for permission/etc verification. This can only be
+     * done by services trusted by the camera subsystem to act on behalf of applications and
+     * to forward the real UID.</p>
+     *
+     * @param clientUid
+     *             The UID of the application on whose behalf the camera is being opened.
+     *             Must be USE_CALLING_UID unless the caller is a trusted service.
+     *
+     * @hide
+     */
+    public void openCameraForUid(@NonNull String cameraId,
+            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
+            int clientUid)
+            throws CameraAccessException {
+
         if (cameraId == null) {
             throw new IllegalArgumentException("cameraId was null");
         } else if (callback == null) {
@@ -447,7 +474,7 @@
             }
         }
 
-        openCameraDeviceUserAsync(cameraId, callback, handler);
+        openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 10bdb5f..f9810276 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6150,6 +6150,30 @@
                 "camera_double_tap_power_gesture_disabled";
 
         /**
+         * Control whether Night display is currently activated.
+         * @hide
+         */
+        public static final String NIGHT_DISPLAY_ACTIVATED = "night_display_activated";
+
+        /**
+         * Control whether Night display will automatically activate/deactivate.
+         * @hide
+         */
+        public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
+
+        /**
+         * Custom time when Night display is scheduled to activate.
+         * Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
+         * @hide
+         */
+        public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time";
+
+        /**
+         * Custom time when Night display is scheduled to deactivate.
+         * Represented as milliseconds from midnight (e.g. 21600000 == 6am).
+         * @hide
+         */
+        public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
 
         /**
          * Behavior of twilight on the device.
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
new file mode 100644
index 0000000..03cd729
--- /dev/null
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings.Secure;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Controller for managing Night display settings.
+ * <p/>
+ * Night display tints your screen red at night. This makes it easier to look at your screen in
+ * dim light and may help you fall asleep more easily.
+ */
+public final class NightDisplayController {
+
+    private static final String TAG = "NightDisplayController";
+    private static final boolean DEBUG = false;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM, AUTO_MODE_TWILIGHT })
+    public @interface AutoMode {}
+
+    /**
+     * Auto mode value to prevent Night display from being automatically activated. It can still
+     * be activated manually via {@link #setActivated(boolean)}.
+     *
+     * @see #setAutoMode(int)
+     */
+    public static final int AUTO_MODE_DISABLED = 0;
+    /**
+     * Auto mode value to automatically activate Night display at a specific start and end time.
+     *
+     * @see #setAutoMode(int)
+     * @see #setCustomStartTime(LocalTime)
+     * @see #setCustomEndTime(LocalTime)
+     */
+    public static final int AUTO_MODE_CUSTOM = 1;
+    /**
+     * Auto mode value to automatically activate Night display from sunset to sunrise.
+     *
+     * @see #setAutoMode(int)
+     */
+    public static final int AUTO_MODE_TWILIGHT = 2;
+
+    private final Context mContext;
+    private final int mUserId;
+
+    private final ContentObserver mContentObserver;
+
+    private Callback mCallback;
+
+    public NightDisplayController(@NonNull Context context) {
+        this(context, UserHandle.myUserId());
+    }
+
+    public NightDisplayController(@NonNull Context context, int userId) {
+        mContext = context.getApplicationContext();
+        mUserId = userId;
+
+        mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                super.onChange(selfChange, uri);
+
+                final String setting = uri == null ? null : uri.getLastPathSegment();
+                if (setting != null) {
+                    onSettingChanged(setting);
+                }
+            }
+        };
+    }
+
+    /**
+     * Returns {@code true} when Night display is activated (the display is tinted red).
+     */
+    public boolean isActivated() {
+        return Secure.getIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_ACTIVATED, 0, mUserId) == 1;
+    }
+
+    /**
+     * Sets whether Night display should be activated.
+     *
+     * @param activated {@code true} if Night display should be activated
+     * @return {@code true} if the activated value was set successfully
+     */
+    public boolean setActivated(boolean activated) {
+        return Secure.putIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId);
+    }
+
+    /**
+     * Returns the current auto mode value controlling when Night display will be automatically
+     * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
+     * {@link #AUTO_MODE_TWILIGHT}.
+     */
+    public @AutoMode int getAutoMode() {
+        int autoMode = Secure.getIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_AUTO_MODE, -1, mUserId);
+        if (autoMode == -1) {
+            if (DEBUG) {
+                Slog.d(TAG, "Using default value for setting: " + Secure.NIGHT_DISPLAY_AUTO_MODE);
+            }
+            autoMode = mContext.getResources().getInteger(
+                    R.integer.config_defaultNightDisplayAutoMode);
+        }
+
+        if (autoMode != AUTO_MODE_DISABLED
+                && autoMode != AUTO_MODE_CUSTOM
+                && autoMode != AUTO_MODE_TWILIGHT) {
+            Slog.e(TAG, "Invalid autoMode: " + autoMode);
+            autoMode = AUTO_MODE_DISABLED;
+        }
+
+        return autoMode;
+    }
+
+    /**
+     * Sets the current auto mode value controlling when Night display will be automatically
+     * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
+     * {@link #AUTO_MODE_TWILIGHT}.
+     *
+     * @param autoMode the new auto mode to use
+     * @return {@code true} if new auto mode was set successfully
+     */
+    public boolean setAutoMode(@AutoMode int autoMode) {
+        if (autoMode != AUTO_MODE_DISABLED
+                && autoMode != AUTO_MODE_CUSTOM
+                && autoMode != AUTO_MODE_TWILIGHT) {
+            throw new IllegalArgumentException("Invalid autoMode: " + autoMode);
+        }
+
+        return Secure.putIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
+    }
+
+    /**
+     * Returns the local time when Night display will be automatically activated when using
+     * {@link #AUTO_MODE_CUSTOM}.
+     */
+    public @NonNull LocalTime getCustomStartTime() {
+        int startTimeValue = Secure.getIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, -1, mUserId);
+        if (startTimeValue == -1) {
+            if (DEBUG) {
+                Slog.d(TAG, "Using default value for setting: "
+                        + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME);
+            }
+            startTimeValue = mContext.getResources().getInteger(
+                    R.integer.config_defaultNightDisplayCustomStartTime);
+        }
+
+        return LocalTime.valueOf(startTimeValue);
+    }
+
+    /**
+     * Sets the local time when Night display will be automatically activated when using
+     * {@link #AUTO_MODE_CUSTOM}.
+     *
+     * @param startTime the local time to automatically activate Night display
+     * @return {@code true} if the new custom start time was set successfully
+     */
+    public boolean setCustomStartTime(@NonNull LocalTime startTime) {
+        if (startTime == null) {
+            throw new IllegalArgumentException("startTime cannot be null");
+        }
+        return Secure.putIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId);
+    }
+
+    /**
+     * Returns the local time when Night display will be automatically deactivated when using
+     * {@link #AUTO_MODE_CUSTOM}.
+     */
+    public @NonNull LocalTime getCustomEndTime() {
+        int endTimeValue = Secure.getIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, -1, mUserId);
+        if (endTimeValue == -1) {
+            if (DEBUG) {
+                Slog.d(TAG, "Using default value for setting: "
+                        + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME);
+            }
+            endTimeValue = mContext.getResources().getInteger(
+                    R.integer.config_defaultNightDisplayCustomEndTime);
+        }
+
+        return LocalTime.valueOf(endTimeValue);
+    }
+
+    /**
+     * Sets the local time when Night display will be automatically deactivated when using
+     * {@link #AUTO_MODE_CUSTOM}.
+     *
+     * @param endTime the local time to automatically deactivate Night display
+     * @return {@code true} if the new custom end time was set successfully
+     */
+    public boolean setCustomEndTime(@NonNull LocalTime endTime) {
+        if (endTime == null) {
+            throw new IllegalArgumentException("endTime cannot be null");
+        }
+        return Secure.putIntForUser(mContext.getContentResolver(),
+                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId);
+    }
+
+    private void onSettingChanged(@NonNull String setting) {
+        if (DEBUG) {
+            Slog.d(TAG, "onSettingChanged: " + setting);
+        }
+
+        if (mCallback != null) {
+            switch (setting) {
+                case Secure.NIGHT_DISPLAY_ACTIVATED:
+                    mCallback.onActivated(isActivated());
+                    break;
+                case Secure.NIGHT_DISPLAY_AUTO_MODE:
+                    mCallback.onAutoModeChanged(getAutoMode());
+                    break;
+                case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME:
+                    mCallback.onCustomStartTimeChanged(getCustomStartTime());
+                    break;
+                case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME:
+                    mCallback.onCustomEndTimeChanged(getCustomEndTime());
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Register a callback to be invoked whenever the Night display settings are changed.
+     */
+    public void setListener(Callback callback) {
+        final Callback oldCallback = mCallback;
+        if (oldCallback != callback) {
+            mCallback = callback;
+
+            if (callback == null) {
+                // Stop listening for changes now that there IS NOT a listener.
+                mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+            } else if (oldCallback == null) {
+                // Start listening for changes now that there IS a listener.
+                final ContentResolver cr = mContext.getContentResolver();
+                cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED),
+                        false /* notifyForDescendants */, mContentObserver, mUserId);
+                cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE),
+                        false /* notifyForDescendants */, mContentObserver, mUserId);
+                cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME),
+                        false /* notifyForDescendants */, mContentObserver, mUserId);
+                cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME),
+                        false /* notifyForDescendants */, mContentObserver, mUserId);
+            }
+        }
+    }
+
+    /**
+     * Returns {@code true} if Night display is supported by the device.
+     */
+    public static boolean isAvailable(Context context) {
+        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
+    }
+
+    /**
+     * A time without a time-zone or date.
+     */
+    public static class LocalTime {
+
+        /**
+         * The hour of the day from 0 - 23.
+         */
+        public final int hourOfDay;
+        /**
+         * The minute within the hour from 0 - 59.
+         */
+        public final int minute;
+
+        public LocalTime(int hourOfDay, int minute) {
+            if (hourOfDay < 0 || hourOfDay > 23) {
+                throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay);
+            } else if (minute < 0 || minute > 59) {
+                throw new IllegalArgumentException("Invalid minute: " + minute);
+            }
+
+            this.hourOfDay = hourOfDay;
+            this.minute = minute;
+        }
+
+        /**
+         * Returns the first date time corresponding to this local time that occurs before the
+         * provided date time.
+         *
+         * @param time the date time to compare against
+         * @return the prior date time corresponding to this local time
+         */
+        public Calendar getDateTimeBefore(Calendar time) {
+            final Calendar c = Calendar.getInstance();
+            c.set(Calendar.YEAR, time.get(Calendar.YEAR));
+            c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
+
+            c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+            c.set(Calendar.MINUTE, minute);
+            c.set(Calendar.SECOND, 0);
+            c.set(Calendar.MILLISECOND, 0);
+
+            // Check if the local time has past, if so return the same time tomorrow.
+            if (c.after(time)) {
+                c.add(Calendar.DATE, -1);
+            }
+
+            return c;
+        }
+
+        /**
+         * Returns the first date time corresponding to this local time that occurs after the
+         * provided date time.
+         *
+         * @param time the date time to compare against
+         * @return the next date time corresponding to this local time
+         */
+        public Calendar getDateTimeAfter(Calendar time) {
+            final Calendar c = Calendar.getInstance();
+            c.set(Calendar.YEAR, time.get(Calendar.YEAR));
+            c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
+
+            c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+            c.set(Calendar.MINUTE, minute);
+            c.set(Calendar.SECOND, 0);
+            c.set(Calendar.MILLISECOND, 0);
+
+            // Check if the local time has past, if so return the same time tomorrow.
+            if (c.before(time)) {
+                c.add(Calendar.DATE, 1);
+            }
+
+            return c;
+        }
+
+        /**
+         * Returns a local time corresponding the given number of milliseconds from midnight.
+         *
+         * @param millis the number of milliseconds from midnight
+         * @return the corresponding local time
+         */
+        private static LocalTime valueOf(int millis) {
+            final int hourOfDay = (millis / 3600000) % 24;
+            final int minutes = (millis / 60000) % 60;
+            return new LocalTime(hourOfDay, minutes);
+        }
+
+        /**
+         * Returns the local time represented as milliseconds from midnight.
+         */
+        private int toMillis() {
+            return hourOfDay * 3600000 + minute * 60000;
+        }
+
+        @Override
+        public String toString() {
+            return String.format(Locale.US, "%02d:%02d", hourOfDay, minute);
+        }
+    }
+
+    /**
+     * Callback invoked whenever the Night display settings are changed.
+     */
+    public interface Callback {
+        /**
+         * Callback invoked when the activated state changes.
+         *
+         * @param activated {@code true} if Night display is activated
+         */
+        default void onActivated(boolean activated) {}
+        /**
+         * Callback invoked when the auto mode changes.
+         *
+         * @param autoMode the auto mode to use
+         */
+        default void onAutoModeChanged(int autoMode) {}
+        /**
+         * Callback invoked when the time to automatically activate Night display changes.
+         *
+         * @param startTime the local time to automatically activate Night display
+         */
+        default void onCustomStartTimeChanged(LocalTime startTime) {}
+        /**
+         * Callback invoked when the time to automatically deactivate Night display changes.
+         *
+         * @param endTime the local time to automatically deactivate Night display
+         */
+        default void onCustomEndTimeChanged(LocalTime endTime) {}
+    }
+}
diff --git a/core/res/res/layout-watch/preference_material.xml b/core/res/res/layout-watch/preference_material.xml
index 5da64fc..ad217db 100644
--- a/core/res/res/layout-watch/preference_material.xml
+++ b/core/res/res/layout-watch/preference_material.xml
@@ -29,34 +29,42 @@
 
     <LinearLayout
         android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="-4dp"
-        android:minWidth="32dp"
-        android:gravity="start|center_vertical"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:gravity="center"
         android:orientation="horizontal"
-        android:paddingEnd="8dp"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp">
+        android:layout_marginEnd="8dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp">
         <com.android.internal.widget.PreferenceImageView
             android:id="@+id/icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:maxWidth="24dp"
-            android:maxHeight="24dp" />
+            android:maxWidth="40dp"
+            android:maxHeight="40dp" />
     </LinearLayout>
 
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+id/widget_frame"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:gravity="center"
+        android:orientation="horizontal"
+        android:layout_marginEnd="8dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp" />
+
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingTop="16dp"
-        android:paddingBottom="16dp">
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp">
 
         <TextView android:id="@+id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:maxLines="2"
+            android:maxLines="3"
             android:textAppearance="?attr/textAppearanceListItem"
             android:ellipsize="end" />
 
@@ -70,13 +78,4 @@
             android:maxLines="10" />
 
     </RelativeLayout>
-
-    <!-- Preference should place its actual preference widget here. -->
-    <LinearLayout android:id="@+id/widget_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:gravity="end|center_vertical"
-        android:paddingStart="4dp"
-        android:orientation="vertical" />
-
 </LinearLayout>
diff --git a/core/res/res/values-round-watch/dimens_material.xml b/core/res/res/values-round-watch/dimens_material.xml
index a417d19..db1f1f3 100644
--- a/core/res/res/values-round-watch/dimens_material.xml
+++ b/core/res/res/values-round-watch/dimens_material.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 <resources>
-    <dimen name="dialog_padding_material">32dp</dimen>
-    <dimen name="preference_fragment_padding_vertical_material">22dp</dimen>
+    <dimen name="dialog_padding_material">@dimen/screen_percentage_15</dimen>
+    <dimen name="preference_fragment_padding_vertical_material">@dimen/screen_percentage_15</dimen>
 
-    <dimen name="list_item_padding_horizontal_material">32dp</dimen>
-    <dimen name="list_item_padding_start_material">40dp</dimen>
-    <dimen name="list_item_padding_end_material">24dp</dimen>
+    <dimen name="list_item_padding_horizontal_material">@dimen/screen_percentage_15</dimen>
+    <dimen name="list_item_padding_start_material">@dimen/screen_percentage_15</dimen>
+    <dimen name="list_item_padding_end_material">@dimen/screen_percentage_10</dimen>
 </resources>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w194dp/dimens_material.xml
similarity index 71%
copy from packages/SystemUI/res/layout/night_mode_settings.xml
copy to core/res/res/values-w194dp/dimens_material.xml
index 3725e78..220c4b0 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w194dp/dimens_material.xml
@@ -13,12 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+    <dimen name="screen_percentage_05">9.7dp</dimen>
+    <dimen name="screen_percentage_10">19.4dp</dimen>
+    <dimen name="screen_percentage_15">29.1dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w205dp/dimens_material.xml
similarity index 71%
copy from packages/SystemUI/res/layout/night_mode_settings.xml
copy to core/res/res/values-w205dp/dimens_material.xml
index 3725e78..94907ee 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w205dp/dimens_material.xml
@@ -13,12 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+    <dimen name="screen_percentage_05">10.25dp</dimen>
+    <dimen name="screen_percentage_10">20.5dp</dimen>
+    <dimen name="screen_percentage_15">30.75dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w213dp/dimens_material.xml
similarity index 71%
copy from packages/SystemUI/res/layout/night_mode_settings.xml
copy to core/res/res/values-w213dp/dimens_material.xml
index 3725e78..8a4e3a0 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w213dp/dimens_material.xml
@@ -13,12 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+    <dimen name="screen_percentage_05">10.65dp</dimen>
+    <dimen name="screen_percentage_10">21.3dp</dimen>
+    <dimen name="screen_percentage_15">31.95dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w228dp/dimens_material.xml
similarity index 71%
rename from packages/SystemUI/res/layout/night_mode_settings.xml
rename to core/res/res/values-w228dp/dimens_material.xml
index 3725e78..a200975 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w228dp/dimens_material.xml
@@ -13,12 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+    <dimen name="screen_percentage_05">11.4dp</dimen>
+    <dimen name="screen_percentage_10">22.8dp</dimen>
+    <dimen name="screen_percentage_15">34.2dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w240dp/dimens_material.xml
similarity index 71%
copy from packages/SystemUI/res/layout/night_mode_settings.xml
copy to core/res/res/values-w240dp/dimens_material.xml
index 3725e78..a4b58fa9 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w240dp/dimens_material.xml
@@ -13,12 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+    <dimen name="screen_percentage_05">12dp</dimen>
+    <dimen name="screen_percentage_10">24dp</dimen>
+    <dimen name="screen_percentage_15">36dp</dimen>
+</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0c47c19..cd56f0f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -754,6 +754,26 @@
     -->
     <integer name="config_defaultNightMode">1</integer>
 
+    <!-- Control whether Night display is available. This should only be enabled on devices
+         with HWC 2.0 or higher. -->
+    <bool name="config_nightDisplayAvailable">false</bool>
+
+    <!-- Default mode to control how Night display is automatically activated.
+         One of the following values (see NightDisplayController.java):
+             0 - AUTO_MODE_DISABLED
+             1 - AUTO_MODE_CUSTOM
+             2 - AUTO_MODE_TWILIGHT
+    -->
+    <integer name="config_defaultNightDisplayAutoMode">1</integer>
+
+    <!-- Default time when Night display is automatically activated.
+         Represented as milliseconds from midnight (e.g. 79200000 == 10pm). -->
+    <integer name="config_defaultNightDisplayCustomStartTime">79200000</integer>
+
+    <!-- Default time when Night display is automatically deactivated.
+         Represented as milliseconds from midnight (e.g. 21600000 == 6am). -->
+    <integer name="config_defaultNightDisplayCustomEndTime">21600000</integer>
+
     <!-- Indicate whether to allow the device to suspend when the screen is off
          due to the proximity sensor.  This resource should only be set to true
          if the sensor HAL correctly handles the proximity sensor as a wake-up source.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index df0c81a..5045f33 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2666,4 +2666,8 @@
   <java-symbol type="drawable" name="ic_doc_video" />
   <java-symbol type="drawable" name="ic_doc_generic" />
 
+  <java-symbol type="bool" name="config_nightDisplayAvailable" />
+  <java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
+  <java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
+  <java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
 </resources>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4bdc70e..f19a262 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2744,6 +2744,7 @@
      * to be notified.
      * Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current
      * configuration.
+     * @see AudioRecordingConfiguration
      */
     public static abstract class AudioRecordingCallback {
         /**
@@ -2850,6 +2851,7 @@
      * Returns the current active audio recording configurations of the device.
      * @return a non-null list of recording configurations. An empty list indicates there is
      *     no recording active when queried.
+     * @see AudioRecordingConfiguration
      */
     public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
         final IAudioService service = getService();
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 5935166..354339c 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -28,8 +28,18 @@
 
 /**
  * The AudioRecordingConfiguration class collects the information describing an audio recording
- * session. This information is returned through the
- * {@link AudioManager#getActiveRecordingConfigurations()} method.
+ * session.
+ * <p>Direct polling (see {@link AudioManager#getActiveRecordingConfigurations()}) or callback
+ * (see {@link AudioManager#registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler)}
+ * methods are ways to receive information about the current recording configuration of the device.
+ * <p>An audio recording configuration contains information about the recording format as used by
+ * the application ({@link #getClientFormat()}, as well as the recording format actually used by
+ * the device ({@link #getFormat()}). The two recording formats may, for instance, be at different
+ * sampling rates due to hardware limitations (e.g. application recording at 44.1kHz whereas the
+ * device always records at 48kHz, and the Android framework resamples for the application).
+ * <p>The configuration also contains the use case for which audio is recorded
+ * ({@link #getClientAudioSource()}), enabling the ability to distinguish between different
+ * activities such as ongoing voice recognition or camcorder recording.
  *
  */
 public final class AudioRecordingConfiguration implements Parcelable {
@@ -198,4 +208,4 @@
                 && (mClientFormat.equals(that.mClientFormat))
                 && (mDeviceFormat.equals(that.mDeviceFormat)));
     }
-}
\ No newline at end of file
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 0643e9be..239f6a6 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -499,23 +499,26 @@
             throw new IllegalStateException("Failed to delete " + file);
         }
 
-        final ContentResolver resolver = getContext().getContentResolver();
-        final Uri externalUri = MediaStore.Files.getContentUri("external");
+        final File visibleFile = getFileForDocId(docId, true);
+        if (visibleFile != null) {
+            final ContentResolver resolver = getContext().getContentResolver();
+            final Uri externalUri = MediaStore.Files.getContentUri("external");
 
-        // Remove media store entries for any files inside this directory, using
-        // path prefix match. Logic borrowed from MtpDatabase.
-        if (isDirectory) {
-            final String path = file.getAbsolutePath() + "/";
+            // Remove media store entries for any files inside this directory, using
+            // path prefix match. Logic borrowed from MtpDatabase.
+            if (isDirectory) {
+                final String path = visibleFile.getAbsolutePath() + "/";
+                resolver.delete(externalUri,
+                        "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+                        new String[] { path + "%", Integer.toString(path.length()), path });
+            }
+
+            // Remove media store entry for this exact file.
+            final String path = visibleFile.getAbsolutePath();
             resolver.delete(externalUri,
-                    "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
-                    new String[] { path + "%", Integer.toString(path.length()), path });
+                    "_data LIKE ?1 AND lower(_data)=lower(?2)",
+                    new String[] { path, path });
         }
-
-        // Remove media store entry for this exact file.
-        final String path = file.getAbsolutePath();
-        resolver.delete(externalUri,
-                "_data LIKE ?1 AND lower(_data)=lower(?2)",
-                new String[] { path, path });
     }
 
     @Override
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index a4a0e6b..eac3964 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -143,6 +143,7 @@
         <item></item>
         <item>all</item>
         <item>default,security,kernel</item>
+        <item>kernel</item>
     </string-array>
 
     <!-- Titles for logpersist state selection preference. [CHAR LIMIT=14] -->
@@ -150,6 +151,7 @@
         <item>Off</item>
         <item>All</item>
         <item>All but radio</item>
+        <item>kernel only</item>
     </string-array>
 
     <!-- Summaries for logpersist state selection preference. [CHAR LIMIT=50]-->
@@ -157,6 +159,7 @@
         <item>Off</item>
         <item>All log buffers</item>
         <item>All but radio log buffers</item>
+        <item>kernel log buffer only</item>
     </string-array>
 
     <!-- Titles for window animation scale preference. [CHAR LIMIT=35] -->
diff --git a/packages/SystemUI/res/drawable/ic_night_mode.xml b/packages/SystemUI/res/drawable/ic_night_mode.xml
deleted file mode 100644
index caa7a47..0000000
--- a/packages/SystemUI/res/drawable/ic_night_mode.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml b/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
deleted file mode 100644
index 010815a..0000000
--- a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/calibrate_sliders.xml b/packages/SystemUI/res/layout/calibrate_sliders.xml
deleted file mode 100644
index 0dec8a1..0000000
--- a/packages/SystemUI/res/layout/calibrate_sliders.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:paddingTop="8dp"
-    android:paddingBottom="8dp"
-    android:orientation="vertical">
-
-    <LinearLayout
-        android:id="@+id/r_group"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:orientation="horizontal">
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/color_modification_r"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <SeekBar android:id="@*android:id/seekbar"
-            android:layout_marginStart="16dp"
-            android:layout_gravity="center_vertical"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" />
-    </LinearLayout>
-
-    <LinearLayout
-        android:id="@+id/g_group"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:orientation="horizontal">
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/color_modification_g"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <SeekBar android:id="@*android:id/seekbar"
-            android:layout_marginStart="16dp"
-            android:layout_gravity="center_vertical"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" />
-    </LinearLayout>
-
-    <LinearLayout
-        android:id="@+id/b_group"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:orientation="horizontal">
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/color_modification_b"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <SeekBar android:id="@*android:id/seekbar"
-            android:layout_marginStart="16dp"
-            android:layout_gravity="center_vertical"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" />
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 28de590..71816f7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1334,59 +1334,6 @@
     <!-- Notification: Gear: Content description for the gear. [CHAR LIMIT=NONE] -->
     <string name="notification_gear_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> notification controls</string>
 
-    <!-- SysUI Tuner: Color and appearance screen title [CHAR LIMIT=50] -->
-    <string name="color_and_appearance">Color and appearance</string>
-
-    <!-- SysUI Tuner: Name of the night mode feature [CHAR LIMIT=30] -->
-    <string name="night_mode">Night mode</string>
-
-    <!-- SysUI Tuner: Name of calibrate display dialog [CHAR LIMIT=30] -->
-    <string name="calibrate_display">Calibrate display</string>
-
-    <!-- SysUI Tuner: Summary of night mode when its on [CHAR LIMIT=NONE] -->
-    <string name="night_mode_on">On</string>
-
-    <!-- SysUI Tuner: Summary of night mode when its off [CHAR LIMIT=NONE] -->
-    <string name="night_mode_off">Off</string>
-
-    <!-- SysUI Tuner: Label for switch to turn on night mode automatically [CHAR LIMIT=50] -->
-    <string name="turn_on_automatically">Turn on automatically</string>
-
-    <!-- SysUI Tuner: Summary for switch to turn on night mode automatically [CHAR LIMIT=NONE] -->
-    <string name="turn_on_auto_summary">Switch into Night Mode as appropriate for location and time of day</string>
-
-    <!-- SysUI Tuner: Label for section controlling what night mode does [CHAR LIMIT=60] -->
-    <string name="when_night_mode_on">When Night Mode is on</string>
-
-    <!-- SysUI Tuner: Switch controlling whether dark theme is turned on with night mode [CHAR LIMIT=45] -->
-    <string name="use_dark_theme">Use dark theme for Android OS</string>
-
-    <!-- SysUI Tuner: Switch controlling whether tint is changed with night mode [CHAR LIMIT=45] -->
-    <string name="adjust_tint">Adjust tint</string>
-
-    <!-- SysUI Tuner: Switch controlling whether brightness is changed with night mode [CHAR LIMIT=45] -->
-    <string name="adjust_brightness">Adjust brightness</string>
-
-    <!-- SysUI Tuner: Disclaimer about using dark theme with night mode [CHAR LIMIT=NONE] -->
-    <string name="night_mode_disclaimer">The dark theme is applied to
-        core areas of Android OS that are normally displayed in a light theme,
-        such as Settings.</string>
-
-    <!-- Button to apply settings [CHAR LIMIT=30] -->
-    <string name="color_apply">Apply</string>
-
-    <!-- Title of warning dialog about bad color settings. [CHAR LIMIT=30] -->
-    <string name="color_revert_title">Confirm settings</string>
-
-    <!-- Message warning user about custom color settings [CHAR LIMIT=NONE] -->
-    <string name="color_revert_message">Some color settings can make this
-        device unusable. Click OK to confirm these color settings,
-        otherwise these settings will reset after 10 seconds.</string>
-
-    <string name="color_modification_r" translatable="false">R</string>
-    <string name="color_modification_g" translatable="false">G</string>
-    <string name="color_modification_b" translatable="false">B</string>
-
     <!-- Title of the battery settings detail panel [CHAR LIMIT=20] -->
     <string name="battery_panel_title">Battery usage</string>
 
diff --git a/packages/SystemUI/res/xml/color_and_appearance.xml b/packages/SystemUI/res/xml/color_and_appearance.xml
deleted file mode 100644
index 21f890e..0000000
--- a/packages/SystemUI/res/xml/color_and_appearance.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:sysui="http://schemas.android.com/apk/res-auto"
-    android:title="@string/color_and_appearance">
-
-    <Preference
-        android:key="night_mode"
-        android:title="@string/night_mode"
-        android:fragment="com.android.systemui.tuner.NightModeFragment" />
-
-    <com.android.systemui.tuner.CalibratePreference
-        android:key="calibrate"
-        android:title="@string/calibrate_display" />
-
-</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/night_mode.xml b/packages/SystemUI/res/xml/night_mode.xml
deleted file mode 100644
index 34af820..0000000
--- a/packages/SystemUI/res/xml/night_mode.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:sysui="http://schemas.android.com/apk/res-auto"
-    android:title="@string/night_mode">
-
-    <SwitchPreference
-        android:key="auto"
-        android:title="@string/turn_on_automatically"
-        android:summary="@string/turn_on_auto_summary" />
-
-    <PreferenceCategory
-        android:title="@string/when_night_mode_on">
-
-        <SwitchPreference
-            android:key="adjust_tint"
-            android:title="@string/adjust_tint" />
-
-        <SwitchPreference
-            android:key="adjust_brightness"
-            android:title="@string/adjust_brightness" />
-
-    </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 116bc69..b46e862 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -100,13 +100,6 @@
 
     </PreferenceScreen>
 
-    <!--
-    <Preference
-        android:key="color_transform"
-        android:title="@string/color_and_appearance"
-        android:fragment="com.android.systemui.tuner.ColorAndAppearanceFragment" />
-    -->
-
     <PreferenceScreen
         android:key="volume_and_do_not_disturb"
         android:title="@string/volume_and_do_not_disturb">
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 907616c..19ae295 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -47,7 +47,6 @@
         Key.QS_DATA_SAVER_DIALOG_SHOWN,
         Key.QS_INVERT_COLORS_ADDED,
         Key.QS_WORK_ADDED,
-        Key.QS_NIGHT_ADDED,
     })
     public @interface Key {
         String OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME = "OverviewLastStackTaskActiveTime";
@@ -67,7 +66,6 @@
         String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
         String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
         String QS_WORK_ADDED = "QsWorkAdded";
-        String QS_NIGHT_ADDED = "QsNightAdded";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index c56c24a..3da7415 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -39,7 +39,6 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.NightModeController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -460,7 +459,6 @@
         UserInfoController getUserInfoController();
         BatteryController getBatteryController();
         TileServices getTileServices();
-        NightModeController getNightModeController();
         void removeTile(String tileSpec);
         ManagedProfileController getManagedProfileController();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 58fbd4c..b742479 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,7 +24,6 @@
 import com.android.systemui.statusbar.policy.DataSaverController.Listener;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.HotspotController.Callback;
-import com.android.systemui.statusbar.policy.NightModeController;
 
 /**
  * Manages which tiles should be automatically added to QS.
@@ -67,35 +66,12 @@
         if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
             host.getManagedProfileController().addCallback(mProfileCallback);
         }
-        if (!Prefs.getBoolean(context, Key.QS_NIGHT_ADDED, false)) {
-            host.getNightModeController().addListener(mNightModeListener);
-        }
     }
 
     public void destroy() {
         // TODO: Remove any registered listeners.
     }
 
-    private final NightModeController.Listener mNightModeListener =
-            new NightModeController.Listener() {
-        @Override
-        public void onNightModeChanged() {
-            if (mHost.getNightModeController().isEnabled()) {
-                mHost.addTile("night");
-                Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mHost.getNightModeController().removeListener(mNightModeListener);
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void onTwilightAutoChanged() { }
-    };
-
     private final ManagedProfileController.Callback mProfileCallback =
             new ManagedProfileController.Callback() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 011ec22..ca7f905 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -60,7 +60,6 @@
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NightModeController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -71,7 +70,6 @@
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.tuner.NightModeTile;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -111,7 +109,6 @@
     private final TileServices mServices;
 
     private final List<Callback> mCallbacks = new ArrayList<>();
-    private final NightModeController mNightModeController;
     private final AutoTileManager mAutoTiles;
     private final ManagedProfileController mProfileController;
     private final NextAlarmController mNextAlarmController;
@@ -144,7 +141,6 @@
         mBattery = battery;
         mIconController = iconController;
         mNextAlarmController = nextAlarmController;
-        mNightModeController = new NightModeController(mContext, true);
         mProfileController = new ManagedProfileController(this);
 
         final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
@@ -308,10 +304,6 @@
         return mIconController;
     }
 
-    public NightModeController getNightModeController() {
-        return mNightModeController;
-    }
-
     public ManagedProfileController getManagedProfileController() {
         return mProfileController;
     }
@@ -448,8 +440,6 @@
         else if (tileSpec.equals("user")) return new UserTile(this);
         else if (tileSpec.equals("battery")) return new BatteryTile(this);
         else if (tileSpec.equals("saver")) return new DataSaverTile(this);
-        else if (tileSpec.equals(NightModeTile.NIGHT_MODE_SPEC))
-            return new NightModeTile(this);
         // Intent tiles.
         else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
         else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
deleted file mode 100644
index 4611ef9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.opengl.Matrix;
-import android.provider.Settings.Secure;
-import android.util.MathUtils;
-import com.android.systemui.tuner.TunerService;
-
-import java.util.ArrayList;
-
-/**
- * Listens for changes to twilight from the TwilightService.
- *
- * Also pushes the current matrix to accessibility based on the current twilight
- * and various tuner settings.
- */
-public class NightModeController implements TunerService.Tunable {
-
-    public static final String NIGHT_MODE_ADJUST_TINT = "tuner_night_mode_adjust_tint";
-    private static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
-
-    private static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED";
-
-    private static final String EXTRA_IS_NIGHT = "isNight";
-    private static final String EXTRA_AMOUNT = "amount";
-
-    // Night mode ~= 3400 K
-    private static final float[] NIGHT_VALUES = new float[] {
-        1, 0,     0,     0,
-        0, .754f, 0,     0,
-        0, 0,     .516f, 0,
-        0, 0,     0,     1,
-    };
-    public static final float[] IDENTITY_MATRIX = new float[] {
-        1, 0, 0, 0,
-        0, 1, 0, 0,
-        0, 0, 1, 0,
-        0, 0, 0, 1,
-    };
-
-    private final ArrayList<Listener> mListeners = new ArrayList<>();
-
-    private final Context mContext;
-
-    // This is whether or not this is the main NightMode controller in SysUI that should be
-    // updating relevant color matrixes or if its in the tuner process getting current state
-    // for UI.
-    private final boolean mUpdateMatrix;
-
-    private float[] mCustomMatrix;
-    private boolean mListening;
-    private boolean mAdjustTint;
-
-    private boolean mIsNight;
-    private float mAmount;
-    private boolean mIsAuto;
-
-    public NightModeController(Context context) {
-        this(context, false);
-    }
-
-    public NightModeController(Context context, boolean updateMatrix) {
-        mContext = context;
-        mUpdateMatrix = updateMatrix;
-        TunerService.get(mContext).addTunable(this, NIGHT_MODE_ADJUST_TINT,
-                COLOR_MATRIX_CUSTOM_VALUES, Secure.TWILIGHT_MODE);
-    }
-
-    public void setNightMode(boolean isNight) {
-        if (mIsAuto) {
-            if (mIsNight != isNight) {
-                TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
-                        ? Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON
-                        : Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF);
-            } else {
-                TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE,
-                        Secure.TWILIGHT_MODE_AUTO);
-            }
-        } else {
-            TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
-                    ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
-        }
-    }
-
-    public void setAuto(boolean auto) {
-        mIsAuto = auto;
-        if (auto) {
-            TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO);
-        } else {
-            // Lock into the current state
-            TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, mIsNight
-                    ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
-        }
-    }
-
-    public boolean isAuto() {
-        return mIsAuto;
-    }
-
-    public void setAdjustTint(Boolean newValue) {
-        TunerService.get(mContext).setValue(NIGHT_MODE_ADJUST_TINT, ((Boolean) newValue) ? 1 : 0);
-    }
-
-    public void addListener(Listener listener) {
-        mListeners.add(listener);
-        listener.onNightModeChanged();
-        updateListening();
-    }
-
-    public void removeListener(Listener listener) {
-        mListeners.remove(listener);
-        updateListening();
-    }
-
-    private void updateListening() {
-        boolean shouldListen = mListeners.size() != 0 || (mUpdateMatrix && mAdjustTint);
-        if (shouldListen == mListening) return;
-        mListening = shouldListen;
-        if (mListening) {
-            mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_TWILIGHT_CHANGED));
-        } else {
-            mContext.unregisterReceiver(mReceiver);
-        }
-    }
-
-    public boolean isEnabled() {
-        if (!mListening) {
-            updateNightMode(mContext.registerReceiver(null,
-                    new IntentFilter(ACTION_TWILIGHT_CHANGED)));
-        }
-        return mIsNight;
-    }
-
-    public String getCustomValues() {
-        return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES);
-    }
-
-    public void setCustomValues(String values) {
-        TunerService.get(mContext).setValue(COLOR_MATRIX_CUSTOM_VALUES, values);
-    }
-
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        if (COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
-            mCustomMatrix = newValue != null ? toValues(newValue) : null;
-            updateCurrentMatrix();
-        } else if (NIGHT_MODE_ADJUST_TINT.equals(key)) {
-            mAdjustTint = newValue == null || Integer.parseInt(newValue) != 0;
-            updateListening();
-            updateCurrentMatrix();
-        } else if (Secure.TWILIGHT_MODE.equals(key)) {
-            mIsAuto = newValue != null && Integer.parseInt(newValue) >= Secure.TWILIGHT_MODE_AUTO;
-        }
-    }
-
-    private void updateCurrentMatrix() {
-        if (!mUpdateMatrix) return;
-        if ((!mAdjustTint || mAmount == 0) && mCustomMatrix == null) {
-            TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
-            return;
-        }
-        float[] values = scaleValues(IDENTITY_MATRIX, NIGHT_VALUES, mAdjustTint ? mAmount : 0);
-        if (mCustomMatrix != null) {
-            values = multiply(values, mCustomMatrix);
-        }
-        TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
-                toString(values));
-    }
-
-    private void updateNightMode(Intent intent) {
-        mIsNight = intent != null && intent.getBooleanExtra(EXTRA_IS_NIGHT, false);
-        mAmount = intent != null ? intent.getFloatExtra(EXTRA_AMOUNT, 0) : 0;
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (ACTION_TWILIGHT_CHANGED.equals(intent.getAction())) {
-                updateNightMode(intent);
-                updateCurrentMatrix();
-                for (int i = 0; i < mListeners.size(); i++) {
-                    mListeners.get(i).onNightModeChanged();
-                }
-            }
-        }
-    };
-
-    public interface Listener {
-        void onNightModeChanged();
-        void onTwilightAutoChanged();
-    }
-
-    private static float[] multiply(float[] matrix, float[] other) {
-        if (matrix == null) {
-            return other;
-        }
-        float[] result = new float[16];
-        Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
-        return result;
-    }
-
-    private float[] scaleValues(float[] identityMatrix, float[] nightValues, float amount) {
-        float[] values = new float[identityMatrix.length];
-        for (int i = 0; i < values.length; i++) {
-            values[i] = MathUtils.lerp(identityMatrix[i], nightValues[i], amount);
-        }
-        return values;
-    }
-
-    public static String toString(float[] values) {
-        StringBuilder builder = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (builder.length() != 0) {
-                builder.append(',');
-            }
-            builder.append(values[i]);
-        }
-        return builder.toString();
-    }
-
-    public static float[] toValues(String customValues) {
-        String[] strValues = customValues.split(",");
-        float[] values = new float[strValues.length];
-        for (int i = 0; i < values.length; i++) {
-            values[i] = Float.parseFloat(strValues[i]);
-        }
-        return values;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
deleted file mode 100644
index ff7be13..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-import android.content.Context;
-import android.support.v7.preference.DialogPreference;
-import android.util.AttributeSet;
-
-public class CalibratePreference extends DialogPreference {
-    public CalibratePreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
deleted file mode 100644
index af95cf9..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.provider.Settings.Secure;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v7.preference.Preference;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.SeekBar;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NightModeController;
-
-public class ColorAndAppearanceFragment extends PreferenceFragment {
-
-    private static final String KEY_CALIBRATE = "calibrate";
-
-    private static final long RESET_DELAY = 10000;
-    private static final CharSequence KEY_NIGHT_MODE = "night_mode";
-
-    private NightModeController mNightModeController;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mNightModeController = new NightModeController(getContext());
-    }
-
-    @Override
-    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        addPreferencesFromResource(R.xml.color_and_appearance);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, true);
-        // TODO: Figure out better title model for Tuner, to avoid any more of this.
-        getActivity().setTitle(R.string.color_and_appearance);
-
-        Preference nightMode = findPreference(KEY_NIGHT_MODE);
-        nightMode.setSummary(mNightModeController.isEnabled()
-                ? R.string.night_mode_on : R.string.night_mode_off);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, false);
-    }
-
-    @Override
-    public void onDisplayPreferenceDialog(Preference preference) {
-        if (preference instanceof CalibratePreference) {
-            CalibrateDialog.show(this);
-        } else {
-            super.onDisplayPreferenceDialog(preference);
-        }
-    }
-
-    private void startRevertTimer() {
-        getView().postDelayed(mResetColorMatrix, RESET_DELAY);
-    }
-
-    private void onApply() {
-        MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_CALIBRATE_DISPLAY_CHANGED);
-        mNightModeController.setCustomValues(Settings.Secure.getString(
-                getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX));
-        getView().removeCallbacks(mResetColorMatrix);
-    }
-
-    private void onRevert() {
-        getView().removeCallbacks(mResetColorMatrix);
-        mResetColorMatrix.run();
-    }
-
-    private final Runnable mResetColorMatrix = new Runnable() {
-        @Override
-        public void run() {
-            ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss();
-            Settings.Secure.putString(getContext().getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
-        }
-    };
-
-    public static class CalibrateDialog extends DialogFragment implements
-            DialogInterface.OnClickListener {
-        private float[] mValues;
-        private NightModeController mNightModeController;
-
-        public static void show(ColorAndAppearanceFragment fragment) {
-            CalibrateDialog dialog = new CalibrateDialog();
-            dialog.setTargetFragment(fragment, 0);
-            dialog.show(fragment.getFragmentManager(), "Calibrate");
-        }
-
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            mNightModeController = new NightModeController(getContext());
-            String customValues = mNightModeController.getCustomValues();
-            if (customValues == null) {
-                // Generate this as a string because its the easiest way to generate a copy of the
-                // identity.
-                customValues = NightModeController.toString(NightModeController.IDENTITY_MATRIX);
-            }
-            mValues = NightModeController.toValues(customValues);
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            View v = LayoutInflater.from(getContext()).inflate(R.layout.calibrate_sliders, null);
-            bindView(v.findViewById(R.id.r_group), 0);
-            bindView(v.findViewById(R.id.g_group), 5);
-            bindView(v.findViewById(R.id.b_group), 10);
-            MetricsLogger.visible(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
-            return new AlertDialog.Builder(getContext())
-                    .setTitle(R.string.calibrate_display)
-                    .setView(v)
-                    .setPositiveButton(R.string.color_apply, this)
-                    .setNegativeButton(android.R.string.cancel, null)
-                    .create();
-        }
-
-        @Override
-        public void onDismiss(DialogInterface dialog) {
-            super.onDismiss(dialog);
-            MetricsLogger.hidden(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
-        }
-
-        private void bindView(View view, final int index) {
-            SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
-            seekBar.setMax(1000);
-            seekBar.setProgress((int) (1000 * mValues[index]));
-            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-                @Override
-                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                    mValues[index] = progress / 1000f;
-                }
-
-                @Override
-                public void onStartTrackingTouch(SeekBar seekBar) {
-                }
-
-                @Override
-                public void onStopTrackingTouch(SeekBar seekBar) {
-                }
-            });
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            if (mValues[0] == 1 && mValues[5] == 1 && mValues[10] == 1) {
-                // Allow removal of matrix by all values set to highest.
-                mNightModeController.setCustomValues(null);
-                return;
-            }
-            ((ColorAndAppearanceFragment) getTargetFragment()).startRevertTimer();
-            Settings.Secure.putString(getContext().getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
-                    NightModeController.toString(mValues));
-            RevertWarning.show((ColorAndAppearanceFragment) getTargetFragment());
-        }
-    }
-
-    public static class RevertWarning extends DialogFragment
-            implements DialogInterface.OnClickListener {
-
-        public static void show(ColorAndAppearanceFragment fragment) {
-            RevertWarning warning = new RevertWarning();
-            warning.setTargetFragment(fragment, 0);
-            warning.show(fragment.getFragmentManager(), "RevertWarning");
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            AlertDialog alertDialog = new AlertDialog.Builder(getContext())
-                    .setTitle(R.string.color_revert_title)
-                    .setMessage(R.string.color_revert_message)
-                    .setPositiveButton(R.string.ok, this)
-                    .create();
-            alertDialog.setCanceledOnTouchOutside(true);
-            return alertDialog;
-        }
-
-        @Override
-        public void onCancel(DialogInterface dialog) {
-            super.onCancel(dialog);
-            ((ColorAndAppearanceFragment) getTargetFragment()).onRevert();
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            ((ColorAndAppearanceFragment) getTargetFragment()).onApply();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
deleted file mode 100644
index ae2856c..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.annotation.Nullable;
-import android.app.UiModeManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.provider.Settings.Secure;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NightModeController;
-import com.android.systemui.statusbar.policy.NightModeController.Listener;
-import com.android.systemui.tuner.TunerService.Tunable;
-
-public class NightModeFragment extends PreferenceFragment implements Tunable,
-        Listener, OnPreferenceChangeListener {
-
-    private static final String TAG = "NightModeFragment";
-
-    public static final String EXTRA_SHOW_NIGHT_MODE = "show_night_mode";
-
-    private static final CharSequence KEY_AUTO = "auto";
-    private static final CharSequence KEY_ADJUST_TINT = "adjust_tint";
-    private static final CharSequence KEY_ADJUST_BRIGHTNESS = "adjust_brightness";
-
-    private Switch mSwitch;
-
-    private NightModeController mNightModeController;
-    private SwitchPreference mAutoSwitch;
-    private SwitchPreference mAdjustTint;
-    private SwitchPreference mAdjustBrightness;
-    private UiModeManager mUiModeManager;
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mNightModeController = new NightModeController(getContext());
-        mUiModeManager = getContext().getSystemService(UiModeManager.class);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        final View view = LayoutInflater.from(getContext()).inflate(
-                R.layout.night_mode_settings, container, false);
-        ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
-        return view;
-    }
-
-    @Override
-    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        final Context context = getPreferenceManager().getContext();
-
-        addPreferencesFromResource(R.xml.night_mode);
-        mAutoSwitch = (SwitchPreference) findPreference(KEY_AUTO);
-        mAutoSwitch.setOnPreferenceChangeListener(this);
-        mAdjustTint = (SwitchPreference) findPreference(KEY_ADJUST_TINT);
-        mAdjustTint.setOnPreferenceChangeListener(this);
-        mAdjustBrightness = (SwitchPreference) findPreference(KEY_ADJUST_BRIGHTNESS);
-        mAdjustBrightness.setOnPreferenceChangeListener(this);
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        View switchBar = view.findViewById(R.id.switch_bar);
-        mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
-        mSwitch.setChecked(mNightModeController.isEnabled());
-        switchBar.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                boolean newState = !mNightModeController.isEnabled();
-                MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE, newState);
-                mNightModeController.setNightMode(newState);
-                mSwitch.setChecked(newState);
-            }
-        });
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, true);
-        mNightModeController.addListener(this);
-        TunerService.get(getContext()).addTunable(this, Secure.BRIGHTNESS_USE_TWILIGHT,
-                NightModeController.NIGHT_MODE_ADJUST_TINT);
-        calculateDisabled();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, false);
-        mNightModeController.removeListener(this);
-        TunerService.get(getContext()).removeTunable(this);
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final Boolean value = (Boolean) newValue;
-        if (mAutoSwitch == preference) {
-            MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE_AUTO, value);
-            mNightModeController.setAuto(value);
-        } else if (mAdjustTint == preference) {
-            MetricsLogger.action(getContext(),
-                    MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_TINT, value);
-            mNightModeController.setAdjustTint(value);
-            postCalculateDisabled();
-        } else if (mAdjustBrightness == preference) {
-            MetricsLogger.action(getContext(),
-                    MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_BRIGHTNESS, value);
-            TunerService.get(getContext()).setValue(Secure.BRIGHTNESS_USE_TWILIGHT,
-                    value ? 1 : 0);
-            postCalculateDisabled();
-        } else {
-            return false;
-        }
-        return true;
-    }
-
-    private void postCalculateDisabled() {
-        // Post this because its the easiest way to wait for all state to be calculated.
-        getView().post(new Runnable() {
-            @Override
-            public void run() {
-                calculateDisabled();
-            }
-        });
-    }
-
-    private void calculateDisabled() {
-        int enabledCount = (mAdjustTint.isChecked() ? 1 : 0)
-                + (mAdjustBrightness.isChecked() ? 1 : 0);
-        if (enabledCount == 1) {
-            if (mAdjustTint.isChecked()) {
-                mAdjustTint.setEnabled(false);
-            } else {
-                mAdjustBrightness.setEnabled(false);
-            }
-        } else {
-            mAdjustTint.setEnabled(true);
-            mAdjustBrightness.setEnabled(true);
-        }
-    }
-
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        if (Secure.BRIGHTNESS_USE_TWILIGHT.equals(key)) {
-            mAdjustBrightness.setChecked(newValue != null && Integer.parseInt(newValue) != 0);
-        } else if (NightModeController.NIGHT_MODE_ADJUST_TINT.equals(key)) {
-            // Default on.
-            mAdjustTint.setChecked(newValue == null || Integer.parseInt(newValue) != 0);
-        }
-    }
-
-    @Override
-    public void onNightModeChanged() {
-        mSwitch.setChecked(mNightModeController.isEnabled());
-    }
-
-    @Override
-    public void onTwilightAutoChanged() {
-        mAutoSwitch.setChecked(mNightModeController.isAuto());
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
deleted file mode 100644
index fe44502..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.content.Intent;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.policy.NightModeController;
-
-
-public class NightModeTile extends QSTile<QSTile.State> implements NightModeController.Listener {
-
-    public static final String NIGHT_MODE_SPEC = "night";
-
-    private final NightModeController mNightModeController;
-
-    private int mIndex;
-    private String mCurrentValue;
-
-    private boolean mCustomEnabled;
-    private String[] mValues;
-    private CharSequence[] mValueTitles;
-
-    public NightModeTile(Host host) {
-        super(host);
-        mNightModeController = host.getNightModeController();
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return Prefs.getBoolean(mContext, Key.QS_NIGHT_ADDED, false)
-                && TunerService.isTunerEnabled(mContext);
-    }
-
-    @Override
-    public void setListening(boolean listening) {
-        if (listening) {
-            mNightModeController.addListener(this);
-            refreshState();
-        } else {
-            mNightModeController.removeListener(this);
-        }
-    }
-
-    @Override
-    public State newTileState() {
-        return new State();
-    }
-
-    @Override
-    public Intent getLongClickIntent() {
-        return new Intent(mContext, TunerActivity.class)
-                .putExtra(NightModeFragment.EXTRA_SHOW_NIGHT_MODE, true);
-    }
-
-    @Override
-    protected void handleClick() {
-        mNightModeController.setNightMode(!mNightModeController.isEnabled());
-        refreshState();
-    }
-
-    @Override
-    public CharSequence getTileLabel() {
-        return mContext.getString(R.string.night_mode);
-    }
-
-    @Override
-    protected void handleUpdateState(State state, Object arg) {
-        // TODO: Right now this is just a dropper, needs an actual night icon.
-        boolean enabled = mNightModeController.isEnabled();
-        state.icon = ResourceIcon.get(enabled ? R.drawable.ic_night_mode
-                : R.drawable.ic_night_mode_disabled);
-        state.label = mContext.getString(R.string.night_mode);
-        state.contentDescription = mContext.getString(R.string.night_mode);
-    }
-
-    @Override
-    public void onNightModeChanged() {
-        refreshState();
-    }
-
-    @Override
-    public void onTwilightAutoChanged() {
-        // Don't care.
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.QS_COLOR_MATRIX;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 5e5da74..5fe9296 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -39,10 +39,7 @@
             final String action = getIntent().getAction();
             boolean showDemoMode = action != null && action.equals(
                     "com.android.settings.action.DEMO_MODE");
-            boolean showNightMode = getIntent().getBooleanExtra(
-                    NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false);
-            final PreferenceFragment fragment = showNightMode ? new NightModeFragment()
-                    : showDemoMode ? new DemoModeFragment()
+            final PreferenceFragment fragment = showDemoMode ? new DemoModeFragment()
                     : new TunerFragment();
             getFragmentManager().beginTransaction().replace(R.id.content_frame,
                     fragment, TAG_TUNER).commit();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index cd90dc5..0fc9da0 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2367,6 +2367,10 @@
     // ACTION: Settings -> Support -> "Travel Abroad" Button -> Tolled Phone
     ACTION_SUPPORT_DIAL_TOLLED = 487;
 
+    // OPEN: Settings > Display > Night display
+    // CATEGORY: SETTINGS
+    NIGHT_DISPLAY_SETTINGS = 488;
+
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
 
     // ------- Begin N Keyboard Shortcuts Helper -----
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
new file mode 100644
index 0000000..27abd1e
--- /dev/null
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings.Secure;
+import android.util.Slog;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.server.SystemService;
+import com.android.server.twilight.TwilightListener;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Tints the display at night.
+ */
+public final class NightDisplayService extends SystemService
+        implements NightDisplayController.Callback {
+
+    private static final String TAG = "NightDisplayService";
+    private static final boolean DEBUG = false;
+
+    /**
+     * Night mode ~= 3400 K.
+     */
+    private static final String MATRIX_NIGHT = "1,0,0,0,0,.754,0,0,0,0,.516,0,0,0,0,1";
+
+    private int mCurrentUser = UserHandle.USER_NULL;
+    private boolean mBootCompleted;
+
+    private NightDisplayController mController;
+    private Boolean mIsActivated;
+    private AutoMode mAutoMode;
+
+    public NightDisplayService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        // Nothing to publish.
+    }
+
+    @Override
+    public void onStartUser(int userHandle) {
+        super.onStartUser(userHandle);
+
+        // Register listeners for the new user.
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            mCurrentUser = userHandle;
+            if (mBootCompleted) {
+                setUpNightMode();
+            }
+        }
+    }
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+        super.onSwitchUser(userHandle);
+
+        // Unregister listeners for the old user.
+        if (mBootCompleted && mCurrentUser != UserHandle.USER_NULL) {
+            tearDownNightMode();
+        }
+
+        // Register listeners for the new user.
+        mCurrentUser = userHandle;
+        if (mBootCompleted) {
+            setUpNightMode();
+        }
+    }
+
+    @Override
+    public void onStopUser(int userHandle) {
+        super.onStopUser(userHandle);
+
+        // Unregister listeners for the old user.
+        if (mCurrentUser == userHandle) {
+            if (mBootCompleted) {
+                tearDownNightMode();
+            }
+            mCurrentUser = UserHandle.USER_NULL;
+        }
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_BOOT_COMPLETED) {
+            mBootCompleted = true;
+
+            // Register listeners now that boot is complete.
+            if (mCurrentUser != UserHandle.USER_NULL) {
+                setUpNightMode();
+            }
+        }
+    }
+
+    private void setUpNightMode() {
+        // Create a new controller for the current user and start listening for changes.
+        mController = new NightDisplayController(getContext(), mCurrentUser);
+        mController.setListener(this);
+
+        // Initialize the current auto mode.
+        onAutoModeChanged(mController.getAutoMode());
+
+        // Force the initialization current activated state.
+        if (mIsActivated == null) {
+            onActivated(mController.isActivated());
+        }
+    }
+
+    private void tearDownNightMode() {
+        mController.setListener(null);
+
+        if (mAutoMode != null) {
+            mAutoMode.onStop();
+            mAutoMode = null;
+        }
+
+        mIsActivated = null;
+        mController = null;
+    }
+
+    @Override
+    public void onActivated(boolean activated) {
+        if (mIsActivated == null || mIsActivated != activated) {
+            Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
+
+            mIsActivated = activated;
+
+            if (mAutoMode != null) {
+                mAutoMode.onActivated(activated);
+            }
+
+            // Update the current color matrix.
+            final ContentResolver cr = getContext().getContentResolver();
+            Secure.putStringForUser(cr, Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
+                    activated ? MATRIX_NIGHT : null, mCurrentUser);
+        }
+    }
+
+    @Override
+    public void onAutoModeChanged(int autoMode) {
+        if (mAutoMode != null) {
+            mAutoMode.onStop();
+            mAutoMode = null;
+        }
+
+        if (autoMode == NightDisplayController.AUTO_MODE_CUSTOM) {
+            mAutoMode = new CustomAutoMode();
+        } else if (autoMode == NightDisplayController.AUTO_MODE_TWILIGHT) {
+            mAutoMode = new TwilightAutoMode();
+        }
+
+        if (mAutoMode != null) {
+            mAutoMode.onStart();
+        }
+    }
+
+    @Override
+    public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+        if (mAutoMode != null) {
+            mAutoMode.onCustomStartTimeChanged(startTime);
+        }
+    }
+
+    @Override
+    public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+        if (mAutoMode != null) {
+            mAutoMode.onCustomEndTimeChanged(endTime);
+        }
+    }
+
+    private abstract class AutoMode implements NightDisplayController.Callback {
+        public abstract void onStart();
+        public abstract void onStop();
+    }
+
+    private class CustomAutoMode extends AutoMode implements AlarmManager.OnAlarmListener {
+
+        private final AlarmManager mAlarmManager;
+        private final BroadcastReceiver mTimeChangedReceiver;
+
+        private NightDisplayController.LocalTime mStartTime;
+        private NightDisplayController.LocalTime mEndTime;
+
+        private Calendar mLastActivatedTime;
+
+        public CustomAutoMode() {
+            mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+            mTimeChangedReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    updateActivated();
+                }
+            };
+        }
+
+        private void updateActivated() {
+            final Calendar now = Calendar.getInstance();
+            final Calendar startTime = mStartTime.getDateTimeBefore(now);
+            final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
+            final boolean activated = now.before(endTime);
+
+            boolean setActivated = mIsActivated == null || mLastActivatedTime == null;
+            if (!setActivated && mIsActivated != activated) {
+                final TimeZone currentTimeZone = now.getTimeZone();
+                if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
+                    final int year = mLastActivatedTime.get(Calendar.YEAR);
+                    final int dayOfYear = mLastActivatedTime.get(Calendar.DAY_OF_YEAR);
+                    final int hourOfDay = mLastActivatedTime.get(Calendar.HOUR_OF_DAY);
+                    final int minute = mLastActivatedTime.get(Calendar.MINUTE);
+
+                    mLastActivatedTime.setTimeZone(currentTimeZone);
+                    mLastActivatedTime.set(Calendar.YEAR, year);
+                    mLastActivatedTime.set(Calendar.DAY_OF_YEAR, dayOfYear);
+                    mLastActivatedTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
+                    mLastActivatedTime.set(Calendar.MINUTE, minute);
+                }
+
+                if (mIsActivated) {
+                    setActivated = now.before(mStartTime.getDateTimeBefore(mLastActivatedTime))
+                            || now.after(mEndTime.getDateTimeAfter(mLastActivatedTime));
+                } else {
+                    setActivated = now.before(mEndTime.getDateTimeBefore(mLastActivatedTime))
+                            || now.after(mStartTime.getDateTimeAfter(mLastActivatedTime));
+                }
+            }
+
+            if (setActivated) {
+                mController.setActivated(activated);
+            }
+            updateNextAlarm();
+        }
+
+        private void updateNextAlarm() {
+            if (mIsActivated != null) {
+                final Calendar now = Calendar.getInstance();
+                final Calendar next = mIsActivated ? mEndTime.getDateTimeAfter(now)
+                        : mStartTime.getDateTimeAfter(now);
+                mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null);
+            }
+        }
+
+        @Override
+        public void onStart() {
+            final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
+            intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+            getContext().registerReceiver(mTimeChangedReceiver, intentFilter);
+
+            mStartTime = mController.getCustomStartTime();
+            mEndTime = mController.getCustomEndTime();
+
+            // Force an update to initialize state.
+            updateActivated();
+        }
+
+        @Override
+        public void onStop() {
+            getContext().unregisterReceiver(mTimeChangedReceiver);
+
+            mAlarmManager.cancel(this);
+            mLastActivatedTime = null;
+        }
+
+        @Override
+        public void onActivated(boolean activated) {
+            mLastActivatedTime = Calendar.getInstance();
+            updateNextAlarm();
+        }
+
+        @Override
+        public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+            mStartTime = startTime;
+            mLastActivatedTime = null;
+            updateActivated();
+        }
+
+        @Override
+        public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+            mEndTime = endTime;
+            mLastActivatedTime = null;
+            updateActivated();
+        }
+
+        @Override
+        public void onAlarm() {
+            if (DEBUG) Slog.d(TAG, "onAlarm");
+            updateActivated();
+        }
+    }
+
+    private class TwilightAutoMode extends AutoMode implements TwilightListener {
+
+        private final TwilightManager mTwilightManager;
+        private final Handler mHandler;
+
+        private boolean mIsNight;
+
+        public TwilightAutoMode() {
+            mTwilightManager = getLocalService(TwilightManager.class);
+            mHandler = new Handler(Looper.getMainLooper());
+        }
+
+        private void updateActivated() {
+            final TwilightState state = mTwilightManager.getCurrentState();
+            final boolean isNight = state != null && state.isNight();
+            if (mIsNight != isNight) {
+                mIsNight = isNight;
+
+                if (mIsActivated == null || mIsActivated != isNight) {
+                    mController.setActivated(isNight);
+                }
+            }
+        }
+
+        @Override
+        public void onStart() {
+            mTwilightManager.registerListener(this, mHandler);
+
+            // Force an update to initialize state.
+            updateActivated();
+        }
+
+        @Override
+        public void onStop() {
+            mTwilightManager.unregisterListener(this);
+        }
+
+        @Override
+        public void onTwilightStateChanged() {
+            if (DEBUG) Slog.d(TAG, "onTwilightStateChanged");
+            updateActivated();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 6158c92..89e5e58 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -556,7 +556,7 @@
         public void onChange(boolean selfChange) {
             super.onChange(selfChange);
             int value = Secure.getIntForUser(getContext().getContentResolver(),
-                    Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_LOCKED_OFF, mCurrentUser);
+                    Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, mCurrentUser);
             if (value == Secure.TWILIGHT_MODE_LOCKED_OFF) {
                 setLockedState(new TwilightState(false, 0));
             } else if (value == Secure.TWILIGHT_MODE_LOCKED_ON) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a405c5f..099f518 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -51,6 +51,7 @@
 import android.view.WindowManager;
 
 import com.android.internal.R;
+import com.android.internal.app.NightDisplayController;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.ZygoteInit;
@@ -63,6 +64,7 @@
 import com.android.server.connectivity.MetricsLoggerService;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
 import com.android.server.display.DisplayManagerService;
+import com.android.server.display.NightDisplayService;
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.fingerprint.FingerprintService;
 import com.android.server.hdmi.HdmiControlService;
@@ -999,6 +1001,10 @@
 
             mSystemServiceManager.startService(TwilightService.class);
 
+            if (NightDisplayController.isAvailable(context)) {
+                mSystemServiceManager.startService(NightDisplayService.class);
+            }
+
             mSystemServiceManager.startService(JobSchedulerService.class);
 
             mSystemServiceManager.startService(SoundTriggerService.class);