Merge "Support multiple intents in ShortcutInfo" into nyc-mr1-dev
diff --git a/core/java/android/app/ITransientNotification.aidl b/core/java/android/app/ITransientNotification.aidl
index d5b3ed0..35b53a4 100644
--- a/core/java/android/app/ITransientNotification.aidl
+++ b/core/java/android/app/ITransientNotification.aidl
@@ -19,7 +19,7 @@
 
 /** @hide */
 oneway interface ITransientNotification {
-    void show(IBinder windowToken);
+    void show();
     void hide();
 }
 
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index a20307a..04ee1e6 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1356,20 +1356,35 @@
     /**
      * Computes the device's orientation based on the rotation matrix.
      * <p>
-     * When it returns, the array values is filled with the result:
+     * When it returns, the array values are as follows:
      * <ul>
-     * <li>values[0]: <i>azimuth</i>, rotation around the -Z axis,
-     *                i.e. the opposite direction of Z axis.</li>
-     * <li>values[1]: <i>pitch</i>, rotation around the -X axis,
-     *                i.e the opposite direction of X axis.</li>
-     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
+     * <li>values[0]: <i>Azimuth</i>, angle of rotation about the -z axis.
+     *                This value represents the angle between the device's y
+     *                axis and the magnetic north pole. When facing north, this
+     *                angle is 0, when facing south, this angle is &pi;.
+     *                Likewise, when facing east, this angle is &pi;/2, and
+     *                when facing west, this angle is -&pi;/2. The range of
+     *                values is -&pi; to &pi;.</li>
+     * <li>values[1]: <i>Pitch</i>, angle of rotation about the x axis.
+     *                This value represents the angle between a plane parallel
+     *                to the device's screen and a plane parallel to the ground.
+     *                Assuming that the bottom edge of the device faces the
+     *                user and that the screen is face-up, tilting the top edge
+     *                of the device toward the ground creates a positive pitch
+     *                angle. The range of values is -&pi; to &pi;.</li>
+     * <li>values[2]: <i>Roll</i>, angle of rotation about the y axis. This
+     *                value represents the angle between a plane perpendicular
+     *                to the device's screen and a plane perpendicular to the
+     *                ground. Assuming that the bottom edge of the device faces
+     *                the user and that the screen is face-up, tilting the left
+     *                edge of the device toward the ground creates a positive
+     *                roll angle. The range of values is -&pi;/2 to &pi;/2.</li>
      * </ul>
      * <p>
-     * Applying these three intrinsic rotations in azimuth, pitch and roll order transforms
-     * identity matrix to the rotation matrix given in input R.
-     * All three angles above are in <b>radians</b> and <b>positive</b> in the
-     * <b>counter-clockwise</b> direction. Range of output is: azimuth from -&pi; to &pi;,
-     * pitch from -&pi;/2 to &pi;/2 and roll from -&pi; to &pi;.
+     * Applying these three rotations in the azimuth, pitch, roll order
+     * transforms an identity matrix to the rotation matrix passed into this
+     * method. Also, note that all three orientation angles are expressed in
+     * <b>radians</b>.
      *
      * @param R
      *        rotation matrix see {@link #getRotationMatrix}.
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 93da3e5..826eb74 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -354,9 +354,9 @@
         }
     }
 
-    public void requestColorTransform(int displayId, int colorTransformId) {
+    public void requestColorMode(int displayId, int colorMode) {
         try {
-            mDm.requestColorTransform(displayId, colorTransformId);
+            mDm.requestColorMode(displayId, colorMode);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 8a1abf1..f696c8d 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -59,8 +59,8 @@
     // No permissions required.
     WifiDisplayStatus getWifiDisplayStatus();
 
-    // Requires CONFIGURE_DISPLAY_COLOR_TRANSFORM
-    void requestColorTransform(int displayId, int colorTransformId);
+    // Requires CONFIGURE_DISPLAY_COLOR_MODE
+    void requestColorMode(int displayId, int colorMode);
 
     // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
     // MediaProjection token for certain combinations of flags.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1b9e2aa..f0cc390 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1302,9 +1302,11 @@
         // Event for the UID that woke up the application processor.
         // Used for wakeups coming from WiFi, modem, etc.
         public static final int EVENT_WAKEUP_AP = 0x0013;
+        // Event for reporting that a specific partial wake lock has been held for a long duration.
+        public static final int EVENT_LONG_WAKE_LOCK = 0x0014;
 
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0014;
+        public static final int EVENT_COUNT = 0x0015;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1332,6 +1334,10 @@
                 EVENT_TEMP_WHITELIST | EVENT_FLAG_START;
         public static final int EVENT_TEMP_WHITELIST_FINISH =
                 EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH;
+        public static final int EVENT_LONG_WAKE_LOCK_START =
+                EVENT_LONG_WAKE_LOCK | EVENT_FLAG_START;
+        public static final int EVENT_LONG_WAKE_LOCK_FINISH =
+                EVENT_LONG_WAKE_LOCK | EVENT_FLAG_FINISH;
 
         // For CMD_EVENT.
         public int eventCode;
@@ -1996,13 +2002,13 @@
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
             "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
             "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist",
-            "screenwake", "wakeupap"
+            "screenwake", "wakeupap", "longwake"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
             "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw",
-            "Esw", "Ewa"
+            "Esw", "Ewa", "Elw"
     };
 
     /**
@@ -4960,7 +4966,9 @@
                         pw.print(',');
                         pw.print(rec.stepDetails.statIdlTime);
                         pw.print(',');
-                        pw.print(rec.stepDetails.statPlatformIdleState);
+                        if (rec.stepDetails.statPlatformIdleState != null) {
+                            pw.print(rec.stepDetails.statPlatformIdleState);
+                        }
                         pw.println();
                     }
                 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 5254d35..c5507b9 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -132,10 +132,15 @@
     public static final int FLAG_INCLUDE_INVISIBLE = 1 << 10;
 
     private static volatile IMountService sMountService = null;
-    private static final String INTERNAL_STORAGE_SIZE_PATH =
-            "/sys/block/mmcblk0/size";
-    private static final String INTERNAL_STORAGE_SECTOR_SIZE =
-            "/sys/block/mmcblk0/queue/hw_sector_size";
+
+    // TODO: the location of the primary storage block varies from device to device, so we need to
+    // try the most likely candidates - a long-term solution would be a device-specific vold
+    // function that returns the calculated size.
+    private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
+            "/sys/block/mmcblk0/size",
+            "/sys/block/sda/size"
+    };
+    private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512;
 
     private final Context mContext;
     private final ContentResolver mResolver;
@@ -926,9 +931,13 @@
 
     /** {@hide} */
     public long getPrimaryStorageSize() {
-        final long numberBlocks = readLong(INTERNAL_STORAGE_SIZE_PATH);
-        final long sectorSize = readLong(INTERNAL_STORAGE_SECTOR_SIZE);
-        return numberBlocks * sectorSize;
+        for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
+            final long numberBlocks = readLong(path);
+            if (numberBlocks > 0) {
+                return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
+            }
+        }
+        return 0;
     }
 
     private long readLong(String path) {
@@ -936,7 +945,7 @@
                 final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
             return Long.parseLong(reader.readLine());
         } catch (Exception e) {
-            Slog.w("Could not read " + path, e);
+            Slog.w(TAG, "Could not read " + path, e);
             return 0;
         }
     }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 69960b0..e90a3ba 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -44,6 +44,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.Locale;
 import java.util.Objects;
@@ -896,9 +897,13 @@
                     ", endHour=" + endHour +
                     ", endMinute=" + endMinute +
                     ", exitAtAlarm=" + exitAtAlarm +
-                    ", nextAlarm=" + nextAlarm +
+                    ", nextAlarm=" + ts(nextAlarm) +
                     '}';
         }
+
+        protected static String ts(long time) {
+            return new Date(time) + " (" + time + ")";
+        }
     }
 
     // ==== Built-in system condition: event ====
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 8c49009..899ae49 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -36,7 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
-import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM;
+import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
 
 /**
  * Provides information about the size and density of a logical display.
@@ -284,6 +284,27 @@
      */
     public static final int STATE_DOZE_SUSPEND = 4;
 
+    /* The color mode constants defined below must be kept in sync with the ones in
+     * system/graphics.h */
+
+    /**
+     * Display color mode: The current color mode is unknown or invalid.
+     * @hide
+     */
+    public static final int COLOR_MODE_INVALID = -1;
+
+    /**
+     * Display color mode: The default or native gamut of the display.
+     * @hide
+     */
+    public static final int COLOR_MODE_DEFAULT = 0;
+
+    /**
+     * Display color mode: SRGB
+     * @hide
+     */
+    public static final int COLOR_MODE_SRGB = 7;
+
     /**
      * Internal method to create a display.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
@@ -696,33 +717,22 @@
     }
 
     /**
-     * Request the display applies a color transform.
+     * Request the display applies a color mode.
      * @hide
      */
-    @RequiresPermission(CONFIGURE_DISPLAY_COLOR_TRANSFORM)
-    public void requestColorTransform(ColorTransform colorTransform) {
-        mGlobal.requestColorTransform(mDisplayId, colorTransform.getId());
+    @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE)
+    public void requestColorMode(int colorMode) {
+        mGlobal.requestColorMode(mDisplayId, colorMode);
     }
 
     /**
-     * Returns the active color transform of this display
+     * Returns the active color mode of this display
      * @hide
      */
-    public ColorTransform getColorTransform() {
+    public int getColorMode() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.getColorTransform();
-        }
-    }
-
-    /**
-     * Returns the default color transform of this display
-     * @hide
-     */
-    public ColorTransform getDefaultColorTransform() {
-        synchronized (this) {
-            updateDisplayInfoLocked();
-            return mDisplayInfo.getDefaultColorTransform();
+            return mDisplayInfo.colorMode;
         }
     }
 
@@ -737,14 +747,14 @@
     }
 
     /**
-     * Gets the supported color transforms of this device.
+     * Gets the supported color modes of this device.
      * @hide
      */
-    public ColorTransform[] getSupportedColorTransforms() {
+    public int[] getSupportedColorModes() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            ColorTransform[] transforms = mDisplayInfo.supportedColorTransforms;
-            return Arrays.copyOf(transforms, transforms.length);
+            int[] colorModes = mDisplayInfo.supportedColorModes;
+            return Arrays.copyOf(colorModes, colorModes.length);
         }
     }
 
@@ -1263,89 +1273,4 @@
             return 0;
         }
     }
-
-    /**
-     * A color transform supported by a given display.
-     *
-     * @see Display#getSupportedColorTransforms()
-     * @hide
-     */
-    public static final class ColorTransform implements Parcelable {
-        public static final ColorTransform[] EMPTY_ARRAY = new ColorTransform[0];
-
-        private final int mId;
-        private final int mColorTransform;
-
-        public ColorTransform(int id, int colorTransform) {
-            mId = id;
-            mColorTransform = colorTransform;
-        }
-
-        public int getId() {
-            return mId;
-        }
-
-        public int getColorTransform() {
-            return mColorTransform;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) {
-                return true;
-            }
-            if (!(other instanceof ColorTransform)) {
-                return false;
-            }
-            ColorTransform that = (ColorTransform) other;
-            return mId == that.mId
-                && mColorTransform == that.mColorTransform;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 1;
-            hash = hash * 17 + mId;
-            hash = hash * 17 + mColorTransform;
-            return hash;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder("{")
-                    .append("id=").append(mId)
-                    .append(", colorTransform=").append(mColorTransform)
-                    .append("}")
-                    .toString();
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        private ColorTransform(Parcel in) {
-            this(in.readInt(), in.readInt());
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int parcelableFlags) {
-            out.writeInt(mId);
-            out.writeInt(mColorTransform);
-        }
-
-        @SuppressWarnings("hiding")
-        public static final Parcelable.Creator<ColorTransform> CREATOR
-                = new Parcelable.Creator<ColorTransform>() {
-            @Override
-            public ColorTransform createFromParcel(Parcel in) {
-                return new ColorTransform(in);
-            }
-
-            @Override
-            public ColorTransform[] newArray(int size) {
-                return new ColorTransform[size];
-            }
-        };
-    }
 }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 8aeeffd..49c3c46 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -169,14 +169,11 @@
      */
     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
 
-    /** The active color transform. */
-    public int colorTransformId;
+    /** The active color mode. */
+    public int colorMode;
 
-    /** The default color transform. */
-    public int defaultColorTransformId;
-
-    /** The list of supported color transforms */
-    public Display.ColorTransform[] supportedColorTransforms = Display.ColorTransform.EMPTY_ARRAY;
+    /** The list of supported color modes */
+    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
 
     /** The display's HDR capabilities */
     public Display.HdrCapabilities hdrCapabilities;
@@ -291,8 +288,8 @@
                 && rotation == other.rotation
                 && modeId == other.modeId
                 && defaultModeId == other.defaultModeId
-                && colorTransformId == other.colorTransformId
-                && defaultColorTransformId == other.defaultColorTransformId
+                && colorMode == other.colorMode
+                && Objects.equal(supportedColorModes, other.supportedColorModes)
                 && Objects.equal(hdrCapabilities, other.hdrCapabilities)
                 && logicalDensityDpi == other.logicalDensityDpi
                 && physicalXDpi == other.physicalXDpi
@@ -332,10 +329,9 @@
         modeId = other.modeId;
         defaultModeId = other.defaultModeId;
         supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
-        colorTransformId = other.colorTransformId;
-        defaultColorTransformId = other.defaultColorTransformId;
-        supportedColorTransforms = Arrays.copyOf(
-                other.supportedColorTransforms, other.supportedColorTransforms.length);
+        colorMode = other.colorMode;
+        supportedColorModes = Arrays.copyOf(
+                other.supportedColorModes, other.supportedColorModes.length);
         hdrCapabilities = other.hdrCapabilities;
         logicalDensityDpi = other.logicalDensityDpi;
         physicalXDpi = other.physicalXDpi;
@@ -373,12 +369,11 @@
         for (int i = 0; i < nModes; i++) {
             supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
         }
-        colorTransformId = source.readInt();
-        defaultColorTransformId = source.readInt();
-        int nColorTransforms = source.readInt();
-        supportedColorTransforms = new Display.ColorTransform[nColorTransforms];
-        for (int i = 0; i < nColorTransforms; i++) {
-            supportedColorTransforms[i] = Display.ColorTransform.CREATOR.createFromParcel(source);
+        colorMode = source.readInt();
+        int nColorModes = source.readInt();
+        supportedColorModes = new int[nColorModes];
+        for (int i = 0; i < nColorModes; i++) {
+            supportedColorModes[i] = source.readInt();
         }
         hdrCapabilities = source.readParcelable(null);
         logicalDensityDpi = source.readInt();
@@ -418,11 +413,10 @@
         for (int i = 0; i < supportedModes.length; i++) {
             supportedModes[i].writeToParcel(dest, flags);
         }
-        dest.writeInt(colorTransformId);
-        dest.writeInt(defaultColorTransformId);
-        dest.writeInt(supportedColorTransforms.length);
-        for (int i = 0; i < supportedColorTransforms.length; i++) {
-            supportedColorTransforms[i].writeToParcel(dest, flags);
+        dest.writeInt(colorMode);
+        dest.writeInt(supportedColorModes.length);
+        for (int i = 0; i < supportedColorModes.length; i++) {
+            dest.writeInt(supportedColorModes[i]);
         }
         dest.writeParcelable(hdrCapabilities, flags);
         dest.writeInt(logicalDensityDpi);
@@ -496,24 +490,6 @@
         return result;
     }
 
-    public Display.ColorTransform getColorTransform() {
-        return findColorTransform(colorTransformId);
-    }
-
-    public Display.ColorTransform getDefaultColorTransform() {
-        return findColorTransform(defaultColorTransformId);
-    }
-
-    private Display.ColorTransform findColorTransform(int colorTransformId) {
-        for (int i = 0; i < supportedColorTransforms.length; i++) {
-            Display.ColorTransform colorTransform = supportedColorTransforms[i];
-            if (colorTransform.getId() == colorTransformId) {
-                return colorTransform;
-            }
-        }
-        throw new IllegalStateException("Unable to locate color transform: " + colorTransformId);
-    }
-
     public void getAppMetrics(DisplayMetrics outMetrics) {
         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
@@ -615,12 +591,10 @@
         sb.append(defaultModeId);
         sb.append(", modes ");
         sb.append(Arrays.toString(supportedModes));
-        sb.append(", colorTransformId ");
-        sb.append(colorTransformId);
-        sb.append(", defaultColorTransformId ");
-        sb.append(defaultColorTransformId);
-        sb.append(", supportedColorTransforms ");
-        sb.append(Arrays.toString(supportedColorTransforms));
+        sb.append(", colorMode ");
+        sb.append(colorMode);
+        sb.append(", supportedColorModes ");
+        sb.append(Arrays.toString(supportedColorModes));
         sb.append(", hdrCapabilities ");
         sb.append(hdrCapabilities);
         sb.append(", rotation ");
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index f1abca8..e778a7f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -82,6 +82,10 @@
             IBinder displayToken);
     private static native int nativeGetActiveConfig(IBinder displayToken);
     private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
+    private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
+    private static native int nativeGetActiveColorMode(IBinder displayToken);
+    private static native boolean nativeSetActiveColorMode(IBinder displayToken,
+            int colorMode);
     private static native void nativeSetDisplayPowerMode(
             IBinder displayToken, int mode);
     private static native void nativeDeferTransactionUntil(long nativeObject,
@@ -547,7 +551,6 @@
         public boolean secure;
         public long appVsyncOffsetNanos;
         public long presentationDeadlineNanos;
-        public int colorTransform;
 
         public PhysicalDisplayInfo() {
         }
@@ -571,8 +574,7 @@
                     && yDpi == other.yDpi
                     && secure == other.secure
                     && appVsyncOffsetNanos == other.appVsyncOffsetNanos
-                    && presentationDeadlineNanos == other.presentationDeadlineNanos
-                    && colorTransform == other.colorTransform;
+                    && presentationDeadlineNanos == other.presentationDeadlineNanos;
         }
 
         @Override
@@ -590,7 +592,6 @@
             secure = other.secure;
             appVsyncOffsetNanos = other.appVsyncOffsetNanos;
             presentationDeadlineNanos = other.presentationDeadlineNanos;
-            colorTransform = other.colorTransform;
         }
 
         // For debugging purposes
@@ -599,8 +600,7 @@
             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
                     + ", appVsyncOffset " + appVsyncOffsetNanos
-                    + ", bufferDeadline " + presentationDeadlineNanos
-                    + ", colorTransform " + colorTransform + "}";
+                    + ", bufferDeadline " + presentationDeadlineNanos + "}";
         }
     }
 
@@ -632,6 +632,27 @@
         return nativeSetActiveConfig(displayToken, id);
     }
 
+    public static int[] getDisplayColorModes(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeGetDisplayColorModes(displayToken);
+    }
+
+    public static int getActiveColorMode(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeGetActiveColorMode(displayToken);
+    }
+
+    public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeSetActiveColorMode(displayToken, colorMode);
+    }
+
     public static void setDisplayProjection(IBinder displayToken,
             int orientation, Rect layerStackRect, Rect displayRect) {
         if (displayToken == null) {
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 81ec330..2dfa8cd 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -305,7 +305,18 @@
                 return;
             }
             if (!mIsEnabled) {
-                throw new IllegalStateException("Accessibility off. Did you forget to check that?");
+                Looper myLooper = Looper.myLooper();
+                if (myLooper == Looper.getMainLooper()) {
+                    throw new IllegalStateException(
+                            "Accessibility off. Did you forget to check that?");
+                } else {
+                    // If we're not running on the thread with the main looper, it's possible for
+                    // the state of accessibility to change between checking isEnabled and
+                    // calling this method. So just log the error rather than throwing the
+                    // exception.
+                    Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
+                    return;
+                }
             }
             userId = mUserId;
         }
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 4074166..7762675 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -24,10 +24,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
-import android.os.Binder;
 import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
@@ -329,6 +326,13 @@
     }
 
     private static class TN extends ITransientNotification.Stub {
+        final Runnable mShow = new Runnable() {
+            @Override
+            public void run() {
+                handleShow();
+            }
+        };
+
         final Runnable mHide = new Runnable() {
             @Override
             public void run() {
@@ -339,13 +343,7 @@
         };
 
         private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
-        final Handler mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                IBinder token = (IBinder) msg.obj;
-                handleShow(token);
-            }
-        };
+        final Handler mHandler = new Handler();
 
         int mGravity;
         int mX, mY;
@@ -381,9 +379,9 @@
          * schedule handleShow into the right thread
          */
         @Override
-        public void show(IBinder windowToken) {
+        public void show() {
             if (localLOGV) Log.v(TAG, "SHOW: " + this);
-            mHandler.obtainMessage(0, windowToken).sendToTarget();
+            mHandler.post(mShow);
         }
 
         /**
@@ -395,7 +393,7 @@
             mHandler.post(mHide);
         }
 
-        public void handleShow(IBinder windowToken) {
+        public void handleShow() {
             if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                     + " mNextView=" + mNextView);
             if (mView != mNextView) {
@@ -426,7 +424,6 @@
                 mParams.packageName = packageName;
                 mParams.removeTimeoutMilliseconds = mDuration ==
                     Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
-                mParams.token = windowToken;
                 if (mView.getParent() != null) {
                     if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                     mWM.removeView(mView);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index ca69746..5623a2c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -79,6 +79,8 @@
             String newHistoryName, int newType, boolean newUnimportantForLogging);
     void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName,
             int type);
+    void noteLongPartialWakelockStart(String name, String historyName, int uid);
+    void noteLongPartialWakelockFinish(String name, String historyName, int uid);
 
     void noteVibratorOn(int uid, long durationMillis);
     void noteVibratorOff(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 11c1de1..b174e33 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3285,6 +3285,36 @@
         }
     }
 
+    public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
+        uid = mapUid(uid);
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        final long uptime = mClocks.uptimeMillis();
+        if (historyName == null) {
+            historyName = name;
+        }
+        if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
+                0)) {
+            return;
+        }
+        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
+                historyName, uid);
+    }
+
+    public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
+        uid = mapUid(uid);
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        final long uptime = mClocks.uptimeMillis();
+        if (historyName == null) {
+            historyName = name;
+        }
+        if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
+                0)) {
+            return;
+        }
+        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
+                historyName, uid);
+    }
+
     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
         if (mLastWakeupReason != null) {
             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index fa1313b..0d8a95c 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -32,6 +32,7 @@
 #include <jni.h>
 #include <memory>
 #include <stdio.h>
+#include <system/graphics.h>
 #include <ui/DisplayInfo.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/FrameStats.h>
@@ -58,7 +59,6 @@
     jfieldID secure;
     jfieldID appVsyncOffsetNanos;
     jfieldID presentationDeadlineNanos;
-    jfieldID colorTransform;
 } gPhysicalDisplayInfoClassInfo;
 
 static struct {
@@ -429,8 +429,6 @@
                 info.appVsyncOffset);
         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
                 info.presentationDeadline);
-        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.colorTransform,
-                info.colorTransform);
         env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
         env->DeleteLocalRef(infoObj);
     }
@@ -451,6 +449,43 @@
     return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
 }
 
+static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return NULL;
+    Vector<android_color_mode_t> colorModes;
+    if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR ||
+            colorModes.isEmpty()) {
+        return NULL;
+    }
+
+    jintArray colorModesArray = env->NewIntArray(colorModes.size());
+    if (colorModesArray == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return NULL;
+    }
+    jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
+    for (size_t i = 0; i < colorModes.size(); i++) {
+        colorModesArrayValues[i] = static_cast<jint>(colorModes[i]);
+    }
+    env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
+    return colorModesArray;
+}
+
+static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return -1;
+    return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
+}
+
+static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass,
+        jobject tokenObj, jint colorMode) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+    status_t err = SurfaceComposerClient::setActiveColorMode(token,
+            static_cast<android_color_mode_t>(colorMode));
+    return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
+}
+
 static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == NULL) return;
@@ -715,6 +750,12 @@
             (void*)nativeGetActiveConfig },
     {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
             (void*)nativeSetActiveConfig },
+    {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
+            (void*)nativeGetDisplayColorModes},
+    {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I",
+            (void*)nativeGetActiveColorMode},
+    {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
+            (void*)nativeSetActiveColorMode},
     {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
             (void*)nativeGetHdrCapabilities },
     {"nativeClearContentFrameStats", "(J)Z",
@@ -757,8 +798,6 @@
             clazz, "appVsyncOffsetNanos", "J");
     gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env,
             clazz, "presentationDeadlineNanos", "J");
-    gPhysicalDisplayInfoClassInfo.colorTransform = GetFieldIDOrDie(env, clazz,
-            "colorTransform", "I");
 
     jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect");
     gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4b66f70..48dfdff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2508,11 +2508,10 @@
     <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
         android:protectionLevel="signature" />
 
-    <!-- Allows an application to control the color transforms applied to
-         displays system-wide.
+    <!-- Allows an application to control the color modes set for displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
-    <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
+    <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
         android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to control VPN.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 674a0d7..2835c6f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1825,28 +1825,6 @@
     -->
     <bool name="config_enableWifiDisplay">false</bool>
 
-    <!-- The color transform values that correspond to each respective configuration mode for the
-         built-in display, or -1 if the mode is unsupported by the device. The possible
-         configuration modes are:
-            1. Wide-gamut ("Vibrant")
-            2. Adobe RGB ("Natural")
-            3. sRGB ("Standard")
-
-        For example, if a device had Wide-gamut as color transform mode 1, sRGB mode as color
-        transform mode 7, and did not support Adobe RGB at all this would look like:
-
-            <integer-array name="config_colorTransforms">
-                <item>1</item>
-                <item>-1</item>
-                <item>7</item>
-            </integer-array>
-    -->
-    <integer-array name="config_colorTransforms">
-        <item>-1</item>
-        <item>-1</item>
-        <item>-1</item>
-    </integer-array>
-
     <!-- When true, local displays that do not contain any of their own content will automatically
          mirror the content of the default display. -->
     <bool name="config_localDisplaysMirrorContent">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3590ac8..38749f6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1142,7 +1142,6 @@
   <java-symbol type="array" name="config_telephonyHardware" />
   <java-symbol type="array" name="config_keySystemUuidMapping" />
   <java-symbol type="array" name="config_gpsParameters" />
-  <java-symbol type="array" name="config_colorTransforms" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
   <java-symbol type="drawable" name="default_lock_wallpaper" />
diff --git a/docs/html/guide/topics/sensors/sensors_position.jd b/docs/html/guide/topics/sensors/sensors_position.jd
index d0ddead..5ec16c7 100644
--- a/docs/html/guide/topics/sensors/sensors_position.jd
+++ b/docs/html/guide/topics/sensors/sensors_position.jd
@@ -8,7 +8,7 @@
   <ol>
     <li><a href="#sensors-pos-gamerot">Using the Game Rotation Vector Sensor</a></li>
     <li><a href="#sensors-pos-geomrot">Using the Geomagnetic Rotation Vector Sensor</a></li>
-    <li><a href="#sensors-pos-orient">Using the Orientation Sensor</a></li>
+    <li><a href="#sensors-pos-orient">Computing the Device's Orientation</a></li>
     <li><a href="#sensors-pos-mag">Using the Geomagnetic Field Sensor</a></li>
     <li><a href="#sensors-pos-prox">Using the Proximity Sensor</a></li>
   </ol>
@@ -42,38 +42,49 @@
   </div>
 </div>
 
-<p>The Android platform provides two sensors that let you determine the position of a device: the
-geomagnetic field sensor and the orientation sensor. The Android platform also
-provides a sensor that lets you determine how close the face of a device is to an object (known as
-the proximity sensor). The geomagnetic field sensor and the proximity sensor are hardware-based.
-Most
-handset and tablet manufacturers include a geomagnetic field sensor. Likewise, handset manufacturers
-usually include a proximity sensor to determine when a handset is being held close to a user's face
-(for example, during a phone call). The orientation sensor is software-based and derives its data
-from the accelerometer and the geomagnetic field sensor.</p>
+<p>
+  The Android platform provides two sensors that let you determine the position
+  of a device: the geomagnetic field sensor and the accelerometer. The Android
+  platform also provides a sensor that lets you determine how close the face of
+  a device is to an object (known as the <em>proximity sensor</em>). The
+  geomagnetic field sensor and the proximity sensor are hardware-based. Most
+  handset and tablet manufacturers include a geomagnetic field sensor. Likewise,
+  handset manufacturers usually include a proximity sensor to determine when a
+  handset is being held close to a user's face (for example, during a phone
+  call). For determining a device's orientation, you can use the readings from
+  the device's accelerometer and the geomagnetic field sensor.
+</p>
 
-<p class="note"><strong>Note:</strong> The orientation sensor was deprecated in Android 2.2 (API
-Level 8).</p>
+<p class="note">
+  <strong>Note:</strong> The orientation sensor was deprecated in Android 2.2
+  (API level 8), and the orientation sensor type was deprecated in Android 4.4W
+  (API level 20).
+</p>
 
-<p>Position sensors are useful for determining a device's physical position in the
-world's frame of reference. For example, you can use the geomagnetic field sensor in
-combination with the accelerometer to determine a device's position relative to
-the magnetic North Pole. You can also use the orientation sensor (or similar sensor-based
-orientation methods) to determine a device's position in your application's frame of reference.
-Position sensors are not typically used to monitor device movement or motion, such as shake, tilt,
-or thrust (for more information, see <a
-href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion Sensors</a>).</p>
+<p>
+  Position sensors are useful for determining a device's physical position in
+  the world's frame of reference. For example, you can use the geomagnetic field
+  sensor in combination with the accelerometer to determine a device's position
+  relative to the magnetic north pole. You can also use these sensors to
+  determine a device's orientation in your application's frame of reference.
+  Position sensors are not typically used to monitor device movement or motion,
+  such as shake, tilt, or thrust (for more information, see <a
+  href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion Sensors</a>).
+</p>
 
-<p>The geomagnetic field sensor and orientation sensor return multi-dimensional arrays of sensor
-values
-for each {@link android.hardware.SensorEvent}. For example, the orientation sensor provides
-geomagnetic
-field strength values for each of the three coordinate axes during a single sensor event. Likewise,
-the orientation sensor provides azimuth (yaw), pitch, and roll values during a single sensor event.
-For more information about the coordinate systems that are used by sensors, see <a
-href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">Sensor Coordinate
-Systems</a>. The proximity sensor provides a single value for each sensor event. Table 1 summarizes
-the position sensors that are supported on the Android platform.</p>
+<p>
+  The geomagnetic field sensor and accelerometer return multi-dimensional arrays
+  of sensor values for each {@link android.hardware.SensorEvent}. For example,
+  the geomagnetic field sensor provides geomagnetic field strength values for
+  each of the three coordinate axes during a single sensor event. Likewise, the
+  accelerometer sensor measures the acceleration applied to the device during a
+  sensor event. For more information about the coordinate systems that are used
+  by sensors, see <a
+  href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">
+  Sensor Coordinate Systems</a>. The proximity sensor provides a single value
+  for each sensor event. Table 1 summarizes the position sensors that are
+  supported on the Android platform.
+</p>
 
 <p class="table-caption" id="table1">
   <strong>Table 1.</strong> Position sensors that are supported on the Android platform.</p>
@@ -174,14 +185,17 @@
   </tr>
 </table>
 
-<p class="note"><sup><strong>1</strong></sup> This sensor was deprecated in Android 2.2 (API Level
-  8). The sensor framework provides alternate methods for acquiring device orientation, which are
-discussed in <a href="#sensors-pos-orient">Using the Orientation Sensor</a>.</p>
+<p class="note">
+  <sup><strong>1</strong></sup>This sensor was deprecated in Android 2.2 (API
+  level 8), and this sensor type was deprecated in Android 4.4W (API level 20).
+  The sensor framework provides alternate methods for acquiring device
+  orientation, which are discussed in <a href="#sensors-pos-orient">Computing
+  the Device's Orientation</a>.
+</p>
 
 <p class="note"><sup><strong>2</strong></sup> Some proximity sensors provide only binary values
 representing near and far.</p>
 
-
 <h2 id="sensors-pos-gamerot">Using the Game Rotation Vector Sensor</h2>
 
 <p>The game rotation vector sensor is identical to the
@@ -228,71 +242,106 @@
 </pre>
 
 
-<h2 id="sensors-pos-orient">Using the Orientation Sensor</h2>
+<h2 id="sensors-pos-orient">Computing the Device's Orientation</h2>
 
-<p>The orientation sensor lets you monitor the position of a device relative to the earth's frame of
-reference (specifically, magnetic north). The following code shows you how to get an instance of the
-default orientation sensor:</p>
-
+<p>By computing a device's orientation, you can monitor the position of the
+  device relative to the earth's frame of reference (specifically, the magnetic
+  north pole). The following code shows you how to compute a device's
+  orientation:
+</p>
 <pre>
 private SensorManager mSensorManager;
-private Sensor mSensor;
 ...
-mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
-mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+// Rotation matrix based on current readings from accelerometer and magnetometer.
+final float[] rotationMatrix = new float[9];
+mSensorManager.getRotationMatrix(rotationMatrix, null,
+  accelerometerReading, magnetometerReading);
+
+// Express the updated rotation matrix as three orientation angles.
+final float[] orientationAngles = new float[3];
+mSensorManager.getOrientation(rotationMatrix, orientationAngles);
 </pre>
-
-<p>The orientation sensor derives its data by using a device's geomagnetic field sensor in
-combination with a device's accelerometer. Using these two hardware sensors, an orientation sensor
-provides data for the following three dimensions:</p>
-
+<p>The system computes the orientation angles by using a device's geomagnetic
+  field sensor in combination with the device's accelerometer. Using these two
+  hardware sensors, the system provides data for the following three
+  orientation angles:
+</p>
 <ul>
-  <li>Azimuth (degrees of rotation around the z axis). This is the angle between magnetic north
-and the device's y axis. For example, if the device's y axis is aligned with magnetic north
-this value is 0, and if the device's y axis is pointing south this value is 180. Likewise, when
-the y axis is pointing east this value is 90 and when it is pointing west this value is 270.</li>
-  <li>Pitch (degrees of rotation around the x axis). This value is positive when the positive z axis
-rotates toward the positive y axis, and it is negative when the positive z axis
-rotates toward the negative y axis. The range of values is 180 degrees to -180
-degrees.</li>
-  <li>Roll (degrees of rotation around the y axis). This value is positive when the positive z axis
-rotates toward the positive x axis, and it is negative when the positive z axis
-rotates toward the negative x axis. The range of values is 90 degrees to -90
-degrees.</li>
+  <li>
+    <strong>Azimuth (degrees of rotation about the -z axis).</strong> This is
+    the angle between the device's current compass direction and magnetic north.
+    If the top edge of the device faces magnetic north, the azimuth is 0
+    degrees; if the top edge faces south, the azimuth is 180 degrees. Similarly,
+    if the top edge faces east, the azimuth is 90 degrees, and if the top edge
+    faces west, the azimuth is 270 degrees.
+  </li>
+  <li>
+    <strong>Pitch (degrees of rotation about the x axis).</strong> This is the
+    angle between a plane parallel to the device's screen and a plane parallel
+    to the ground. If you hold the device parallel to the ground with the bottom
+    edge closest to you and tilt the top edge of the device toward the ground,
+    the pitch angle becomes positive. Tilting in the opposite direction&mdash;
+    moving the top edge of the device away from the ground&mdash;causes
+    the pitch angle to become negative. The range of values is -180 degrees to
+    180 degrees.
+  </li>
+  <li>
+    <strong>Roll (degrees of rotation about the y axis).</strong> This is the
+    angle between a plane perpendicular to the device's screen and a plane
+    perpendicular to the ground. If you hold the device parallel to the ground
+    with the bottom edge closest to you and tilt the left edge of the device
+    toward the ground, the roll angle becomes positive. Tilting in the opposite
+    direction&mdash;moving the right edge of the device toward the ground&mdash;
+    causes the roll angle to become negative. The range of values is -90 degrees
+    to 90 degrees.
+  </li>
 </ul>
 
-<p>This definition is different from yaw, pitch, and roll used in aviation, where the X axis is
-along the long side of the plane (tail to nose). Also, for historical reasons the roll angle is
-positive in the clockwise direction (mathematically speaking, it should be positive in the
-counter-clockwise direction).</p>
+<p class="note">
+  <strong>Note:</strong>The sensor's roll definition has changed to reflect the
+  vast majority of implementations in the geosensor ecosystem.
+</p>
 
-<p>The orientation sensor derives its data by processing the raw sensor data from the accelerometer
-and the geomagnetic field sensor. Because of the heavy processing that is involved, the accuracy and
-precision of the orientation sensor is diminished (specifically, this sensor is only reliable when
-the roll component is 0). As a result, the orientation sensor was deprecated in Android 2.2 (API
-level 8). Instead of using raw data from the orientation sensor, we recommend that you use the
-{@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()} method in conjunction
-with the {@link android.hardware#getOrientation getOrientation()} method to compute orientation
-values. You can also use the {@link android.hardware.SensorManager#remapCoordinateSystem
-remapCoordinateSystem()} method to translate the orientation values to your application's frame of
-reference.</p>
+<p>
+  Note that these angles work off of a different coordinate system than the
+  one used in aviation (for yaw, pitch, and roll). In the aviation system, the
+  x axis is along the long side of the plane, from tail to nose.
+</p>
 
-<p>The following code sample shows how to acquire orientation data directly from the orientation
-sensor. We recommend that you do this only if a device has negligible roll.</p>
+<p>
+  The orientation sensor derives its data by processing the raw sensor data
+  from the accelerometer and the geomagnetic field sensor. Because of the heavy
+  processing that is involved, the accuracy and precision of the orientation
+  sensor is diminished. Specifically, this sensor is reliable only when the roll
+  angle is 0. As a result, the orientation sensor was deprecated in Android
+  2.2 (API level 8), and the orientation sensor type was deprecated in Android
+  4.4W (API level 20).
 
+  Instead of using raw data from the orientation sensor, we recommend that you
+  use the {@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()}
+  method in conjunction with the
+  {@link android.hardware.SensorManager#getOrientation getOrientation()} method
+  to compute orientation values, as shown in the following code sample. As part
+  of this process, you can use the
+  {@link android.hardware.SensorManager#remapCoordinateSystem remapCoordinateSystem()}
+  method to translate the orientation values to your application's frame of
+  reference.
+</p>
 <pre>
 public class SensorActivity extends Activity implements SensorEventListener {
 
   private SensorManager mSensorManager;
-  private Sensor mOrientation;
+  private final float[] mAccelerometerReading = new float[3];
+  private final float[] mMagnetometerReading = new float[3];
+
+  private final float[] mRotationMatrix = new float[9];
+  private final float[] mOrientationAngles = new float[3];
 
   &#64;Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
-
     mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
-    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
   }
 
   &#64;Override
@@ -304,31 +353,63 @@
   &#64;Override
   protected void onResume() {
     super.onResume();
-    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL);
+
+    // Get updates from the accelerometer and magnetometer at a constant rate.
+    // To make batch operations more efficient and reduce power consumption,
+    // provide support for delaying updates to the application.
+    //
+    // In this example, the sensor reporting delay is small enough such that
+    // the application receives an update before the system checks the sensor
+    // readings again.
+    mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER,
+      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
+    mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD,
+      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
   }
 
   &#64;Override
   protected void onPause() {
     super.onPause();
+
+    // Don't receive any more updates from either sensor.
     mSensorManager.unregisterListener(this);
   }
 
+  // Get readings from accelerometer and magnetometer. To simplify calculations,
+  // consider storing these readings as unit vectors.
   &#64;Override
   public void onSensorChanged(SensorEvent event) {
-    float azimuth_angle = event.values[0];
-    float pitch_angle = event.values[1];
-    float roll_angle = event.values[2];
-    // Do something with these orientation angles.
+    if (event.sensor == Sensor.TYPE_ACCELEROMETER) {
+      System.arraycopy(event.values, 0, mAccelerometerReading,
+        0, mAccelerometerReading.length);
+    }
+    else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) {
+      System.arraycopy(event.values, 0, mMagnetometerReading,
+        0, mMagnetometerReading.length);
+    }
+  }
+
+  // Compute the three orientation angles based on the most recent readings from
+  // the device's accelerometer and magnetometer.
+  public void updateOrientationAngles() {
+    // Update rotation matrix, which is needed to update orientation angles.
+    mSensorManager.getRotationMatrix(mRotationMatrix, null,
+      mAccelerometerReading, mMagnetometerReading);
+
+    // "mRotationMatrix" now has up-to-date information.
+
+    mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);
+
+    // "mOrientationAngles" now has up-to-date information.
   }
 }
 </pre>
 
-<p>You do not usually need to perform any data processing or filtering of the raw data that you
-obtain from an orientation sensor, other than translating the sensor's coordinate system to your
-application's frame of reference. The <a
-href="{@docRoot}resources/samples/AccelerometerPlay/index.html">Accelerometer Play</a> sample shows
-you how to translate acceleration sensor data into another frame of reference; the technique is
-similar to the one you might use with the orientation sensor.</p>
+<p>
+  You don't usually need to perform any data processing or filtering of the
+  device's raw orientation angles other than translating the sensor's
+  coordinate system to your application's frame of reference.
+</p>
 
 <h2 id="sensors-pos-mag">Using the Geomagnetic Field Sensor</h2>
 
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 146e735..9956975 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -33,7 +33,6 @@
     false, // secure?
     0, // appVsyncOffset
     0, // presentationDeadline
-    0, // colorTransform
 };
 
 DisplayInfo getBuiltInDisplay() {
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index f7becf5..da490b9 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -69,8 +69,9 @@
 
     // More video file types
     public static final int FILE_TYPE_MP2PS   = 200;
+    public static final int FILE_TYPE_QT      = 201;
     private static final int FIRST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS;
-    private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS;
+    private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_QT;
 
     // Image file types
     public static final int FILE_TYPE_JPEG    = 31;
@@ -211,6 +212,8 @@
         addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG);
         addFileType("MP4", FILE_TYPE_MP4, "video/mp4", MtpConstants.FORMAT_MPEG);
         addFileType("M4V", FILE_TYPE_M4V, "video/mp4", MtpConstants.FORMAT_MPEG);
+        addFileType("MOV", FILE_TYPE_QT, "video/quicktime", MtpConstants.FORMAT_MPEG);
+
         addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp",  MtpConstants.FORMAT_3GP_CONTAINER);
         addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER);
         addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2", MtpConstants.FORMAT_3GP_CONTAINER);
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index e67cc8a..c2d4d04 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Title of the documents application [CHAR LIMIT=32] -->
-    <string name="app_label">Documents</string>
+    <string name="app_label">Files</string>
 
     <!-- Title of the standalone downloads activity. [CHAR LIMIT=32] -->
     <string name="downloads_label">Downloads</string>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 525d6f4..b8e6d20 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -362,4 +362,12 @@
         <item>3</item>
     </string-array>
 
+    <!-- IDs for each color mode. The values must match the corresponding constants in
+         android.view.Display -->
+    <integer-array name="color_mode_ids">
+        <item>0</item>
+        <item>-1</item>
+        <item>7</item>
+    </integer-array>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 575f198..6bc94b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -178,8 +178,8 @@
     @Override
     public void updateQsTile(Tile tile, IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             synchronized (mServices) {
                 final TileServiceManager tileServiceManager = mServices.get(customTile);
                 tileServiceManager.clearPendingBind();
@@ -193,8 +193,8 @@
     @Override
     public void onStartSuccessful(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             synchronized (mServices) {
                 final TileServiceManager tileServiceManager = mServices.get(customTile);
                 tileServiceManager.clearPendingBind();
@@ -206,8 +206,8 @@
     @Override
     public void onShowDialog(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             customTile.onDialogShown();
             mHost.collapsePanels();
             mServices.get(customTile).setShowingDialog(true);
@@ -217,8 +217,8 @@
     @Override
     public void onDialogHidden(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             mServices.get(customTile).setShowingDialog(false);
             customTile.onDialogHidden();
         }
@@ -227,8 +227,8 @@
     @Override
     public void onStartActivity(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             mHost.collapsePanels();
         }
     }
@@ -236,8 +236,8 @@
     @Override
     public void updateStatusIcon(IBinder token, Icon icon, String contentDescription) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             try {
                 ComponentName componentName = customTile.getComponent();
                 String packageName = componentName.getPackageName();
@@ -266,8 +266,8 @@
     @Override
     public Tile getTile(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             return customTile.getQsTile();
         }
         return null;
@@ -276,8 +276,8 @@
     @Override
     public void startUnlockAndRun(IBinder token) {
         CustomTile customTile = getTileForToken(token);
-        verifyCaller(customTile);
         if (customTile != null) {
+            verifyCaller(customTile);
             customTile.startUnlockAndRun();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8530d66..4c3bd7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -472,20 +472,28 @@
                 }
             }
 
-            riv.setVisibility(View.VISIBLE);
-            int cx = view.getLeft() + view.getWidth() / 2;
+            int width = view.getWidth();
+            if (view instanceof TextView) {
+                // Center the reveal on the text which might be off-center from the TextView
+                TextView tv = (TextView) view;
+                if (tv.getLayout() != null) {
+                    int innerWidth = (int) tv.getLayout().getLineWidth(0);
+                    innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
+                    width = Math.min(width, innerWidth);
+                }
+            }
+            int cx = view.getLeft() + width / 2;
             int cy = view.getTop() + view.getHeight() / 2;
             int w = riv.getWidth();
             int h = riv.getHeight();
             int r = Math.max(
                     Math.max(cx + cy, cx + (h - cy)),
                     Math.max((w - cx) + cy, (w - cx) + (h - cy)));
-            ViewAnimationUtils.createCircularReveal(riv, cx, cy, 0, r)
-                    .start();
 
+            riv.setRevealParameters(cx, cy, r);
             riv.setPendingIntent(pendingIntent);
             riv.setRemoteInput(inputs, input);
-            riv.focus();
+            riv.focusAnimated();
 
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 9a21a1e..91b21ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
@@ -42,6 +43,7 @@
     private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
 
     private final CameraManager mCameraManager;
+    private final Context mContext;
     /** Call {@link #ensureHandler()} before using */
     private Handler mHandler;
 
@@ -51,20 +53,22 @@
     /** Lock on {@code this} when accessing */
     private boolean mFlashlightEnabled;
 
-    private final String mCameraId;
+    private String mCameraId;
     private boolean mTorchAvailable;
 
-    public FlashlightController(Context mContext) {
+    public FlashlightController(Context context) {
+        mContext = context;
         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
 
-        String cameraId = null;
+        tryInitCamera();
+    }
+
+    private void tryInitCamera() {
         try {
-            cameraId = getCameraId();
+            mCameraId = getCameraId();
         } catch (Throwable e) {
             Log.e(TAG, "Couldn't initialize.", e);
             return;
-        } finally {
-            mCameraId = cameraId;
         }
 
         if (mCameraId != null) {
@@ -94,7 +98,7 @@
     }
 
     public boolean hasFlashlight() {
-        return mCameraId != null;
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
     }
 
     public synchronized boolean isEnabled() {
@@ -107,6 +111,9 @@
 
     public void addListener(FlashlightListener l) {
         synchronized (mListeners) {
+            if (mCameraId == null) {
+                tryInitCamera();
+            }
             cleanUpListenersLocked(l);
             mListeners.add(new WeakReference<>(l));
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index a2289c8..38dbaee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
@@ -33,6 +35,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.inputmethod.CompletionInfo;
@@ -47,11 +50,13 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.stack.ScrollContainer;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 /**
  * Host for the remote input.
@@ -77,6 +82,10 @@
     private View mScrollContainerChild;
     private boolean mRemoved;
 
+    private int mRevealCx;
+    private int mRevealCy;
+    private int mRevealR;
+
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -180,14 +189,28 @@
         return true;
     }
 
-    public void onDefocus() {
+    private void onDefocus(boolean animate) {
         mController.removeRemoteInput(mEntry);
         mEntry.remoteInputText = mEditText.getText();
 
         // During removal, we get reattached and lose focus. Not hiding in that
         // case to prevent flicker.
         if (!mRemoved) {
-            setVisibility(INVISIBLE);
+            if (animate && mRevealR > 0) {
+                Animator reveal = ViewAnimationUtils.createCircularReveal(
+                        this, mRevealCx, mRevealCy, mRevealR, 0);
+                reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+                reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
+                reveal.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        setVisibility(INVISIBLE);
+                    }
+                });
+                reveal.start();
+            } else {
+                setVisibility(INVISIBLE);
+            }
         }
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
                 mEntry.notification.getPackageName());
@@ -223,6 +246,17 @@
         mEditText.setHint(mRemoteInput.getLabel());
     }
 
+    public void focusAnimated() {
+        if (getVisibility() != VISIBLE) {
+            Animator animator = ViewAnimationUtils.createCircularReveal(
+                    this, mRevealCx, mRevealCy, 0, mRevealR);
+            animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            animator.start();
+        }
+        focus();
+    }
+
     public void focus() {
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_OPEN,
                 mEntry.notification.getPackageName());
@@ -253,7 +287,7 @@
         mProgressBar.setVisibility(INVISIBLE);
         mController.removeSpinning(mEntry.key);
         updateSendButton();
-        onDefocus();
+        onDefocus(false /* animate */);
     }
 
     private void updateSendButton() {
@@ -272,7 +306,7 @@
     }
 
     public void close() {
-        mEditText.defocusIfNeeded();
+        mEditText.defocusIfNeeded(false /* animated */);
     }
 
     @Override
@@ -321,6 +355,7 @@
         other.close();
         setPendingIntent(other.mPendingIntent);
         setRemoteInput(other.mRemoteInputs, other.mRemoteInput);
+        setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
         focus();
     }
 
@@ -374,6 +409,12 @@
         mRemoved = true;
     }
 
+    public void setRevealParameters(int cx, int cy, int r) {
+        mRevealCx = cx;
+        mRevealCy = cy;
+        mRevealR = r;
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -389,14 +430,14 @@
             mBackground = getBackground();
         }
 
-        private void defocusIfNeeded() {
+        private void defocusIfNeeded(boolean animate) {
             if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
                 return;
             }
             if (isFocusable() && isEnabled()) {
                 setInnerFocusable(false);
                 if (mRemoteInputView != null) {
-                    mRemoteInputView.onDefocus();
+                    mRemoteInputView.onDefocus(animate);
                 }
                 mShowImeOnInputConnection = false;
             }
@@ -407,7 +448,7 @@
             super.onVisibilityChanged(changedView, visibility);
 
             if (!isShown()) {
-                defocusIfNeeded();
+                defocusIfNeeded(false /* animate */);
             }
         }
 
@@ -415,7 +456,7 @@
         protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
             super.onFocusChanged(focused, direction, previouslyFocusedRect);
             if (!focused) {
-                defocusIfNeeded();
+                defocusIfNeeded(true /* animate */);
             }
         }
 
@@ -434,7 +475,7 @@
         @Override
         public boolean onKeyPreIme(int keyCode, KeyEvent event) {
             if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
-                defocusIfNeeded();
+                defocusIfNeeded(true /* animate */);
                 final InputMethodManager imm = InputMethodManager.getInstance();
                 imm.hideSoftInputFromWindow(getWindowToken(), 0);
                 return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 659eaf7..3804b42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -44,6 +44,7 @@
     public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
     public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
     public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
+    public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
     public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 650;
     public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 230;
     public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ba59c2f0..0106f7f0 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2177,7 +2177,7 @@
     // CATEGORY: SETTINGS
     ACTION_SUPPORT_DIAL_TOLLED = 487;
 
-    // OPEN: Settings > Display > Night display
+    // OPEN: Settings > Display > Night Light
     // CATEGORY: SETTINGS
     NIGHT_DISPLAY_SETTINGS = 488;
 
@@ -2188,12 +2188,15 @@
     // Settings launched from collapsed quick settings.
     ACTION_QS_COLLAPSED_SETTINGS_LAUNCH = 490;
 
-    // OPEN: QS Night mode tile shown
-    // ACTION: QS Night mode tile tapped
+    // OPEN: QS Night Light tile shown
+    // ACTION: QS Night Light tile tapped
     //   SUBTYPE: 0 is off, 1 is on
     // CATEGORY: QUICK_SETTINGS
     QS_NIGHT_DISPLAY = 491;
 
+    // Night Light on
+    SETTINGS_CONDITION_NIGHT_DISPLAY = 492;
+
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 7fe29b0..ff13125 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -484,6 +484,20 @@
         }
     }
 
+    public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteLongPartialWakelockStart(name, historyName, uid);
+        }
+    }
+
+    public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteLongPartialWakelockFinish(name, historyName, uid);
+        }
+    }
+
     public void noteStartSensor(int uid, int sensor) {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/services/core/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java
index 701b9f1..6ba25a5 100644
--- a/services/core/java/com/android/server/display/DisplayAdapter.java
+++ b/services/core/java/com/android/server/display/DisplayAdapter.java
@@ -49,13 +49,6 @@
      */
     private static final AtomicInteger NEXT_DISPLAY_MODE_ID = new AtomicInteger(1);  // 0 = no mode.
 
-    /**
-     * Used to generate globally unique color transform ids.
-     *
-     * Valid IDs start at 1 with 0 as the sentinel value for the default mode.
-     */
-    private static final AtomicInteger NEXT_COLOR_TRANSFORM_ID = new AtomicInteger(1);
-
     // Called with SyncRoot lock held.
     public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener, String name) {
@@ -141,11 +134,6 @@
                 NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate);
     }
 
-    public static Display.ColorTransform createColorTransform(int colorTransform) {
-        return new Display.ColorTransform(
-                NEXT_COLOR_TRANSFORM_ID.getAndIncrement(), colorTransform);
-    }
-
     public interface Listener {
         public void onDisplayDeviceEvent(DisplayDevice device, int event);
         public void onTraversalRequested();
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7af0bdb..839ab4d 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -94,6 +94,11 @@
     }
 
     /**
+     * Returns whether the unique id of the device is stable across reboots.
+     */
+    public abstract boolean hasStableUniqueId();
+
+    /**
      * Gets information about the display device.
      *
      * The information returned should not change between calls unless the display
@@ -135,7 +140,7 @@
     /**
      * Sets the mode, if supported.
      */
-    public void requestColorTransformAndModeInTransactionLocked(int colorTransformId, int modeId) {
+    public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 5ce66fa..6719182 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -118,6 +118,11 @@
     public static final int DIFF_OTHER = 1 << 1;
 
     /**
+     * Diff result: The color mode fields differ.
+     */
+    public static final int DIFF_COLOR_MODE = 1 << 2;
+
+    /**
      * Gets the name of the display device, which may be derived from EDID or
      * other sources. The name may be localized and displayed to the user.
      */
@@ -155,14 +160,11 @@
      */
     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
 
-    /** The active color transform of the display */
-    public int colorTransformId;
+    /** The active color mode of the display */
+    public int colorMode;
 
-    /** The default color transform of the display */
-    public int defaultColorTransformId;
-
-    /** The supported color transforms of the display */
-    public Display.ColorTransform[] supportedColorTransforms = Display.ColorTransform.EMPTY_ARRAY;
+    /** The supported color modes of the display */
+    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
 
     /**
      * The HDR capabilities this display claims to support.
@@ -283,6 +285,9 @@
         if (state != other.state) {
             diff |= DIFF_STATE;
         }
+        if (colorMode != other.colorMode) {
+            diff |= DIFF_COLOR_MODE;
+        }
         if (!Objects.equal(name, other.name)
                 || !Objects.equal(uniqueId, other.uniqueId)
                 || width != other.width
@@ -290,9 +295,7 @@
                 || modeId != other.modeId
                 || defaultModeId != other.defaultModeId
                 || !Arrays.equals(supportedModes, other.supportedModes)
-                || colorTransformId != other.colorTransformId
-                || defaultColorTransformId != other.defaultColorTransformId
-                || !Arrays.equals(supportedColorTransforms, other.supportedColorTransforms)
+                || !Arrays.equals(supportedColorModes, other.supportedColorModes)
                 || !Objects.equal(hdrCapabilities, other.hdrCapabilities)
                 || densityDpi != other.densityDpi
                 || xDpi != other.xDpi
@@ -324,9 +327,8 @@
         modeId = other.modeId;
         defaultModeId = other.defaultModeId;
         supportedModes = other.supportedModes;
-        colorTransformId = other.colorTransformId;
-        defaultColorTransformId = other.defaultColorTransformId;
-        supportedColorTransforms = other.supportedColorTransforms;
+        colorMode = other.colorMode;
+        supportedColorModes = other.supportedColorModes;
         hdrCapabilities = other.hdrCapabilities;
         densityDpi = other.densityDpi;
         xDpi = other.xDpi;
@@ -353,9 +355,8 @@
         sb.append(", modeId ").append(modeId);
         sb.append(", defaultModeId ").append(defaultModeId);
         sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
-        sb.append(", colorTransformId ").append(colorTransformId);
-        sb.append(", defaultColorTransformId ").append(defaultColorTransformId);
-        sb.append(", supportedColorTransforms ").append(Arrays.toString(supportedColorTransforms));
+        sb.append(", colorMode ").append(colorMode);
+        sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
         sb.append(", HdrCapabilities ").append(hdrCapabilities);
         sb.append(", density ").append(densityDpi);
         sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index fec7ed1..0abd2e7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -239,6 +239,11 @@
 
     @Override
     public void onStart() {
+        // We need to pre-load the persistent data store so it's ready before the default display
+        // adapter is up so that we have it's configuration. We could load it lazily, but since
+        // we're going to have to read it in eventually we may as well do it here rather than after
+        // we've waited for the diplay to register itself with us.
+        mPersistentDataStore.loadIfNeeded();
         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
 
         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
@@ -541,12 +546,12 @@
         }
     }
 
-    private void requestColorTransformInternal(int displayId, int colorTransformId) {
+    private void requestColorModeInternal(int displayId, int colorMode) {
         synchronized (mSyncRoot) {
             LogicalDisplay display = mLogicalDisplays.get(displayId);
             if (display != null &&
-                    display.getRequestedColorTransformIdLocked() != colorTransformId) {
-                display.setRequestedColorTransformIdLocked(colorTransformId);
+                    display.getRequestedColorModeLocked() != colorMode) {
+                display.setRequestedColorModeLocked(colorMode);
                 scheduleTraversalLocked(false);
             }
         }
@@ -691,11 +696,15 @@
         device.mDebugLastLoggedDeviceInfo = info;
 
         mDisplayDevices.add(device);
-        addLogicalDisplayLocked(device);
+        LogicalDisplay display = addLogicalDisplayLocked(device);
         Runnable work = updateDisplayStateLocked(device);
         if (work != null) {
             work.run();
         }
+        if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
+            int colorMode = mPersistentDataStore.getColorMode(device);
+            display.setRequestedColorModeLocked(colorMode);
+        }
         scheduleTraversalLocked(false);
     }
 
@@ -714,6 +723,13 @@
             } else if (diff != 0) {
                 Slog.i(TAG, "Display device changed: " + info);
             }
+            if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
+                try {
+                    mPersistentDataStore.setColorMode(device, info.colorMode);
+                } finally {
+                    mPersistentDataStore.saveIfNeeded();
+                }
+            }
             device.mDebugLastLoggedDeviceInfo = info;
 
             device.applyPendingDisplayDeviceInfoChangesLocked();
@@ -766,7 +782,7 @@
 
     // Adds a new logical display based on the given display device.
     // Sends notifications if needed.
-    private void addLogicalDisplayLocked(DisplayDevice device) {
+    private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
         boolean isDefault = (deviceInfo.flags
                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
@@ -778,7 +794,7 @@
         if (!isDefault && mSingleDisplayDemoMode) {
             Slog.i(TAG, "Not creating a logical display for a secondary display "
                     + " because single display demo mode is enabled: " + deviceInfo);
-            return;
+            return null;
         }
 
         final int displayId = assignDisplayIdLocked(isDefault);
@@ -790,7 +806,7 @@
             // This should never happen currently.
             Slog.w(TAG, "Ignoring display device because the logical display "
                     + "created from it was not considered valid: " + deviceInfo);
-            return;
+            return null;
         }
 
         mLogicalDisplays.put(displayId, display);
@@ -801,6 +817,7 @@
         }
 
         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+        return display;
     }
 
     private int assignDisplayIdLocked(boolean isDefault) {
@@ -1068,6 +1085,9 @@
             if (mDisplayPowerController != null) {
                 mDisplayPowerController.dump(pw);
             }
+
+            pw.println();
+            mPersistentDataStore.dump(pw);
         }
     }
 
@@ -1352,13 +1372,13 @@
         }
 
         @Override // Binder call
-        public void requestColorTransform(int displayId, int colorTransformId) {
+        public void requestColorMode(int displayId, int colorMode) {
             mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM,
-                    "Permission required to change the display color transform");
+                    Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
+                    "Permission required to change the display color mode");
             final long token = Binder.clearCallingIdentity();
             try {
-                requestColorTransformInternal(displayId, colorTransformId);
+                requestColorModeInternal(displayId, colorMode);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 7b16ea6..61c2eac 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -39,6 +39,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A display adapter for the local displays managed by Surface Flinger.
@@ -100,14 +102,25 @@
                         builtInDisplayId);
                 return;
             }
+            int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
+            if (activeColorMode < 0) {
+                // We failed to get the active color mode. We don't bail out here since on the next
+                // configuration pass we'll go ahead and set it to whatever it was set to last (or
+                // COLOR_MODE_NATIVE if this is the first configuration).
+                Slog.w(TAG, "Unable to get active color mode for display device " +
+                        builtInDisplayId);
+                activeColorMode = Display.COLOR_MODE_INVALID;
+            }
+            int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
             LocalDisplayDevice device = mDevices.get(builtInDisplayId);
             if (device == null) {
                 // Display was added.
                 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
-                        configs, activeConfig);
+                        configs, activeConfig, colorModes, activeColorMode);
                 mDevices.put(builtInDisplayId, device);
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
-            } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig)) {
+            } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
+                        colorModes, activeColorMode)) {
                 // Display properties changed.
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
             }
@@ -144,8 +157,7 @@
         private final int mBuiltInDisplayId;
         private final Light mBacklight;
         private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
-        private final SparseArray<Display.ColorTransform> mSupportedColorTransforms =
-                new SparseArray<>();
+        private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
@@ -155,18 +167,20 @@
         private int mDefaultModeId;
         private int mActiveModeId;
         private boolean mActiveModeInvalid;
-        private int mDefaultColorTransformId;
-        private int mActiveColorTransformId;
-        private boolean mActiveColorTransformInvalid;
+        private int mActiveColorMode;
+        private boolean mActiveColorModeInvalid;
         private Display.HdrCapabilities mHdrCapabilities;
 
         private  SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
-                SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
+                SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
+                int[] colorModes, int activeColorMode) {
             super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
             mBuiltInDisplayId = builtInDisplayId;
-            updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo);
+            updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
+                    colorModes, activeColorMode);
+            updateColorModesLocked(colorModes, activeColorMode);
             if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                 LightsManager lights = LocalServices.getService(LightsManager.class);
                 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
@@ -176,39 +190,16 @@
             mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
         }
 
+        @Override
+        public boolean hasStableUniqueId() {
+            return true;
+        }
+
         public boolean updatePhysicalDisplayInfoLocked(
-                SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
+                SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
+                int[] colorModes, int activeColorMode) {
             mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
             mActivePhysIndex = activeDisplayInfo;
-            ArrayList<Display.ColorTransform> colorTransforms = new ArrayList<>();
-
-            // Build an updated list of all existing color transforms.
-            boolean colorTransformsAdded = false;
-            Display.ColorTransform activeColorTransform = null;
-            for (int i = 0; i < physicalDisplayInfos.length; i++) {
-                SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
-                // First check to see if we've already added this color transform
-                boolean existingMode = false;
-                for (int j = 0; j < colorTransforms.size(); j++) {
-                    if (colorTransforms.get(j).getColorTransform() == info.colorTransform) {
-                        existingMode = true;
-                        break;
-                    }
-                }
-                if (existingMode) {
-                    continue;
-                }
-                Display.ColorTransform colorTransform = findColorTransform(info);
-                if (colorTransform == null) {
-                    colorTransform = createColorTransform(info.colorTransform);
-                    colorTransformsAdded = true;
-                }
-                colorTransforms.add(colorTransform);
-                if (i == activeDisplayInfo) {
-                    activeColorTransform = colorTransform;
-                }
-            }
-
             // Build an updated list of all existing modes.
             ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
             boolean modesAdded = false;
@@ -254,21 +245,10 @@
                 mActiveModeInvalid = true;
                 sendTraversalRequestLocked();
             }
-            // Check whether surface flinger spontaneously changed color transforms out from under
-            // us.
-            if (mActiveColorTransformId != 0
-                    && mActiveColorTransformId != activeColorTransform.getId()) {
-                mActiveColorTransformInvalid = true;
-                sendTraversalRequestLocked();
-            }
 
-            boolean colorTransformsChanged =
-                    colorTransforms.size() != mSupportedColorTransforms.size()
-                    || colorTransformsAdded;
             boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
-            // If neither the records nor the supported color transforms have changed then we're
-            // done here.
-            if (!recordsChanged && !colorTransformsChanged) {
+            // If the records haven't changed then we're done here.
+            if (!recordsChanged) {
                 return false;
             }
             // Update the index of modes.
@@ -278,24 +258,13 @@
             for (DisplayModeRecord record : records) {
                 mSupportedModes.put(record.mMode.getModeId(), record);
             }
-            mSupportedColorTransforms.clear();
-            for (Display.ColorTransform colorTransform : colorTransforms) {
-                mSupportedColorTransforms.put(colorTransform.getId(), colorTransform);
-            }
-
-            // Update the default mode and color transform if needed. This needs to be done in
-            // tandem so we always have a default state to fall back to.
-            if (findDisplayInfoIndexLocked(mDefaultColorTransformId, mDefaultModeId) < 0) {
+            // Update the default mode, if needed.
+            if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
                 if (mDefaultModeId != 0) {
                     Slog.w(TAG, "Default display mode no longer available, using currently"
                             + " active mode as default.");
                 }
                 mDefaultModeId = activeRecord.mMode.getModeId();
-                if (mDefaultColorTransformId != 0) {
-                    Slog.w(TAG, "Default color transform no longer available, using currently"
-                            + " active color transform as default");
-                }
-                mDefaultColorTransformId = activeColorTransform.getId();
             }
             // Determine whether the active mode is still there.
             if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
@@ -307,20 +276,62 @@
                 mActiveModeInvalid = true;
             }
 
-            // Determine whether the active color transform is still there.
-            if (mSupportedColorTransforms.indexOfKey(mActiveColorTransformId) < 0) {
-                if (mActiveColorTransformId != 0) {
-                    Slog.w(TAG, "Active color transform no longer available, reverting"
-                            + " to default transform.");
-                }
-                mActiveColorTransformId = mDefaultColorTransformId;
-                mActiveColorTransformInvalid = true;
-            }
             // Schedule traversals so that we apply pending changes.
             sendTraversalRequestLocked();
             return true;
         }
 
+        private boolean updateColorModesLocked(int[] colorModes,
+                int activeColorMode) {
+            List<Integer> pendingColorModes = new ArrayList<>();
+
+            // Build an updated list of all existing color modes.
+            boolean colorModesAdded = false;
+            for (int colorMode: colorModes) {
+                if (!mSupportedColorModes.contains(colorMode)) {
+                    colorModesAdded = true;
+                }
+                pendingColorModes.add(colorMode);
+            }
+
+            boolean colorModesChanged =
+                    pendingColorModes.size() != mSupportedColorModes.size()
+                    || colorModesAdded;
+
+            // If the supported color modes haven't changed then we're done here.
+            if (!colorModesChanged) {
+                return false;
+            }
+
+            mHavePendingChanges = true;
+
+            mSupportedColorModes.clear();
+            mSupportedColorModes.addAll(pendingColorModes);
+            Collections.sort(mSupportedColorModes);
+
+            // Determine whether the active color mode is still there.
+            if (!mSupportedColorModes.contains(mActiveColorMode)) {
+                if (mActiveColorMode != 0) {
+                    Slog.w(TAG, "Active color mode no longer available, reverting"
+                            + " to default mode.");
+                    mActiveColorMode = Display.COLOR_MODE_DEFAULT;
+                    mActiveColorModeInvalid = true;
+                } else {
+                    if (!mSupportedColorModes.isEmpty()) {
+                        // This should never happen.
+                        Slog.e(TAG, "Default and active color mode is no longer available!"
+                                + " Reverting to first available mode.");
+                        mActiveColorMode = mSupportedColorModes.get(0);
+                        mActiveColorModeInvalid = true;
+                    } else {
+                        // This should really never happen.
+                        Slog.e(TAG, "No color modes available!");
+                    }
+                }
+            }
+            return true;
+        }
+
         private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 DisplayModeRecord record = mSupportedModes.valueAt(i);
@@ -331,16 +342,6 @@
             return null;
         }
 
-        private Display.ColorTransform findColorTransform(SurfaceControl.PhysicalDisplayInfo info) {
-            for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
-                Display.ColorTransform transform = mSupportedColorTransforms.valueAt(i);
-                if (transform.getColorTransform() == info.colorTransform) {
-                    return transform;
-                }
-            }
-            return null;
-        }
-
         @Override
         public void applyPendingDisplayDeviceInfoChangesLocked() {
             if (mHavePendingChanges) {
@@ -363,12 +364,11 @@
                     DisplayModeRecord record = mSupportedModes.valueAt(i);
                     mInfo.supportedModes[i] = record.mMode;
                 }
-                mInfo.colorTransformId = mActiveColorTransformId;
-                mInfo.defaultColorTransformId = mDefaultColorTransformId;
-                mInfo.supportedColorTransforms =
-                        new Display.ColorTransform[mSupportedColorTransforms.size()];
-                for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
-                    mInfo.supportedColorTransforms[i] = mSupportedColorTransforms.valueAt(i);
+                mInfo.colorMode = mActiveColorMode;
+                mInfo.supportedColorModes =
+                        new int[mSupportedColorModes.size()];
+                for (int i = 0; i < mSupportedColorModes.size(); i++) {
+                    mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
                 }
                 mInfo.hdrCapabilities = mHdrCapabilities;
                 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
@@ -520,8 +520,15 @@
         }
 
         @Override
-        public void requestColorTransformAndModeInTransactionLocked(
-                int colorTransformId, int modeId) {
+        public void requestDisplayModesInTransactionLocked(
+                int colorMode, int modeId) {
+            if (requestModeInTransactionLocked(modeId) ||
+                    requestColorModeInTransactionLocked(colorMode)) {
+                updateDeviceInfoLocked();
+            }
+        }
+
+        public boolean requestModeInTransactionLocked(int modeId) {
             if (modeId == 0) {
                 modeId = mDefaultModeId;
             } else if (mSupportedModes.indexOfKey(modeId) < 0) {
@@ -530,37 +537,36 @@
                 modeId = mDefaultModeId;
             }
 
-            if (colorTransformId == 0) {
-                colorTransformId = mDefaultColorTransformId;
-            } else if (mSupportedColorTransforms.indexOfKey(colorTransformId) < 0) {
-                Slog.w(TAG, "Requested color transform " + colorTransformId + " is not supported"
-                        + " by this display, reverting to the default color transform");
-                colorTransformId = mDefaultColorTransformId;
-            }
-            int physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
+            int physIndex = findDisplayInfoIndexLocked(modeId);
             if (physIndex < 0) {
-                Slog.w(TAG, "Requested color transform, mode ID pair (" + colorTransformId + ", "
-                        + modeId + ") not available, trying color transform with default mode ID");
+                Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
+                        + " trying with default mode ID");
                 modeId = mDefaultModeId;
-                physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
-                if (physIndex < 0) {
-                    Slog.w(TAG, "Requested color transform with default mode ID still not"
-                            + " available, falling back to default color transform with default"
-                            + " mode.");
-                    colorTransformId = mDefaultColorTransformId;
-                    physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
-                }
+                physIndex = findDisplayInfoIndexLocked(modeId);
             }
             if (mActivePhysIndex == physIndex) {
-                return;
+                return false;
             }
             SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
             mActivePhysIndex = physIndex;
             mActiveModeId = modeId;
             mActiveModeInvalid = false;
-            mActiveColorTransformId = colorTransformId;
-            mActiveColorTransformInvalid = false;
-            updateDeviceInfoLocked();
+            return true;
+        }
+
+        public boolean requestColorModeInTransactionLocked(int colorMode) {
+            if (mActiveColorMode == colorMode) {
+                return false;
+            }
+            if (!mSupportedColorModes.contains(colorMode)) {
+                Slog.w(TAG, "Unable to find color mode " + colorMode
+                        + ", ignoring request.");
+                return false;
+            }
+            SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
+            mActiveColorMode = colorMode;
+            mActiveColorModeInvalid = false;
+            return true;
         }
 
         @Override
@@ -569,7 +575,7 @@
             pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
             pw.println("mActivePhysIndex=" + mActivePhysIndex);
             pw.println("mActiveModeId=" + mActiveModeId);
-            pw.println("mActiveColorTransformId=" + mActiveColorTransformId);
+            pw.println("mActiveColorMode=" + mActiveColorMode);
             pw.println("mState=" + Display.stateToString(mState));
             pw.println("mBrightness=" + mBrightness);
             pw.println("mBacklight=" + mBacklight);
@@ -581,24 +587,22 @@
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 pw.println("  " + mSupportedModes.valueAt(i));
             }
-            pw.println("mSupportedColorTransforms=[");
-            for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
+            pw.print("mSupportedColorModes=[");
+            for (int i = 0; i < mSupportedColorModes.size(); i++) {
                 if (i != 0) {
                     pw.print(", ");
                 }
-                pw.print(mSupportedColorTransforms.valueAt(i));
+                pw.print(mSupportedColorModes.get(i));
             }
             pw.println("]");
         }
 
-        private int findDisplayInfoIndexLocked(int colorTransformId, int modeId) {
+        private int findDisplayInfoIndexLocked(int modeId) {
             DisplayModeRecord record = mSupportedModes.get(modeId);
-            Display.ColorTransform transform = mSupportedColorTransforms.get(colorTransformId);
-            if (record != null && transform != null) {
+            if (record != null) {
                 for (int i = 0; i < mDisplayInfos.length; i++) {
                     SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
-                    if (info.colorTransform == transform.getColorTransform()
-                            && record.hasMatchingMode(info)){
+                    if (record.hasMatchingMode(info)){
                         return i;
                     }
                 }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 973f04c..287a25a 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -74,7 +74,7 @@
     private boolean mHasContent;
 
     private int mRequestedModeId;
-    private int mRequestedColorTransformId;
+    private int mRequestedColorMode;
 
     // The display offsets to apply to the display projection.
     private int mDisplayOffsetX;
@@ -236,11 +236,10 @@
             mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
             mBaseDisplayInfo.supportedModes = Arrays.copyOf(
                     deviceInfo.supportedModes, deviceInfo.supportedModes.length);
-            mBaseDisplayInfo.colorTransformId = deviceInfo.colorTransformId;
-            mBaseDisplayInfo.defaultColorTransformId = deviceInfo.defaultColorTransformId;
-            mBaseDisplayInfo.supportedColorTransforms = Arrays.copyOf(
-                    deviceInfo.supportedColorTransforms,
-                    deviceInfo.supportedColorTransforms.length);
+            mBaseDisplayInfo.colorMode = deviceInfo.colorMode;
+            mBaseDisplayInfo.supportedColorModes = Arrays.copyOf(
+                    deviceInfo.supportedColorModes,
+                    deviceInfo.supportedColorModes.length);
             mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
@@ -282,12 +281,12 @@
         // Set the layer stack.
         device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
 
-        // Set the color transform and mode.
+        // Set the color mode and mode.
         if (device == mPrimaryDisplayDevice) {
-            device.requestColorTransformAndModeInTransactionLocked(
-                    mRequestedColorTransformId, mRequestedModeId);
+            device.requestDisplayModesInTransactionLocked(
+                    mRequestedColorMode, mRequestedModeId);
         } else {
-            device.requestColorTransformAndModeInTransactionLocked(0, 0);  // Revert to default.
+            device.requestDisplayModesInTransactionLocked(0, 0);  // Revert to default.
         }
 
         // Only grab the display info now as it may have been changed based on the requests above.
@@ -391,15 +390,15 @@
     }
 
     /**
-     * Requests the given color transform.
+     * Requests the given color mode.
      */
-    public void setRequestedColorTransformIdLocked(int colorTransformId) {
-        mRequestedColorTransformId = colorTransformId;
+    public void setRequestedColorModeLocked(int colorMode) {
+        mRequestedColorMode = colorMode;
     }
 
-    /** Returns the pending requested color transform. */
-    public int getRequestedColorTransformIdLocked() {
-        return mRequestedColorTransformId;
+    /** Returns the pending requested color mode. */
+    public int getRequestedColorModeLocked() {
+        return mRequestedColorMode;
     }
 
     /**
@@ -429,7 +428,7 @@
         pw.println("mLayerStack=" + mLayerStack);
         pw.println("mHasContent=" + mHasContent);
         pw.println("mRequestedMode=" + mRequestedModeId);
-        pw.println("mRequestedColorTransformId=" + mRequestedColorTransformId);
+        pw.println("mRequestedColorMode=" + mRequestedColorMode);
         pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
         pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
                 mPrimaryDisplayDevice.getNameLocked() : "null"));
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index cf6264a..27327d4 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -266,6 +266,11 @@
         }
 
         @Override
+        public boolean hasStableUniqueId() {
+            return false;
+        }
+
+        @Override
         public void performTraversalInTransactionLocked() {
             if (mSurfaceTexture != null) {
                 if (mSurface == null) {
@@ -310,7 +315,7 @@
         }
 
         @Override
-        public void requestColorTransformAndModeInTransactionLocked(int color, int id) {
+        public void requestDisplayModesInTransactionLocked(int color, int id) {
             int index = -1;
             if (id == 0) {
                 // Use the default.
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index d676b35..5616fb9 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -27,6 +27,7 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
+import android.view.Display;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -35,8 +36,11 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 import libcore.io.IoUtils;
 import libcore.util.Objects;
@@ -50,8 +54,13 @@
  * &lt;display-manager-state>
  *   &lt;remembered-wifi-displays>
  *     &lt;wifi-display deviceAddress="00:00:00:00:00:00" deviceName="XXXX" deviceAlias="YYYY" />
- *   &gt;remembered-wifi-displays>
- * &gt;/display-manager-state>
+ *   &lt;remembered-wifi-displays>
+ *   &lt;display-states>
+ *      &lt;display>
+ *          &lt;color-mode>0&lt;/color-mode>
+ *      &lt;/display>
+ *  &lt;/display-states>
+ * &lt;/display-manager-state>
  * </code>
  *
  * TODO: refactor this to extract common code shared with the input manager's data store
@@ -62,6 +71,10 @@
     // Remembered Wifi display devices.
     private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
 
+    // Display state by unique id.
+    private final HashMap<String, DisplayState> mDisplayStates =
+            new HashMap<String, DisplayState>();
+
     // The atomic file used to safely read or write the file.
     private final AtomicFile mAtomicFile;
 
@@ -168,7 +181,41 @@
         return -1;
     }
 
-    private void loadIfNeeded() {
+    public int getColorMode(DisplayDevice device) {
+        if (!device.hasStableUniqueId()) {
+            return Display.COLOR_MODE_DEFAULT;
+        }
+        DisplayState state = getDisplayState(device.getUniqueId(), false);
+        if (state == null) {
+            return Display.COLOR_MODE_DEFAULT;
+        }
+        return state.getColorMode();
+    }
+
+    public boolean setColorMode(DisplayDevice device, int colorMode) {
+        if (!device.hasStableUniqueId()) {
+            return false;
+        }
+        DisplayState state = getDisplayState(device.getUniqueId(), true);
+        if (state.setColorMode(colorMode)) {
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
+    private DisplayState getDisplayState(String uniqueId, boolean createIfAbsent) {
+        loadIfNeeded();
+        DisplayState state = mDisplayStates.get(uniqueId);
+        if (state == null && createIfAbsent) {
+            state = new DisplayState();
+            mDisplayStates.put(uniqueId, state);
+            setDirty();
+        }
+        return state;
+    }
+
+    public void loadIfNeeded() {
         if (!mLoaded) {
             load();
             mLoaded = true;
@@ -240,6 +287,9 @@
             if (parser.getName().equals("remembered-wifi-displays")) {
                 loadRememberedWifiDisplaysFromXml(parser);
             }
+            if (parser.getName().equals("display-states")) {
+                loadDisplaysFromXml(parser);
+            }
         }
     }
 
@@ -267,6 +317,27 @@
         }
     }
 
+    private void loadDisplaysFromXml(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        final int outerDepth = parser.getDepth();
+        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+            if (parser.getName().equals("display")) {
+                String uniqueId = parser.getAttributeValue(null, "unique-id");
+                if (uniqueId == null) {
+                    throw new XmlPullParserException(
+                            "Missing unique-id attribute on display.");
+                }
+                if (mDisplayStates.containsKey(uniqueId)) {
+                    throw new XmlPullParserException("Found duplicate display.");
+                }
+
+                DisplayState state = new DisplayState();
+                state.loadFromXml(parser);
+                mDisplayStates.put(uniqueId, state);
+            }
+        }
+    }
+
     private void saveToXml(XmlSerializer serializer) throws IOException {
         serializer.startDocument(null, true);
         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
@@ -282,7 +353,72 @@
             serializer.endTag(null, "wifi-display");
         }
         serializer.endTag(null, "remembered-wifi-displays");
+        serializer.startTag(null, "display-states");
+        for (Map.Entry<String, DisplayState> entry : mDisplayStates.entrySet()) {
+            final String uniqueId = entry.getKey();
+            final DisplayState state = entry.getValue();
+            serializer.startTag(null, "display");
+            serializer.attribute(null, "unique-id", uniqueId);
+            state.saveToXml(serializer);
+            serializer.endTag(null, "display");
+        }
+        serializer.endTag(null, "display-states");
         serializer.endTag(null, "display-manager-state");
         serializer.endDocument();
     }
+
+    public void dump(PrintWriter pw) {
+        pw.println("PersistentDataStore");
+        pw.println("  mLoaded=" + mLoaded);
+        pw.println("  mDirty=" + mDirty);
+        pw.println("  RememberedWifiDisplays:");
+        int i = 0;
+        for (WifiDisplay display : mRememberedWifiDisplays) {
+            pw.println("    " + i++ + ": " + display);
+        }
+        pw.println("  DisplayStates:");
+        i = 0;
+        for (Map.Entry<String, DisplayState> entry : mDisplayStates.entrySet()) {
+            pw.println("    " + i++ + ": " + entry.getKey());
+            entry.getValue().dump(pw, "      ");
+        }
+    }
+
+    private static final class DisplayState {
+        private int mColorMode;
+
+        public boolean setColorMode(int colorMode) {
+            if (colorMode == mColorMode) {
+                return false;
+            }
+            mColorMode = colorMode;
+            return true;
+        }
+
+        public int getColorMode() {
+            return mColorMode;
+        }
+
+        public void loadFromXml(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            final int outerDepth = parser.getDepth();
+
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if (parser.getName().equals("color-mode")) {
+                    String value = parser.nextText();
+                    mColorMode = Integer.parseInt(value);
+                }
+            }
+        }
+
+        public void saveToXml(XmlSerializer serializer) throws IOException {
+            serializer.startTag(null, "color-mode");
+            serializer.text(Integer.toString(mColorMode));
+            serializer.endTag(null, "color-mode");
+        }
+
+        private void dump(final PrintWriter pw, final String prefix) {
+            pw.println(prefix + "ColorMode=" + mColorMode);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 986efd69..9d0fde5 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -225,6 +225,11 @@
         }
 
         @Override
+        public boolean hasStableUniqueId() {
+            return false;
+        }
+
+        @Override
         public Runnable requestDisplayStateLocked(int state, int brightness) {
             if (state != mDisplayState) {
                 mDisplayState = state;
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 64bc729..08c0a1a 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -602,6 +602,11 @@
             mMode = createMode(width, height, refreshRate);
         }
 
+        @Override
+        public boolean hasStableUniqueId() {
+            return true;
+        }
+
         public void destroyLocked() {
             if (mSurface != null) {
                 mSurface.release();
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 8f212db..9d93146 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -28,6 +28,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -43,7 +44,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -396,10 +399,11 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
             if (DEBUG) {
-                Slog.d(TAG, "Receieved: " + intent.getAction());
+                Slog.d(TAG, "Receieved: " + action);
             }
-            if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                 // Purge the app's jobs if the whole package was just disabled.  When this is
                 // the case the component name will be a bare package name.
                 final String pkgName = getPackageName(intent);
@@ -433,7 +437,7 @@
                 } else {
                     Slog.w(TAG, "PACKAGE_CHANGED for " + pkgName + " / uid " + pkgUid);
                 }
-            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
                 // If this is an outright uninstall rather than the first half of an
                 // app update sequence, cancel the jobs associated with the app.
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
@@ -443,12 +447,43 @@
                     }
                     cancelJobsForUid(uidRemoved, true);
                 }
-            } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 if (DEBUG) {
                     Slog.d(TAG, "Removing jobs for user: " + userId);
                 }
                 cancelJobsForUser(userId);
+            } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+                // Has this package scheduled any jobs, such that we will take action
+                // if it were to be force-stopped?
+                final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                final String pkgName = intent.getData().getSchemeSpecificPart();
+                if (pkgUid != -1) {
+                    List<JobStatus> jobsForUid;
+                    synchronized (mLock) {
+                        jobsForUid = mJobs.getJobsByUid(pkgUid);
+                    }
+                    for (int i = jobsForUid.size() - 1; i >= 0; i--) {
+                        if (jobsForUid.get(i).getSourcePackageName().equals(pkgName)) {
+                            if (DEBUG) {
+                                Slog.d(TAG, "Restart query: package " + pkgName + " at uid "
+                                        + pkgUid + " has jobs");
+                            }
+                            setResultCode(Activity.RESULT_OK);
+                            break;
+                        }
+                    }
+                }
+            } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+                // possible force-stop
+                final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                final String pkgName = intent.getData().getSchemeSpecificPart();
+                if (pkgUid != -1) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Removing jobs for pkg " + pkgName + " at uid " + pkgUid);
+                    }
+                    cancelJobsForPackageAndUid(pkgName, pkgUid);
+                }
             }
         }
     };
@@ -583,6 +618,19 @@
         }
     }
 
+    void cancelJobsForPackageAndUid(String pkgName, int uid) {
+        List<JobStatus> jobsForUid;
+        synchronized (mLock) {
+            jobsForUid = mJobs.getJobsByUid(uid);
+        }
+        for (int i = jobsForUid.size() - 1; i >= 0; i--) {
+            final JobStatus job = jobsForUid.get(i);
+            if (job.getSourcePackageName().equals(pkgName)) {
+                cancelJobImpl(job, null);
+            }
+        }
+    }
+
     /**
      * Entry point from client to cancel all jobs originating from their uid.
      * This will remove the job from the master list, and cancel the job if it was staged for
@@ -754,6 +802,8 @@
             final IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
             filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
             filter.addDataScheme("package");
             getContext().registerReceiverAsUser(
                     mBroadcastReceiver, UserHandle.ALL, filter, null, null);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e368af2..8b5942c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -58,6 +58,7 @@
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.app.PendingIntent;
+import android.app.RemoteInput;
 import android.app.StatusBarManager;
 import android.app.backup.BackupManager;
 import android.app.usage.UsageEvents;
@@ -92,6 +93,7 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -120,8 +122,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
-import android.view.WindowManager;
-import android.view.WindowManagerInternal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
@@ -232,7 +232,6 @@
     @Nullable StatusBarManagerInternal mStatusBar;
     Vibrator mVibrator;
     private VrManagerInternal mVrManagerInternal;
-    private WindowManagerInternal mWindowManagerInternal;
 
     final IBinder mForegroundToken = new Binder();
     private Handler mHandler;
@@ -453,15 +452,13 @@
         final String pkg;
         final ITransientNotification callback;
         int duration;
-        Binder token;
 
-        ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
-                    Binder token) {
+        ToastRecord(int pid, String pkg, ITransientNotification callback, int duration)
+        {
             this.pid = pid;
             this.pkg = pkg;
             this.callback = callback;
             this.duration = duration;
-            this.token = token;
         }
 
         void update(int duration) {
@@ -1128,7 +1125,6 @@
             mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
             mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
             mVrManagerInternal = getLocalService(VrManagerInternal.class);
-            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
             mZenModeHelper.onSystemReady();
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
@@ -1329,13 +1325,10 @@
                             }
                         }
 
-                        Binder token = new Binder();
-                        mWindowManagerInternal.addWindowToken(token,
-                                WindowManager.LayoutParams.TYPE_TOAST);
-                        record = new ToastRecord(callingPid, pkg, callback, duration, token);
+                        record = new ToastRecord(callingPid, pkg, callback, duration);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
-                        keepProcessAliveIfNeededLocked(callingPid);
+                        keepProcessAliveLocked(callingPid);
                     }
                     // If it's at index 0, it's the current toast.  It doesn't matter if it's
                     // new or just been updated.  Call back and tell it to show itself.
@@ -2994,7 +2987,7 @@
         while (record != null) {
             if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
             try {
-                record.callback.show(record.token);
+                record.callback.show();
                 scheduleTimeoutLocked(record);
                 return;
             } catch (RemoteException e) {
@@ -3005,7 +2998,7 @@
                 if (index >= 0) {
                     mToastQueue.remove(index);
                 }
-                keepProcessAliveIfNeededLocked(record.pid);
+                keepProcessAliveLocked(record.pid);
                 if (mToastQueue.size() > 0) {
                     record = mToastQueue.get(0);
                 } else {
@@ -3025,11 +3018,8 @@
             // don't worry about this, we're about to remove it from
             // the list anyway
         }
-
-        ToastRecord lastToast = mToastQueue.remove(index);
-        mWindowManagerInternal.removeWindowToken(lastToast.token, true);
-
-        keepProcessAliveIfNeededLocked(record.pid);
+        mToastQueue.remove(index);
+        keepProcessAliveLocked(record.pid);
         if (mToastQueue.size() > 0) {
             // Show the next one. If the callback fails, this will remove
             // it from the list, so don't assume that the list hasn't changed
@@ -3073,7 +3063,7 @@
     }
 
     // lock on mToastQueue
-    void keepProcessAliveIfNeededLocked(int pid)
+    void keepProcessAliveLocked(int pid)
     {
         int toastCount = 0; // toasts from this pid
         ArrayList<ToastRecord> list = mToastQueue;
diff --git a/services/core/java/com/android/server/notification/ScheduleCalendar.java b/services/core/java/com/android/server/notification/ScheduleCalendar.java
index 22ca702..9e8b2e3 100644
--- a/services/core/java/com/android/server/notification/ScheduleCalendar.java
+++ b/services/core/java/com/android/server/notification/ScheduleCalendar.java
@@ -82,15 +82,13 @@
         if (end <= start) {
             end = addDays(end, 1);
         }
-        boolean isInSchedule =
-                isInSchedule(-1, time, start, end) || isInSchedule(0, time, start, end);
-        if (isInSchedule && mSchedule.exitAtAlarm
+        return isInSchedule(-1, time, start, end) || isInSchedule(0, time, start, end);
+    }
+
+    public boolean shouldExitForAlarm(long time) {
+        return mSchedule.exitAtAlarm
                 && mSchedule.nextAlarm != 0
-                && time >= mSchedule.nextAlarm) {
-            return false;
-        } else {
-            return isInSchedule;
-        }
+                && time >= mSchedule.nextAlarm;
     }
 
     private boolean isInSchedule(int daysOffset, long time, long start, long end) {
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 8197544..32d03ce 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -25,11 +25,15 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
+import android.os.Binder;
+import android.provider.Settings;
 import android.service.notification.Condition;
 import android.service.notification.IConditionProvider;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 
@@ -53,9 +57,13 @@
     private static final String ACTION_EVALUATE =  SIMPLE_NAME + ".EVALUATE";
     private static final int REQUEST_CODE_EVALUATE = 1;
     private static final String EXTRA_TIME = "time";
+    private static final String SEPARATOR = ";";
+    private static final String SCP_SETTING = "snoozed_schedule_condition_provider";
+
 
     private final Context mContext = this;
     private final ArrayMap<Uri, ScheduleCalendar> mSubscriptions = new ArrayMap<>();
+    private ArraySet<Uri> mSnoozed = new ArraySet<>();
 
     private AlarmManager mAlarmManager;
     private boolean mConnected;
@@ -90,6 +98,7 @@
             pw.print("            ");
             pw.println(mSubscriptions.get(conditionId).toString());
         }
+        pw.println("      snoozed due to alarm: " + TextUtils.join(SEPARATOR, mSnoozed));
         dumpUpcomingTime(pw, "mNextAlarmTime", mNextAlarmTime, now);
     }
 
@@ -97,6 +106,7 @@
     public void onConnected() {
         if (DEBUG) Slog.d(TAG, "onConnected");
         mConnected = true;
+        readSnoozed();
     }
 
     @Override
@@ -126,6 +136,7 @@
     public void onUnsubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
         mSubscriptions.remove(conditionId);
+        removeSnoozed(conditionId);
         evaluateSubscriptions();
     }
 
@@ -150,10 +161,16 @@
         for (Uri conditionId : mSubscriptions.keySet()) {
             final ScheduleCalendar cal = mSubscriptions.get(conditionId);
             if (cal != null && cal.isInSchedule(now)) {
-                notifyCondition(conditionId, Condition.STATE_TRUE, "meetsSchedule");
+                if (conditionSnoozed(conditionId) || cal.shouldExitForAlarm(now)) {
+                    notifyCondition(conditionId, Condition.STATE_FALSE, "alarmCanceled");
+                    addSnoozed(conditionId);
+                } else {
+                    notifyCondition(conditionId, Condition.STATE_TRUE, "meetsSchedule");
+                }
                 cal.maybeSetNextAlarm(now, nextUserAlarmTime);
             } else {
                 notifyCondition(conditionId, Condition.STATE_FALSE, "!meetsSchedule");
+                removeSnoozed(conditionId);
                 if (nextUserAlarmTime == 0) {
                     cal.maybeSetNextAlarm(now, nextUserAlarmTime);
                 }
@@ -194,7 +211,7 @@
         return info != null ? info.getTriggerTime() : 0;
     }
 
-    private static boolean meetsSchedule(ScheduleCalendar cal, long time) {
+    private boolean meetsSchedule(ScheduleCalendar cal, long time) {
         return cal != null && cal.isInSchedule(time);
     }
 
@@ -237,6 +254,62 @@
         return new Condition(id, summary, line1, line2, 0, state, Condition.FLAG_RELEVANT_ALWAYS);
     }
 
+    private boolean conditionSnoozed(Uri conditionId) {
+        synchronized (mSnoozed) {
+            return mSnoozed.contains(conditionId);
+        }
+    }
+
+    private void addSnoozed(Uri conditionId) {
+        synchronized (mSnoozed) {
+            mSnoozed.add(conditionId);
+            saveSnoozedLocked();
+        }
+    }
+
+    private void removeSnoozed(Uri conditionId) {
+        synchronized (mSnoozed) {
+            mSnoozed.remove(conditionId);
+            saveSnoozedLocked();
+        }
+    }
+
+    public void saveSnoozedLocked() {
+        final String setting = TextUtils.join(SEPARATOR, mSnoozed);
+        final int currentUser = ActivityManager.getCurrentUser();
+        Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                SCP_SETTING,
+                setting,
+                currentUser);
+    }
+
+    public void readSnoozed() {
+        synchronized (mSnoozed) {
+            long identity = Binder.clearCallingIdentity();
+            try {
+                final String setting = Settings.Secure.getStringForUser(
+                        mContext.getContentResolver(),
+                        SCP_SETTING,
+                        ActivityManager.getCurrentUser());
+                if (setting != null) {
+                    final String[] tokens = setting.split(SEPARATOR);
+                    for (int i = 0; i < tokens.length; i++) {
+                        String token = tokens[i];
+                        if (token != null) {
+                            token = token.trim();
+                        }
+                        if (TextUtils.isEmpty(token)) {
+                            continue;
+                        }
+                        mSnoozed.add(Uri.parse(token));
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 9ccfd67..4e9f5a2 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -194,6 +194,48 @@
         }
     }
 
+    public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
+            String historyTag) {
+        if (DEBUG) {
+            Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
+                    + ", workSource=" + workSource);
+        }
+
+        try {
+            if (workSource != null) {
+                final int N = workSource.size();
+                for (int i=0; i<N; i++) {
+                    mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, workSource.get(i));
+                }
+            } else {
+                mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
+            }
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
+            String historyTag) {
+        if (DEBUG) {
+            Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
+                    + ", workSource=" + workSource);
+        }
+
+        try {
+            if (workSource != null) {
+                final int N = workSource.size();
+                for (int i=0; i<N; i++) {
+                    mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, workSource.get(i));
+                }
+            } else {
+                mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
+            }
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
     /**
      * Called when a wake lock is changing.
      */
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 12a2d2e..2215cbb 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -56,6 +56,7 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.EventLog;
+import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
@@ -73,9 +74,7 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
-import com.android.server.vr.VrManagerInternal;
 import com.android.server.vr.VrManagerService;
-import com.android.server.vr.VrStateListener;
 import libcore.util.Objects;
 
 import java.io.FileDescriptor;
@@ -108,6 +107,8 @@
     private static final int MSG_SANDMAN = 2;
     // Message: Sent when the screen brightness boost expires.
     private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
+    // Message: Polling to look for long held wake locks.
+    private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4;
 
     // Dirty bit: mWakeLocks changed
     private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -159,6 +160,9 @@
     // This should perhaps be a setting.
     private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;
 
+    // How long a partial wake lock must be held until we consider it a long wake lock.
+    static final long MIN_LONG_WAKE_CHECK_INTERVAL = 60*1000;
+
     // Power hints defined in hardware/libhardware/include/hardware/power.h.
     private static final int POWER_HINT_LOW_POWER = 5;
     private static final int POWER_HINT_VR_MODE = 7;
@@ -221,6 +225,15 @@
     // A bitfield that summarizes the state of all active wakelocks.
     private int mWakeLockSummary;
 
+    // Have we scheduled a message to check for long wake locks?  This is when we will check.
+    private long mNotifyLongScheduled;
+
+    // Last time we checked for long wake locks.
+    private long mNotifyLongDispatched;
+
+    // The time we decided to do next long check.
+    private long mNotifyLongNextCheck;
+
     // If true, instructs the display controller to wait for the proximity sensor to
     // go negative before turning the screen on.
     private boolean mRequestWaitForNegativeProximity;
@@ -1025,6 +1038,38 @@
             mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
                     wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
                     wakeLock.mHistoryTag);
+            restartNofifyLongTimerLocked(wakeLock);
+        }
+    }
+
+    private void enqueueNotifyLongMsgLocked(long time) {
+        mNotifyLongScheduled = time;
+        Message msg = mHandler.obtainMessage(MSG_CHECK_FOR_LONG_WAKELOCKS);
+        msg.setAsynchronous(true);
+        mHandler.sendMessageAtTime(msg, time);
+    }
+
+    private void restartNofifyLongTimerLocked(WakeLock wakeLock) {
+        wakeLock.mAcquireTime = SystemClock.uptimeMillis();
+        if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                == PowerManager.PARTIAL_WAKE_LOCK && mNotifyLongScheduled == 0) {
+            enqueueNotifyLongMsgLocked(wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL);
+        }
+    }
+
+    private void notifyWakeLockLongStartedLocked(WakeLock wakeLock) {
+        if (mSystemReady && !wakeLock.mDisabled) {
+            wakeLock.mNotifiedLong = true;
+            mNotifier.onLongPartialWakeLockStart(wakeLock.mTag, wakeLock.mOwnerUid,
+                    wakeLock.mWorkSource, wakeLock.mHistoryTag);
+        }
+    }
+
+    private void notifyWakeLockLongFinishedLocked(WakeLock wakeLock) {
+        if (wakeLock.mNotifiedLong) {
+            wakeLock.mNotifiedLong = false;
+            mNotifier.onLongPartialWakeLockFinish(wakeLock.mTag, wakeLock.mOwnerUid,
+                    wakeLock.mWorkSource, wakeLock.mHistoryTag);
         }
     }
 
@@ -1034,15 +1079,23 @@
             mNotifier.onWakeLockChanging(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
                     wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
                     wakeLock.mHistoryTag, flags, tag, packageName, uid, pid, ws, historyTag);
+            notifyWakeLockLongFinishedLocked(wakeLock);
+            // Changing the wake lock will count as releasing the old wake lock(s) and
+            // acquiring the new ones...  we do this because otherwise once a wakelock
+            // becomes long, if we just continued to treat it as long we can get in to
+            // situations where we spam battery stats with every following change to it.
+            restartNofifyLongTimerLocked(wakeLock);
         }
     }
 
     private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
         if (mSystemReady && wakeLock.mNotifiedAcquired) {
             wakeLock.mNotifiedAcquired = false;
+            wakeLock.mAcquireTime = 0;
             mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
                     wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
                     wakeLock.mWorkSource, wakeLock.mHistoryTag);
+            notifyWakeLockLongFinishedLocked(wakeLock);
         }
     }
 
@@ -1599,6 +1652,42 @@
         }
     }
 
+    void checkForLongWakeLocks() {
+        synchronized (mLock) {
+            final long now = SystemClock.uptimeMillis();
+            mNotifyLongDispatched = now;
+            final long when = now - MIN_LONG_WAKE_CHECK_INTERVAL;
+            long nextCheckTime = Long.MAX_VALUE;
+            final int numWakeLocks = mWakeLocks.size();
+            for (int i = 0; i < numWakeLocks; i++) {
+                final WakeLock wakeLock = mWakeLocks.get(i);
+                if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                        == PowerManager.PARTIAL_WAKE_LOCK) {
+                    if (wakeLock.mNotifiedAcquired && !wakeLock.mNotifiedLong) {
+                        if (wakeLock.mAcquireTime < when) {
+                            // This wake lock has exceeded the long acquire time, report!
+                            notifyWakeLockLongStartedLocked(wakeLock);
+                        } else {
+                            // This wake lock could still become a long one, at this time.
+                            long checkTime = wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL;
+                            if (checkTime < nextCheckTime) {
+                                nextCheckTime = checkTime;
+                            }
+                        }
+                    }
+                }
+            }
+            mNotifyLongScheduled = 0;
+            mHandler.removeMessages(MSG_CHECK_FOR_LONG_WAKELOCKS);
+            if (nextCheckTime != Long.MAX_VALUE) {
+                mNotifyLongNextCheck = nextCheckTime;
+                enqueueNotifyLongMsgLocked(nextCheckTime);
+            } else {
+                mNotifyLongNextCheck = 0;
+            }
+        }
+    }
+
     /**
      * Updates the value of mUserActivitySummary to summarize the user requested
      * state of the system such as whether the screen should be bright or dim.
@@ -2748,6 +2837,27 @@
             pw.println("  mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
             pw.println("  mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
             pw.println("  mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
+            pw.print("  mNotifyLongScheduled=");
+            if (mNotifyLongScheduled == 0) {
+                pw.print("(none)");
+            } else {
+                TimeUtils.formatDuration(mNotifyLongScheduled, SystemClock.uptimeMillis(), pw);
+            }
+            pw.println();
+            pw.print("  mNotifyLongDispatched=");
+            if (mNotifyLongDispatched == 0) {
+                pw.print("(none)");
+            } else {
+                TimeUtils.formatDuration(mNotifyLongDispatched, SystemClock.uptimeMillis(), pw);
+            }
+            pw.println();
+            pw.print("  mNotifyLongNextCheck=");
+            if (mNotifyLongNextCheck == 0) {
+                pw.print("(none)");
+            } else {
+                TimeUtils.formatDuration(mNotifyLongNextCheck, SystemClock.uptimeMillis(), pw);
+            }
+            pw.println();
             pw.println("  mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
             pw.println("  mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
             pw.println("  mSandmanScheduled=" + mSandmanScheduled);
@@ -2856,6 +2966,10 @@
             }
 
             pw.println();
+            pw.println("Looper state:");
+            mHandler.getLooper().dump(new PrintWriterPrinter(pw), "  ");
+
+            pw.println();
             pw.println("Wake Locks: size=" + mWakeLocks.size());
             for (WakeLock wl : mWakeLocks) {
                 pw.println("  " + wl);
@@ -2984,6 +3098,9 @@
                 case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                     handleScreenBrightnessBoostTimeout();
                     break;
+                case MSG_CHECK_FOR_LONG_WAKELOCKS:
+                    checkForLongWakeLocks();
+                    break;
             }
         }
     }
@@ -3000,7 +3117,9 @@
         public String mHistoryTag;
         public final int mOwnerUid;
         public final int mOwnerPid;
+        public long mAcquireTime;
         public boolean mNotifiedAcquired;
+        public boolean mNotifiedLong;
         public boolean mDisabled;
 
         public WakeLock(IBinder lock, int flags, String tag, String packageName,
@@ -3059,9 +3178,34 @@
 
         @Override
         public String toString() {
-            return getLockLevelString()
-                    + " '" + mTag + "'" + getLockFlagsString() + (mDisabled ? " DISABLED" : "")
-                    + " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
+            StringBuilder sb = new StringBuilder();
+            sb.append(getLockLevelString());
+            sb.append(" '");
+            sb.append(mTag);
+            sb.append("'");
+            sb.append(getLockFlagsString());
+            if (mDisabled) {
+                sb.append(" DISABLED");
+            }
+            if (mNotifiedAcquired) {
+                sb.append(" ACQ=");
+                TimeUtils.formatDuration(mAcquireTime-SystemClock.uptimeMillis(), sb);
+            }
+            if (mNotifiedLong) {
+                sb.append(" LONG");
+            }
+            sb.append(" (uid=");
+            sb.append(mOwnerUid);
+            if (mOwnerPid != 0) {
+                sb.append(" pid=");
+                sb.append(mOwnerPid);
+            }
+            if (mWorkSource != null) {
+                sb.append(" ws=");
+                sb.append(mWorkSource);
+            }
+            sb.append(")");
+            return sb.toString();
         }
 
         @SuppressWarnings("deprecation")
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index f7a92fe..75f6120 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -487,6 +487,7 @@
     final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
     final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
 
+    final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
     int mCurrentUserId;
 
     static class WallpaperData {
@@ -944,26 +945,32 @@
 
     void onUnlockUser(final int userId) {
         synchronized (mLock) {
-            if (mCurrentUserId == userId && mWaitingForUnlock) {
-                switchUser(userId, null);
+            if (mCurrentUserId == userId) {
+                if (mWaitingForUnlock) {
+                    // If we're switching users, now is when we transition the wallpaper
+                    switchUser(userId, null);
+                }
 
                 // Make sure that the SELinux labeling of all the relevant files is correct.
                 // This corrects for mislabeling bugs that might have arisen from move-to
                 // operations involving the wallpaper files.  This isn't timing-critical,
                 // so we do it in the background to avoid holding up the user unlock operation.
-                Runnable relabeler = new Runnable() {
-                    @Override
-                    public void run() {
-                        final File wallpaperDir = getWallpaperDir(userId);
-                        for (String filename : sPerUserFiles) {
-                            File f = new File(wallpaperDir, filename);
-                            if (f.exists()) {
-                                SELinux.restorecon(f);
+                if (mUserRestorecon.get(userId) != Boolean.TRUE) {
+                    mUserRestorecon.put(userId, Boolean.TRUE);
+                    Runnable relabeler = new Runnable() {
+                        @Override
+                        public void run() {
+                            final File wallpaperDir = getWallpaperDir(userId);
+                            for (String filename : sPerUserFiles) {
+                                File f = new File(wallpaperDir, filename);
+                                if (f.exists()) {
+                                    SELinux.restorecon(f);
+                                }
                             }
                         }
-                    }
-                };
-                BackgroundThread.getHandler().post(relabeler);
+                    };
+                    BackgroundThread.getHandler().post(relabeler);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f357cd0..1b89327 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -200,7 +200,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
@@ -1951,11 +1950,6 @@
                             + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (type == TYPE_TOAST) {
-                    Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
-                            + attrs.token + ".  Aborting.");
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
@@ -2005,12 +1999,6 @@
                             + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (type == TYPE_TOAST) {
-                if (token.windowType != TYPE_TOAST) {
-                    Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
-                            + attrs.token + ".  Aborting.");
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
             } else if (type == TYPE_QS_DIALOG) {
                 if (token.windowType != TYPE_QS_DIALOG) {
                     Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index c351e73..3b63d93 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -51,6 +51,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.MediaStore;
@@ -78,6 +79,7 @@
     private static final String DEMO_USER_NAME = "Demo";
     private static final String ACTION_RESET_DEMO =
             "com.android.server.retaildemo.ACTION_RESET_DEMO";
+    private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
 
     private static final int MSG_TURN_SCREEN_ON = 0;
     private static final int MSG_INACTIVITY_TIME_OUT = 1;
@@ -220,9 +222,13 @@
             if (mDeviceDemoModeUri.equals(uri)) {
                 mDeviceInDemoMode = UserManager.isDeviceInDemoMode(getContext());
                 if (mDeviceInDemoMode) {
+                    SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
                     mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-                } else if (mWakeLock.isHeld()) {
-                    mWakeLock.release();
+                } else {
+                    SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
+                    if (mWakeLock.isHeld()) {
+                        mWakeLock.release();
+                    }
                 }
             }
             // If device is provisioned and left demo mode - run the cleanup in demo folder
@@ -470,6 +476,7 @@
 
         if (UserManager.isDeviceInDemoMode(getContext())) {
             mDeviceInDemoMode = true;
+            SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
             mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
         }
         SettingsObserver settingsObserver = new SettingsObserver(mHandler);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 3779d87..e89585c 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -696,8 +696,13 @@
         Slog.w(TAG, "Recognition aborted");
         MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
         ModelData modelData = getModelDataForLocked(event.soundModelHandle);
-        if (modelData != null) {
+        if (modelData != null && modelData.isModelStarted()) {
             modelData.setStopped();
+            try {
+                modelData.getCallback().onRecognitionPaused();
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
+            }
         }
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 65b5ee8b..061037c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -403,6 +403,13 @@
             "always_show_emergency_alert_onoff_bool";
 
     /**
+     * The flag to disable cell broadcast severe alert when extreme alert is disabled.
+     * @hide
+     */
+    public static final String KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL =
+            "disable_severe_when_extreme_disabled_bool";
+
+    /**
      * The data call APN retry configuration for default type APN.
      * @hide
      */
@@ -684,6 +691,8 @@
     public static final String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
     public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
     public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
+    /** @hide */
+    public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
 
     /**
      * If carriers require differentiate un-provisioned status: cold sim or out of credit sim
@@ -945,6 +954,7 @@
         sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
         sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
+        sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
         sDefaults.putString(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_DEFAULT_STRING,
                 "default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
                         + "320000:5000,640000:5000,1280000:5000,1800000:5000");
@@ -997,6 +1007,7 @@
         sDefaults.putBoolean(KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL, true);
         sDefaults.putBoolean(KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL, false);
         sDefaults.putBoolean(KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL, true);
+        sDefaults.putBoolean(KEY_MMS_CLOSE_CONNECTION_BOOL, false);
         sDefaults.putInt(KEY_MMS_ALIAS_MAX_CHARS_INT, 48);
         sDefaults.putInt(KEY_MMS_ALIAS_MIN_CHARS_INT, 2);
         sDefaults.putInt(KEY_MMS_HTTP_SOCKET_TIMEOUT_INT, 60 * 1000);