Merge "Alternate method for adding dismiss in talkback" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 70ea1c5..ebb9899 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2024,6 +2024,8 @@
     field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
     field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
     field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+    field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+    field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
     field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
     field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
     field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6455,7 +6457,7 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
-    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -23624,7 +23626,6 @@
     method public boolean isConnected();
     method public boolean isConnectedOrConnecting();
     method public boolean isFailover();
-    method public boolean isMetered();
     method public boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -34569,7 +34570,7 @@
 
 package android.service.notification {
 
-  public class Condition implements android.os.Parcelable {
+  public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     ctor public Condition(android.os.Parcel);
@@ -34606,7 +34607,7 @@
     method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
-    field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+    field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
     field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
     field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
     field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -42501,6 +42502,7 @@
     method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
     method public boolean performAccessibilityAction(int, android.os.Bundle);
     method public boolean performClick();
+    method public boolean performContextClick(float, float);
     method public boolean performContextClick();
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
diff --git a/api/removed.txt b/api/removed.txt
index 42c64ea..0ff2476 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -31,37 +31,6 @@
 
 }
 
-package android.app.usage {
-
-  public class DataUsagePolicy {
-    field public final int networkType;
-    field public final java.lang.String[] subscriberIds;
-    field public final long thresholdInBytes;
-    field public final int[] uids;
-  }
-
-  public static class DataUsagePolicy.Builder {
-    ctor public DataUsagePolicy.Builder();
-    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
-    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
-    method public android.app.usage.DataUsagePolicy build();
-    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
-    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
-  }
-
-  public class NetworkStatsManager {
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
-    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
-  }
-
-  public static abstract class NetworkStatsManager.DataUsageCallback {
-    ctor public NetworkStatsManager.DataUsageCallback();
-    method public deprecated void onLimitReached();
-  }
-
-}
-
 package android.content {
 
   public abstract class Context {
diff --git a/api/system-current.txt b/api/system-current.txt
index a6f612d..f0211fb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2136,6 +2136,8 @@
     field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
     field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
     field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+    field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+    field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
     field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
     field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
     field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6736,7 +6738,7 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
-    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -25446,7 +25448,6 @@
     method public boolean isConnected();
     method public boolean isConnectedOrConnecting();
     method public boolean isFailover();
-    method public boolean isMetered();
     method public boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -37292,7 +37293,7 @@
     field public static final java.lang.String NEEDS_AUTOGROUPING_KEY = "autogroup_needed";
   }
 
-  public class Condition implements android.os.Parcelable {
+  public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     ctor public Condition(android.os.Parcel);
@@ -37329,7 +37330,7 @@
     method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
-    field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+    field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
     field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
     field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
     field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -45499,6 +45500,7 @@
     method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
     method public boolean performAccessibilityAction(int, android.os.Bundle);
     method public boolean performClick();
+    method public boolean performContextClick(float, float);
     method public boolean performContextClick();
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 4873605..715312f 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -29,37 +29,6 @@
 
 }
 
-package android.app.usage {
-
-  public class DataUsagePolicy {
-    field public final int networkType;
-    field public final java.lang.String[] subscriberIds;
-    field public final long thresholdInBytes;
-    field public final int[] uids;
-  }
-
-  public static class DataUsagePolicy.Builder {
-    ctor public DataUsagePolicy.Builder();
-    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
-    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
-    method public android.app.usage.DataUsagePolicy build();
-    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
-    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
-  }
-
-  public class NetworkStatsManager {
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
-    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
-  }
-
-  public static abstract class NetworkStatsManager.DataUsageCallback {
-    ctor public NetworkStatsManager.DataUsageCallback();
-    method public deprecated void onLimitReached();
-  }
-
-}
-
 package android.content {
 
   public abstract class Context {
diff --git a/api/test-current.txt b/api/test-current.txt
index 37bc7af..9142ec0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2024,6 +2024,8 @@
     field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213
     field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214
     field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215
+    field public static final int TextAppearance_Material_Widget_Button_Borderless_Colored = 16974559; // 0x10302df
+    field public static final int TextAppearance_Material_Widget_Button_Colored = 16974558; // 0x10302de
     field public static final int TextAppearance_Material_Widget_Button_Inverse = 16974548; // 0x10302d4
     field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216
     field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217
@@ -6461,7 +6463,7 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
-    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
@@ -23693,7 +23695,6 @@
     method public boolean isConnected();
     method public boolean isConnectedOrConnecting();
     method public boolean isFailover();
-    method public boolean isMetered();
     method public boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -34646,7 +34647,7 @@
 
 package android.service.notification {
 
-  public class Condition implements android.os.Parcelable {
+  public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     ctor public Condition(android.os.Parcel);
@@ -34683,7 +34684,7 @@
     method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
-    field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+    field public static final java.lang.String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
     field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
     field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
     field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
@@ -42580,6 +42581,7 @@
     method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
     method public boolean performAccessibilityAction(int, android.os.Bundle);
     method public boolean performClick();
+    method public boolean performContextClick(float, float);
     method public boolean performContextClick();
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 42c64ea..0ff2476 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -31,37 +31,6 @@
 
 }
 
-package android.app.usage {
-
-  public class DataUsagePolicy {
-    field public final int networkType;
-    field public final java.lang.String[] subscriberIds;
-    field public final long thresholdInBytes;
-    field public final int[] uids;
-  }
-
-  public static class DataUsagePolicy.Builder {
-    ctor public DataUsagePolicy.Builder();
-    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
-    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
-    method public android.app.usage.DataUsagePolicy build();
-    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
-    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
-  }
-
-  public class NetworkStatsManager {
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
-    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
-    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
-  }
-
-  public static abstract class NetworkStatsManager.DataUsageCallback {
-    ctor public NetworkStatsManager.DataUsageCallback();
-    method public deprecated void onLimitReached();
-  }
-
-}
-
 package android.content {
 
   public abstract class Context {
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 8ff38bb..7841d29 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -465,20 +465,26 @@
 
     /**
      * The amount of time, in milliseconds, to delay starting the animation after
-     * {@link #start()} is called.
-
+     * {@link #start()} is called. Note that the start delay should always be non-negative. Any
+     * negative start delay will be clamped to 0 on N and above.
+     *
      * @param startDelay The amount of the delay, in milliseconds
      */
     @Override
     public void setStartDelay(long startDelay) {
-        if (mStartDelay > 0) {
-            mReversible = false;
+        // Clamp start delay to non-negative range.
+        if (startDelay < 0) {
+            Log.w(TAG, "Start delay should always be non-negative");
+            startDelay = 0;
         }
         long delta = startDelay - mStartDelay;
         if (delta == 0) {
             return;
         }
         mStartDelay = startDelay;
+        if (mStartDelay > 0) {
+            mReversible = false;
+        }
         if (!mDependencyDirty) {
             // Dependency graph already constructed, update all the nodes' start/end time
             int size = mNodes.size();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 0a9b5de..4edf249 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -708,12 +708,18 @@
 
     /**
      * The amount of time, in milliseconds, to delay starting the animation after
-     * {@link #start()} is called.
-
+     * {@link #start()} is called. Note that the start delay should always be non-negative. Any
+     * negative start delay will be clamped to 0 on N and above.
+     *
      * @param startDelay The amount of the delay, in milliseconds
      */
     @Override
     public void setStartDelay(long startDelay) {
+        // Clamp start delay to non-negative range.
+        if (startDelay < 0) {
+            Log.w(TAG, "Start delay should always be non-negative");
+            startDelay = 0;
+        }
         mStartDelay = startDelay;
     }
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a672d80..63afdd8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2191,7 +2191,8 @@
      * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
      * device admins that are not device owner and not profile owner.
      * The password can now only be changed if there is currently no password set.  Device owner
-     * and profile owner can still do this.</em>
+     * and profile owner can still do this when user is unlocked and does not have a managed
+     * profile.</em>
      * <p>
      * The given password must be sufficient for the current password quality and length constraints
      * as returned by {@link #getPasswordQuality(ComponentName)} and
@@ -2217,6 +2218,7 @@
      *         current constraints or if the user has not been decrypted yet.
      * @throws SecurityException if the calling application does not own an active administrator
      *             that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
+     * @throws IllegalStateException if the calling user is locked or has a managed profile.
      */
     public boolean resetPassword(String password, int flags) {
         throwIfParentInstance("resetPassword");
diff --git a/core/java/android/app/usage/DataUsagePolicy.java b/core/java/android/app/usage/DataUsagePolicy.java
deleted file mode 100644
index ee6b60c..0000000
--- a/core/java/android/app/usage/DataUsagePolicy.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package android.app.usage;
-
-import android.net.ConnectivityManager;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.IntArray;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Defines a policy for data usage callbacks, made through {@link DataUsagePolicy.Builder} and used
- * to be notified on data usage via {@link NetworkStatsManager#registerDataUsageCallback}.
- * @removed
- */
-public class DataUsagePolicy {
-
-    /**
-     * Network type to be monitored, as defined in {@link ConnectivityManager}, e.g.
-     * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} etc.
-     */
-    public final int networkType;
-
-    /**
-     * Set of subscriber ids to be monitored for the given network type. May be empty if not
-     * applicable.
-     * <p>Should not be modified once created.
-     */
-    public final String[] subscriberIds;
-
-    /**
-     * Set of UIDs of which to monitor data usage.
-     *
-     * <p>If not {@code null}, the caller will be notified when any of the uids exceed
-     * the given threshold. If empty all uids for which the calling process has access
-     * to stats will be monitored.
-     * <p>Should not be modified once created.
-     */
-    public final int[] uids;
-
-    /**
-     * Threshold in bytes to be notified on.
-     */
-    public final long thresholdInBytes;
-
-    /**
-     * @hide
-     */
-    DataUsagePolicy(int networkType, String[] subscriberIds, int[] uids,
-                long thresholdInBytes) {
-        this.networkType = networkType;
-        this.subscriberIds = subscriberIds;
-        this.uids = uids;
-        this.thresholdInBytes = thresholdInBytes;
-    }
-
-    /**
-     * Builder used to create {@link DataUsagePolicy} objects.
-     */
-    public static class Builder {
-        private static final int INVALID_NETWORK_TYPE = -1;
-        private int mNetworkType = INVALID_NETWORK_TYPE;
-        private List<String> mSubscriberList = new ArrayList<>();
-        private IntArray mUids = new IntArray();
-        private long mThresholdInBytes;
-
-        /**
-         * Default constructor for Builder.
-         */
-        public Builder() {}
-
-        /**
-         * Build {@link DataUsagePolicy} given the current policies.
-         */
-        public DataUsagePolicy build() {
-            if (mNetworkType == INVALID_NETWORK_TYPE) {
-                throw new IllegalArgumentException(
-                        "DataUsagePolicy requires a valid network type to be set");
-            }
-            return new DataUsagePolicy(mNetworkType,
-                    mSubscriberList.toArray(new String[mSubscriberList.size()]),
-                    mUids.toArray(), mThresholdInBytes);
-        }
-
-        /**
-         * Specifies that the given {@code subscriberId} should be monitored.
-         *
-         * @param subscriberId the subscriber id of the network interface.
-         */
-        public Builder addSubscriberId(String subscriberId) {
-            mSubscriberList.add(subscriberId);
-            return this;
-        }
-
-        /**
-         * Specifies that the given {@code uid} should be monitored.
-         */
-        public Builder addUid(int uid) {
-            mUids.add(uid);
-            return this;
-        }
-
-        /**
-         * Specifies that the callback should monitor the given network. It is mandatory
-         * to set one.
-         *
-         * @param networkType As defined in {@link ConnectivityManager}, e.g.
-         *            {@link ConnectivityManager#TYPE_MOBILE},
-         *            {@link ConnectivityManager#TYPE_WIFI}, etc.
-         */
-        public Builder setNetworkType(int networkType) {
-            mNetworkType = networkType;
-            return this;
-        }
-
-        /**
-         * Sets the threshold in bytes on which the listener should be called. The framework may
-         * impose a minimum threshold to avoid too many notifications to be triggered.
-         */
-        public Builder setThreshold(long thresholdInBytes) {
-            mThresholdInBytes = thresholdInBytes;
-            return this;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "DataUsagePolicy [ networkType=" + networkType
-                + ", subscriberIds=" + Arrays.toString(subscriberIds)
-                + ", uids=" + Arrays.toString(uids)
-                + ", thresholdInBytes=" + thresholdInBytes + " ]";
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof DataUsagePolicy == false) return false;
-        DataUsagePolicy that = (DataUsagePolicy) obj;
-        return that.networkType == this.networkType
-                && Arrays.deepEquals(that.subscriberIds, this.subscriberIds)
-                && Arrays.equals(that.uids, this.uids)
-                && that.thresholdInBytes == this.thresholdInBytes;
-    }
-
-    @Override
-    public int hashCode() {
-        // Start with a non-zero constant.
-        int result = 17;
-
-        // Include a hash for each field.
-        result = 31 * result + networkType;
-        result = 31 * result + Arrays.deepHashCode(subscriberIds);
-        result = 31 * result + Arrays.hashCode(uids);
-        result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
-
-        return result;
-   }
-}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 4a28117..720c84a 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -240,18 +240,13 @@
      *            {@link java.lang.System#currentTimeMillis}.
      * @param uid UID of app
      * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
-     * @return Statistics object or null if permissions are insufficient or error happened during
-     *         statistics collection.
+     * @return Statistics object or null if an error happened during statistics collection.
+     * @throws SecurityException if permissions are insufficient to read network statistics.
      */
     public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
-            long startTime, long endTime, int uid, int tag) {
+            long startTime, long endTime, int uid, int tag) throws SecurityException {
         NetworkTemplate template;
-        try {
-            template = createTemplate(networkType, subscriberId);
-        } catch (IllegalArgumentException e) {
-            if (DBG) Log.e(TAG, "Cannot create template", e);
-            return null;
-        }
+        template = createTemplate(networkType, subscriberId);
 
         NetworkStats result;
         try {
@@ -303,17 +298,6 @@
         return result;
     }
 
-    /** @removed */
-    public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
-                @Nullable Handler handler) {}
-
-    /** @removed */
-    public void registerDataUsageCallback(DataUsagePolicy policy, UsageCallback callback,
-                @Nullable Handler handler) {}
-
-    /** @removed */
-    public void unregisterDataUsageCallback(DataUsageCallback callback) {}
-
     /**
      * Registers to receive notifications about data usage on specified networks.
      *
@@ -396,13 +380,6 @@
         }
     }
 
-    /** @removed */
-    public static abstract class DataUsageCallback {
-        /** @removed */
-        @Deprecated
-        public void onLimitReached() {}
-    }
-
     /**
      * Base class for usage callbacks. Should be extended by applications wanting notifications.
      */
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4c86578..9390bcd 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2045,12 +2045,15 @@
             public void onBluetoothServiceDown() {
                 if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
 
-                mServiceLock.writeLock().lock();
-                mService = null;
-                if (mLeScanClients != null) mLeScanClients.clear();
-                if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
-                if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
-                mServiceLock.writeLock().unlock();
+                try {
+                    mServiceLock.writeLock().lock();
+                    mService = null;
+                    if (mLeScanClients != null) mLeScanClients.clear();
+                    if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
+                    if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
+                } finally {
+                    mServiceLock.writeLock().unlock();
+                }
 
                 synchronized (mProxyServiceStateCallbacks) {
                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a43d06e..b758868 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1415,6 +1415,8 @@
      * this context. This is typically used to migrate data between storage
      * locations after an upgrade, such as migrating to device protected
      * storage.
+     * <p>
+     * The database must be closed before being moved.
      *
      * @param sourceContext The source context which contains the existing
      *            database to move.
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index b6c5c6f..42f5feb 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -334,6 +334,7 @@
      *
      * @return {@code true} if large transfers should be avoided, otherwise
      *         {@code false}.
+     * @hide
      */
     public boolean isMetered() {
         synchronized (this) {
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 6138b83..f8b5992 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -68,8 +68,28 @@
 
     @Override
     public String toString() {
-      return String.format("DefaultNetworkEvent(%d -> %d, %s, IPv4: %b, IPv6: %b)", prevNetId,
-              netId, NetworkCapabilities.transportNamesOf(transportTypes), prevIPv4, prevIPv6);
+      String prevNetwork = String.valueOf(prevNetId);
+      String newNetwork = String.valueOf(netId);
+      if (prevNetId != 0) {
+          prevNetwork += ":" + ipSupport();
+      }
+      if (netId != 0) {
+          newNetwork += ":" + NetworkCapabilities.transportNamesOf(transportTypes);
+      }
+      return String.format("DefaultNetworkEvent(%s -> %s)", prevNetwork, newNetwork);
+    }
+
+    private String ipSupport() {
+        if (prevIPv4 && prevIPv6) {
+            return "DUAL";
+        }
+        if (prevIPv6) {
+            return "IPv6";
+        }
+        if (prevIPv4) {
+            return "IPv4";
+        }
+        return "NONE";
     }
 
     public static final Parcelable.Creator<DefaultNetworkEvent> CREATOR
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 60b618a..2dc3beb 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -148,17 +148,6 @@
     }
 
     /**
-     * It is almost always better to call {@link #getEmptyLocaleList()} instead which returns
-     * a pre-constructed empty locale list.
-     *
-     * @hide
-     */
-    public LocaleList() {
-        mList = sEmptyList;
-        mStringRepresentation = "";
-    }
-
-    /**
      * Creates a new {@link LocaleList}.
      *
      * <p>For empty lists of {@link Locale} items it is better to use {@link #getEmptyLocaleList()},
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 0163b47..447afe6 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -33,7 +33,7 @@
  * {@link ConditionProviderService} that owns the rule. Used to tell the system to enter Do Not
  * Disturb mode and request that the system exit Do Not Disturb mode.
  */
-public class Condition implements Parcelable {
+public final class Condition implements Parcelable {
 
     @SystemApi
     public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 44c3887..9d4b0a4 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -95,7 +95,7 @@
     /**
      * A String rule id extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}.
      */
-    public static final String EXTRA_RULE_ID = "android.content.automatic.ruleId";
+    public static final String EXTRA_RULE_ID = "android.service.notification.extra.RULE_ID";
 
     /**
      * Called when this service is connected.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 7b01267..b4131b4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -46,7 +46,7 @@
             boolean allLayers, boolean useIdentityTransform);
 
     private static native void nativeOpenTransaction();
-    private static native void nativeCloseTransaction();
+    private static native void nativeCloseTransaction(boolean sync);
     private static native void nativeSetAnimationTransaction();
 
     private static native void nativeSetLayer(long nativeObject, int zorder);
@@ -372,7 +372,11 @@
 
     /** end a transaction */
     public static void closeTransaction() {
-        nativeCloseTransaction();
+        nativeCloseTransaction(false);
+    }
+
+    public static void closeTransactionSync() {
+        nativeCloseTransaction(true);
     }
 
     public void deferTransactionUntil(IBinder handle, long frame) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2269282..f1f4964 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5698,6 +5698,18 @@
     /**
      * Call this view's OnContextClickListener, if it is defined.
      *
+     * @param x the x coordinate of the context click
+     * @param y the y coordinate of the context click
+     * @return True if there was an assigned OnContextClickListener that consumed the event, false
+     *         otherwise.
+     */
+    public boolean performContextClick(float x, float y) {
+        return performContextClick();
+    }
+
+    /**
+     * Call this view's OnContextClickListener, if it is defined.
+     *
      * @return True if there was an assigned OnContextClickListener that consumed the event, false
      *         otherwise.
      */
@@ -10044,7 +10056,7 @@
                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
-                    if (performContextClick()) {
+                    if (performContextClick(event.getX(), event.getY())) {
                         mInContextButtonPress = true;
                         setPressed(true, event.getX(), event.getY());
                         removeTapCallback();
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1618758..4013b30 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1277,6 +1277,28 @@
                             return true;
                         }
                     }
+                } else {
+                    if (startInputReason
+                            == InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN) {
+                        // We are here probably because of an obsolete window-focus-in message sent
+                        // to windowGainingFocus.  Since IMMS determines whether a Window can have
+                        // IME focus or not by using the latest window focus state maintained in the
+                        // WMS, this kind of race condition cannot be avoided.  One obvious example
+                        // would be that we have already received a window-focus-out message but the
+                        // UI thread is still handling previous window-focus-in message here.
+                        // TODO: InputBindResult should have the error code.
+                        if (DEBUG) Log.w(TAG, "startInputOrWindowGainedFocus failed. "
+                                + "Window focus may have already been lost. "
+                                + "win=" + windowGainingFocus + " view=" + dumpViewInfo(view));
+                        if (!mActive) {
+                            // mHasBeenInactive is a latch switch to forcefully refresh IME focus
+                            // state when an inactive (mActive == false) client is gaining window
+                            // focus. In case we have unnecessary disable the latch due to this
+                            // spurious wakeup, we re-enable the latch here.
+                            // TODO: Come up with more robust solution.
+                            mHasBeenInactive = true;
+                        }
+                    }
                 }
                 if (mCurMethod != null && mCompletions != null) {
                     try {
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 66896ab..ac44033 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.annotation.AttrRes;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
@@ -27,17 +29,16 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.icu.util.Calendar;
+import android.icu.util.TimeZone;
 import android.util.AttributeSet;
 import android.util.Log;
-import com.android.internal.R;
 
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
-import java.util.TimeZone;
 
 /**
  * This class is a calendar widget for displaying and selecting dates. The
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index f540479..2b91713 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -27,6 +27,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.icu.util.Calendar;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -37,7 +38,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import java.util.Calendar;
 import java.util.Locale;
 
 import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java
index 0ed75d5..07b2000 100644
--- a/core/java/android/widget/CalendarViewMaterialDelegate.java
+++ b/core/java/android/widget/CalendarViewMaterialDelegate.java
@@ -18,11 +18,10 @@
 
 import android.annotation.StyleRes;
 import android.content.Context;
+import android.icu.util.Calendar;
 import android.util.AttributeSet;
 import android.widget.DayPickerView.OnDaySelectedListener;
 
-import java.util.Calendar;
-
 class CalendarViewMaterialDelegate extends CalendarView.AbstractCalendarViewDelegate {
     private final DayPickerView mDayPickerView;
 
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0c5edc5..8613f99 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,11 +16,15 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.annotation.Nullable;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.icu.util.Calendar;
+import android.icu.util.TimeZone;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
@@ -28,11 +32,7 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
-import com.android.internal.R;
-
-import java.util.Calendar;
 import java.util.Locale;
-import java.util.TimeZone;
 
 /**
  * Provides a widget for selecting a date.
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 0a23b34..2fd52b5 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.icu.text.DisplayContext;
 import android.icu.text.SimpleDateFormat;
+import android.icu.util.Calendar;
 import android.os.Parcelable;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
@@ -40,7 +41,6 @@
 import android.widget.DayPickerView.OnDaySelectedListener;
 import android.widget.YearPickerView.OnYearSelectedListener;
 
-import java.util.Calendar;
 import java.util.Locale;
 
 /**
@@ -432,7 +432,8 @@
     public void setMinDate(long minDate) {
         mTempDate.setTimeInMillis(minDate);
         if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
+            // Same day, no-op.
             return;
         }
         if (mCurrentDate.before(mTempDate)) {
@@ -453,7 +454,8 @@
     public void setMaxDate(long maxDate) {
         mTempDate.setTimeInMillis(maxDate);
         if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+            // Same day, no-op.
             return;
         }
         if (mCurrentDate.after(mTempDate)) {
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index d8a3c56..1a6d351 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.icu.util.Calendar;
 import android.os.Parcelable;
 import android.text.InputType;
 import android.text.TextUtils;
@@ -37,7 +38,6 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
-import java.util.Calendar;
 import java.util.Locale;
 
 import libcore.icu.ICU;
@@ -288,7 +288,8 @@
     public void setMinDate(long minDate) {
         mTempDate.setTimeInMillis(minDate);
         if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
+            // Same day, no-op.
             return;
         }
         mMinDate.setTimeInMillis(minDate);
@@ -311,7 +312,8 @@
     public void setMaxDate(long maxDate) {
         mTempDate.setTimeInMillis(maxDate);
         if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+            // Same day, no-op.
             return;
         }
         mMaxDate.setTimeInMillis(maxDate);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 97936e7..9f02b44 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -25,14 +25,13 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.icu.util.Calendar;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.SimpleMonthView.OnDayClickListener;
 
-import java.util.Calendar;
-
 /**
  * An adapter for a list of {@link android.widget.SimpleMonthView} items.
  */
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index dc772fb..ab89c1f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.icu.util.Calendar;
 import android.util.AttributeSet;
 import android.util.MathUtils;
 import android.view.LayoutInflater;
@@ -31,7 +32,6 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 
-import java.util.Calendar;
 import java.util.Locale;
 
 import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 622567c..15bba3a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -76,6 +76,7 @@
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
 import android.view.ContextMenu;
+import android.view.ContextThemeWrapper;
 import android.view.DisplayListCanvas;
 import android.view.DragAndDropPermissions;
 import android.view.DragEvent;
@@ -3004,8 +3005,16 @@
         protected abstract int getTextOffset();
         protected abstract int getVerticalLocalPosition(int line);
         protected abstract int clipVertically(int positionY);
+        protected void setUp() {
+        }
 
         public PinnedPopupWindow() {
+            // Due to calling subclass methods in base constructor, subclass constructor is not
+            // called before subclass methods, e.g. createPopupWindow or initContentView. To give
+            // a chance to initialize subclasses, call setUp() method here.
+            // TODO: It is good to extract non trivial initialization code from constructor.
+            setUp();
+
             createPopupWindow();
 
             mPopupWindow.setWindowLayoutType(
@@ -3267,8 +3276,7 @@
         private boolean mCursorWasVisibleBeforeSuggestions;
         private boolean mIsShowingUp = false;
         private SuggestionAdapter mSuggestionsAdapter;
-        private final TextAppearanceSpan mHighlightSpan = new TextAppearanceSpan(
-                mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
+        private TextAppearanceSpan mHighlightSpan;  // TODO: Make mHighlightSpan final.
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
         private ListView mSuggestionListView;
@@ -3276,8 +3284,10 @@
         private int mContainerMarginWidth;
         private int mContainerMarginTop;
         private LinearLayout mContainerView;
+        private Context mContext;  // TODO: Make mContext final.
 
         private class CustomPopupWindow extends PopupWindow {
+
             @Override
             public void dismiss() {
                 if (!isShowing()) {
@@ -3301,6 +3311,23 @@
         }
 
         @Override
+        protected void setUp() {
+            mContext = applyDefaultTheme(mTextView.getContext());
+            mHighlightSpan = new TextAppearanceSpan(mContext,
+                    mTextView.mTextEditSuggestionHighlightStyle);
+        }
+
+        private Context applyDefaultTheme(Context originalContext) {
+            TypedArray a = originalContext.obtainStyledAttributes(
+                    new int[]{com.android.internal.R.attr.isLightTheme});
+            boolean isLightTheme = a.getBoolean(0, true);
+            int themeId = isLightTheme ? R.style.ThemeOverlay_Material_Light
+                    : R.style.ThemeOverlay_Material_Dark;
+            a.recycle();
+            return new ContextThemeWrapper(originalContext, themeId);
+        }
+
+        @Override
         protected void createPopupWindow() {
             mPopupWindow = new CustomPopupWindow();
             mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
@@ -3311,8 +3338,8 @@
 
         @Override
         protected void initContentView() {
-            final LayoutInflater inflater = (LayoutInflater) mTextView.getContext().
-                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
             mContentView = (ViewGroup) inflater.inflate(
                     mTextView.mTextEditSuggestionContainerLayout, null);
 
@@ -3405,8 +3432,8 @@
         }
 
         private class SuggestionAdapter extends BaseAdapter {
-            private LayoutInflater mInflater = (LayoutInflater) mTextView.getContext().
-                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            private LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
 
             @Override
             public int getCount() {
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 97d834a..588425f 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -32,6 +32,7 @@
 import android.graphics.Typeface;
 import android.icu.text.DisplayContext;
 import android.icu.text.SimpleDateFormat;
+import android.icu.util.Calendar;
 import android.os.Bundle;
 import android.text.TextPaint;
 import android.text.format.DateFormat;
@@ -48,7 +49,6 @@
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
 import java.text.NumberFormat;
-import java.util.Calendar;
 import java.util.Locale;
 
 import libcore.icu.LocaleData;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fc120eb..3711b94 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6983,14 +6983,19 @@
         return false;
     }
 
-    private static int desired(Layout layout) {
+    private static int desired(Layout layout, int maxLines) {
         int n = layout.getLineCount();
         CharSequence text = layout.getText();
         float max = 0;
 
+        // if maxLines is set, and the text length is greater that the length of the text in the
+        // layout, it means that there is a cut-off and we cannot use it.
+        if (maxLines != -1 && text.length() > layout.getLineEnd(n - 1)) {
+            return -1;
+        }
+
         // if any line was wrapped, we can't use it.
         // but it's ok for the last line not to have a newline
-
         for (int i = 0; i < n - 1; i++) {
             if (text.charAt(layout.getLineEnd(i) - 1) != '\n')
                 return -1;
@@ -7063,7 +7068,7 @@
             width = widthSize;
         } else {
             if (mLayout != null && mEllipsize == null) {
-                des = desired(mLayout);
+                des = desired(mLayout, getMaxLines());
             }
 
             if (des < 0) {
@@ -7095,7 +7100,7 @@
                 int hintWidth;
 
                 if (mHintLayout != null && mEllipsize == null) {
-                    hintDes = desired(mHintLayout);
+                    hintDes = desired(mHintLayout, getMaxLines());
                 }
 
                 if (hintDes < 0) {
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 96624d2..a3f5a67 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -16,18 +16,17 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.Resources;
+import android.icu.util.Calendar;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
-import java.util.Calendar;
-
-import com.android.internal.R;
-
 /**
  * Displays a selectable list of years.
  */
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 07f3801..ddf3a76 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -231,6 +231,7 @@
         popupWindow.setAnchorView(mAnchorView);
         popupWindow.setDropDownGravity(mDropDownGravity);
         popupWindow.setModal(true);
+        popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
         return popupWindow;
     }
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index a5485da..70941b6 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -141,6 +141,9 @@
     // consider it a complex PIN/password.
     public static final int MAX_ALLOWED_SEQUENCE = 3;
 
+    public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
+    public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
+
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private DevicePolicyManager mDevicePolicyManager;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 864a0bf..a9ed9dc 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -223,8 +223,9 @@
     SurfaceComposerClient::openGlobalTransaction();
 }
 
-static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
-    SurfaceComposerClient::closeGlobalTransaction();
+
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz, jboolean sync) {
+    SurfaceComposerClient::closeGlobalTransaction(sync);
 }
 
 static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
@@ -649,7 +650,7 @@
             (void*)nativeScreenshot },
     {"nativeOpenTransaction", "()V",
             (void*)nativeOpenTransaction },
-    {"nativeCloseTransaction", "()V",
+    {"nativeCloseTransaction", "(Z)V",
             (void*)nativeCloseTransaction },
     {"nativeSetAnimationTransaction", "()V",
             (void*)nativeSetAnimationTransaction },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2ff4ef..6c289dc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -273,6 +273,9 @@
     <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
+    <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
+    <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
+    <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
@@ -322,6 +325,9 @@
     <protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
 
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
+    <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
+    <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
 
     <protected-broadcast
         android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
@@ -384,6 +390,7 @@
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
 
     <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
+    <protected-broadcast android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT" />
     <protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
     <protected-broadcast android:name="android.content.syncmanager.SYNC_ALARM" />
     <protected-broadcast android:name="android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION" />
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 30e23f5..e190bd1 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -22,296 +22,120 @@
     <!-- Do not translate. These are all of the drawable resources that should be preloaded by
          the zygote process before it starts forking application processes. -->
     <array name="preloaded_drawables">
-       <item>@drawable/toast_frame</item>
-       <item>@drawable/btn_check_on_pressed_holo_light</item>
-       <item>@drawable/btn_check_on_pressed_holo_dark</item>
-       <item>@drawable/btn_check_on_holo_light</item>
-       <item>@drawable/btn_check_on_holo_dark</item>
-       <item>@drawable/btn_check_on_focused_holo_light</item>
-       <item>@drawable/btn_check_on_focused_holo_dark</item>
-       <item>@drawable/btn_check_on_disabled_holo_light</item>
-       <item>@drawable/btn_check_on_disabled_holo_dark</item>
-       <item>@drawable/btn_check_on_disabled_focused_holo_light</item>
-       <item>@drawable/btn_check_on_disabled_focused_holo_dark</item>
-       <item>@drawable/btn_check_off_pressed_holo_light</item>
-       <item>@drawable/btn_check_off_pressed_holo_dark</item>
-       <item>@drawable/btn_check_off_holo_light</item>
-       <item>@drawable/btn_check_off_holo_dark</item>
-       <item>@drawable/btn_check_off_focused_holo_light</item>
-       <item>@drawable/btn_check_off_focused_holo_dark</item>
-       <item>@drawable/btn_check_off_disabled_holo_light</item>
-       <item>@drawable/btn_check_off_disabled_holo_dark</item>
-       <item>@drawable/btn_check_off_disabled_focused_holo_light</item>
-       <item>@drawable/btn_check_off_disabled_focused_holo_dark</item>
-       <item>@drawable/btn_check_holo_light</item>
-       <item>@drawable/btn_check_holo_dark</item>
-       <item>@drawable/btn_radio_on_pressed_holo_light</item>
-       <item>@drawable/btn_radio_on_pressed_holo_dark</item>
-       <item>@drawable/btn_radio_on_holo_light</item>
-       <item>@drawable/btn_radio_on_holo_dark</item>
-       <item>@drawable/btn_radio_on_focused_holo_light</item>
-       <item>@drawable/btn_radio_on_focused_holo_dark</item>
-       <item>@drawable/btn_radio_on_disabled_holo_light</item>
-       <item>@drawable/btn_radio_on_disabled_holo_dark</item>
-       <item>@drawable/btn_radio_on_disabled_focused_holo_light</item>
-       <item>@drawable/btn_radio_on_disabled_focused_holo_dark</item>
-       <item>@drawable/btn_radio_off_pressed_holo_light</item>
-       <item>@drawable/btn_radio_off_pressed_holo_dark</item>
-       <item>@drawable/btn_radio_off_holo_light</item>
-       <item>@drawable/btn_radio_off_holo_dark</item>
-       <item>@drawable/btn_radio_off_focused_holo_light</item>
-       <item>@drawable/btn_radio_off_focused_holo_dark</item>
-       <item>@drawable/btn_radio_off_disabled_holo_light</item>
-       <item>@drawable/btn_radio_off_disabled_holo_dark</item>
-       <item>@drawable/btn_radio_off_disabled_focused_holo_light</item>
-       <item>@drawable/btn_radio_off_disabled_focused_holo_dark</item>
-       <item>@drawable/btn_default_pressed_holo_light</item>
-       <item>@drawable/btn_default_pressed_holo_dark</item>
-       <item>@drawable/btn_default_normal_holo_light</item>
-       <item>@drawable/btn_default_normal_holo_dark</item>
-       <item>@drawable/btn_default_focused_holo_light</item>
-       <item>@drawable/btn_default_focused_holo_dark</item>
-       <item>@drawable/btn_default_disabled_holo_light</item>
-       <item>@drawable/btn_default_disabled_holo_dark</item>
-       <item>@drawable/btn_default_disabled_focused_holo_light</item>
-       <item>@drawable/btn_default_disabled_focused_holo_dark</item>
-       <item>@drawable/btn_default_holo_dark</item>
-       <item>@drawable/btn_default_holo_light</item>
-       <item>@drawable/edit_text_holo_light</item>
-       <item>@drawable/edit_text_holo_dark</item>
-       <item>@drawable/text_cursor_holo_light</item>
-       <item>@drawable/text_cursor_holo_dark</item>
-       <item>@drawable/text_edit_paste_window</item>
-       <item>@drawable/expander_close_holo_dark</item>
-       <item>@drawable/expander_close_holo_light</item>
-       <item>@drawable/expander_group_holo_dark</item>
-       <item>@drawable/expander_group_holo_light</item>
-       <item>@drawable/list_selector_holo_dark</item>
-       <item>@drawable/list_selector_holo_light</item>
-       <item>@drawable/list_section_divider_holo_light</item>
-       <item>@drawable/list_section_divider_holo_dark</item>
-       <item>@drawable/menu_dropdown_panel_holo_light</item>
-       <item>@drawable/menu_dropdown_panel_holo_dark</item>
-       <item>@drawable/menu_panel_holo_light</item>
-       <item>@drawable/menu_panel_holo_dark</item>
-       <item>@drawable/spinner_16_outer_holo</item>
-       <item>@drawable/spinner_16_inner_holo</item>
-       <item>@drawable/spinner_48_outer_holo</item>
-       <item>@drawable/spinner_48_inner_holo</item>
-       <item>@drawable/progress_bg_holo_dark</item>
-       <item>@drawable/progress_bg_holo_light</item>
-       <item>@drawable/progress_horizontal_holo_dark</item>
-       <item>@drawable/progress_horizontal_holo_light</item>
-       <item>@drawable/progress_large_holo</item>
-       <item>@drawable/progress_medium_holo</item>
-       <item>@drawable/progress_primary_holo_dark</item>
-       <item>@drawable/progress_primary_holo_light</item>
-       <item>@drawable/progress_secondary_holo_dark</item>
-       <item>@drawable/progress_secondary_holo_light</item>
-       <item>@drawable/progress_small_holo</item>
-       <item>@drawable/scrubber_progress_horizontal_holo_dark</item>
-       <item>@drawable/scrubber_progress_horizontal_holo_light</item>
-       <item>@drawable/background_holo_light</item>
-       <item>@drawable/background_holo_dark</item>
-       <item>@drawable/screen_background_dark</item>
-       <item>@drawable/screen_background_dark_transparent</item>
-       <item>@drawable/screen_background_light</item>
-       <item>@drawable/screen_background_light_transparent</item>
-       <item>@drawable/screen_background_selector_dark</item>
-       <item>@drawable/screen_background_selector_light</item>
-       <item>@drawable/scrollbar_handle_holo_dark</item>
-       <item>@drawable/scrollbar_handle_holo_light</item>
-       <item>@drawable/spinner_background_holo_dark</item>
-       <item>@drawable/spinner_background_holo_light</item>
-       <item>@drawable/spinner_ab_default_holo_dark</item>
-       <item>@drawable/spinner_ab_default_holo_light</item>
-       <item>@drawable/spinner_ab_disabled_holo_dark</item>
-       <item>@drawable/spinner_ab_disabled_holo_light</item>
-       <item>@drawable/spinner_ab_focused_holo_dark</item>
-       <item>@drawable/spinner_ab_focused_holo_light</item>
-       <item>@drawable/spinner_ab_pressed_holo_dark</item>
-       <item>@drawable/spinner_ab_pressed_holo_light</item>
-       <item>@drawable/spinner_ab_holo_dark</item>
-       <item>@drawable/spinner_ab_holo_light</item>
-       <item>@drawable/spinner_default_holo_dark</item>
-       <item>@drawable/spinner_default_holo_light</item>
-       <item>@drawable/spinner_disabled_holo_dark</item>
-       <item>@drawable/spinner_disabled_holo_light</item>
-       <item>@drawable/spinner_focused_holo_dark</item>
-       <item>@drawable/spinner_focused_holo_light</item>
-       <item>@drawable/spinner_pressed_holo_dark</item>
-       <item>@drawable/spinner_pressed_holo_light</item>
-       <item>@drawable/cab_background_bottom_holo_dark</item>
-       <item>@drawable/cab_background_top_holo_light</item>
-       <item>@drawable/cab_background_bottom_holo_light</item>
-       <item>@drawable/ic_cab_done_holo_dark</item>
-       <item>@drawable/cab_background_top_holo_dark</item>
-       <item>@drawable/ic_cab_done_holo_light</item>
-       <item>@drawable/btn_cab_done_default_holo_dark</item>
-       <item>@drawable/btn_cab_done_focused_holo_light</item>
-       <item>@drawable/btn_cab_done_default_holo_light</item>
-       <item>@drawable/btn_cab_done_pressed_holo_dark</item>
-       <item>@drawable/btn_cab_done_focused_holo_dark</item>
-       <item>@drawable/btn_cab_done_pressed_holo_light</item>
-       <item>@drawable/btn_cab_done_holo_light</item>
-       <item>@drawable/btn_cab_done_holo_dark</item>
-       <item>@drawable/ic_menu_close_clear_cancel</item>
-       <item>@drawable/ic_menu_copy_holo_dark</item>
-       <item>@drawable/ic_menu_copy_holo_light</item>
-       <item>@drawable/ic_menu_cut_holo_dark</item>
-       <item>@drawable/ic_menu_cut_holo_light</item>
-       <item>@drawable/ic_menu_more</item>
-       <item>@drawable/ic_menu_moreoverflow_holo_dark</item>
-       <item>@drawable/ic_menu_moreoverflow_holo_light</item>
-       <item>@drawable/ic_menu_paste_holo_dark</item>
-       <item>@drawable/ic_menu_paste_holo_light</item>
-       <item>@drawable/ic_menu_selectall_holo_light</item>
-       <item>@drawable/ic_menu_selectall_holo_dark</item>
-       <item>@drawable/ic_clear</item>
-       <item>@drawable/ic_clear_disabled</item>
-       <item>@drawable/ic_clear_normal</item>
-       <item>@drawable/ic_search_api_holo_dark</item>
-       <item>@drawable/ic_search_api_holo_light</item>
-       <item>@drawable/ic_go</item>
-       <item>@drawable/ic_voice_search_api_holo_dark</item>
-       <item>@drawable/ic_voice_search_api_holo_light</item>
-       <item>@drawable/dialog_bottom_holo_dark</item>
-       <item>@drawable/dialog_bottom_holo_light</item>
-       <item>@drawable/dialog_middle_holo_dark</item>
-       <item>@drawable/dialog_middle_holo_light</item>
-       <item>@drawable/dialog_top_holo_dark</item>
-       <item>@drawable/dialog_top_holo_light</item>
-       <item>@drawable/ic_dialog_alert_holo_dark</item>
-       <item>@drawable/ic_dialog_alert_holo_light</item>
-       <item>@drawable/list_divider_holo_dark</item>
-       <item>@drawable/list_divider_holo_light</item>
-       <item>@drawable/list_divider_holo_light</item>
-       <item>@drawable/ab_transparent_dark_holo</item>
-       <item>@drawable/ab_stacked_transparent_dark_holo</item>
-       <item>@drawable/ab_bottom_transparent_dark_holo</item>
-       <item>@drawable/ab_solid_dark_holo</item>
-       <item>@drawable/ab_stacked_solid_dark_holo</item>
-       <item>@drawable/ab_bottom_solid_dark_holo</item>
-       <item>@drawable/ab_transparent_light_holo</item>
-       <item>@drawable/ab_stacked_transparent_light_holo</item>
-       <item>@drawable/ab_bottom_transparent_light_holo</item>
-       <item>@drawable/ab_solid_light_holo</item>
-       <item>@drawable/ab_stacked_solid_light_holo</item>
-       <item>@drawable/ab_bottom_solid_light_holo</item>
-       <item>@drawable/ab_solid_shadow_holo</item>
-       <item>@drawable/item_background_holo_dark</item>
-       <item>@drawable/item_background_holo_light</item>
-       <item>@drawable/fastscroll_thumb_holo</item>
-       <item>@drawable/fastscroll_thumb_pressed_holo</item>
-       <item>@drawable/fastscroll_thumb_default_holo</item>
-       <item>@drawable/fastscroll_track_holo_dark</item>
-       <item>@drawable/fastscroll_track_pressed_holo_dark</item>
-       <item>@drawable/fastscroll_track_default_holo_dark</item>
-       <item>@drawable/fastscroll_track_holo_light</item>
-       <item>@drawable/fastscroll_track_pressed_holo_light</item>
-       <item>@drawable/fastscroll_track_default_holo_light</item>
-       <item>@drawable/editbox_dropdown_background_dark</item>
-       <item>@drawable/textfield_searchview_holo_dark</item>
-       <item>@drawable/textfield_searchview_right_holo_dark</item>
-       <item>@drawable/textfield_searchview_holo_light</item>
-       <item>@drawable/textfield_searchview_right_holo_light</item>
-       <item>@drawable/textfield_search_selected_holo_dark</item>
-       <item>@drawable/textfield_search_default_holo_dark</item>
-       <item>@drawable/textfield_search_right_selected_holo_dark</item>
-       <item>@drawable/textfield_search_right_default_holo_dark</item>
-       <item>@drawable/textfield_search_selected_holo_light</item>
-       <item>@drawable/textfield_search_default_holo_light</item>
-       <item>@drawable/textfield_search_right_selected_holo_light</item>
-       <item>@drawable/textfield_search_right_default_holo_light</item>
-       <item>@drawable/tab_indicator_holo</item>
-       <item>@drawable/tab_unselected_holo</item>
-       <item>@drawable/tab_selected_holo</item>
-       <item>@drawable/tab_unselected_focused_holo</item>
-       <item>@drawable/tab_selected_focused_holo</item>
-       <item>@drawable/tab_unselected_pressed_holo</item>
-       <item>@drawable/tab_selected_pressed_holo</item>
-       <item>@drawable/quickcontact_badge_overlay_dark</item>
-       <item>@drawable/quickcontact_badge_overlay_normal_dark</item>
-       <item>@drawable/quickcontact_badge_overlay_pressed_dark</item>
-       <item>@drawable/quickcontact_badge_overlay_light</item>
-       <item>@drawable/quickcontact_badge_overlay_normal_light</item>
-       <item>@drawable/quickcontact_badge_overlay_pressed_light</item>
-
-       <!-- Material assets -->
-       <item>@drawable/ab_share_pack_material</item>
-       <item>@drawable/ab_solid_shadow_material</item>
-       <item>@drawable/activated_background_material</item>
-       <item>@drawable/btn_borderless_material</item>
-       <item>@drawable/btn_check_material_anim</item>
-       <item>@drawable/btn_default_material</item>
-       <item>@drawable/btn_radio_material_anim</item>
-       <item>@drawable/btn_star_material</item>
-       <item>@drawable/btn_toggle_material</item>
-       <item>@drawable/cab_background_bottom_material</item>
-       <item>@drawable/cab_background_top_material</item>
-       <item>@drawable/dialog_background_material</item>
-       <item>@drawable/edit_text_material</item>
-       <item>@drawable/expander_group_material</item>
-       <item>@drawable/fastscroll_label_left_material</item>
-       <item>@drawable/fastscroll_label_right_material</item>
-       <item>@drawable/fastscroll_thumb_material</item>
-       <item>@drawable/fastscroll_track_material</item>
-       <item>@drawable/floating_popup_background_dark</item>
-       <item>@drawable/floating_popup_background_light</item>
-       <item>@drawable/ic_ab_back_material</item>
-       <item>@drawable/ic_ab_back_material_dark</item>
-       <item>@drawable/ic_ab_back_material_light</item>
-       <item>@drawable/ic_clear_material</item>
-       <item>@drawable/ic_commit_search_api_material</item>
-       <item>@drawable/ic_dialog_alert_material</item>
-       <item>@drawable/ic_find_next_material</item>
-       <item>@drawable/ic_find_previous_material</item>
-       <item>@drawable/ic_go_search_api_material</item>
-       <item>@drawable/ic_media_route_connecting_material</item>
-       <item>@drawable/ic_media_route_material</item>
-       <item>@drawable/ic_menu_copy_material</item>
-       <item>@drawable/ic_menu_cut_material</item>
-       <item>@drawable/ic_menu_find_material</item>
-       <item>@drawable/ic_menu_moreoverflow_material</item>
-       <item>@drawable/ic_menu_paste_material</item>
-       <item>@drawable/ic_menu_search_material</item>
-       <item>@drawable/ic_menu_selectall_material</item>
-       <item>@drawable/ic_menu_share_material</item>
-       <item>@drawable/ic_search_api_material</item>
-       <item>@drawable/ic_voice_search_api_material</item>
-       <item>@drawable/item_background_borderless_material</item>
-       <item>@drawable/item_background_borderless_material_dark</item>
-       <item>@drawable/item_background_borderless_material_light</item>
-       <item>@drawable/item_background_material</item>
-       <item>@drawable/item_background_material_dark</item>
-       <item>@drawable/item_background_material_light</item>
-       <item>@drawable/list_divider_material</item>
-       <item>@drawable/list_section_divider_material</item>
-       <item>@drawable/notification_material_action_background</item>
-       <item>@drawable/notification_material_media_action_background</item>
-       <item>@drawable/popup_background_material</item>
-       <item>@drawable/progress_horizontal_material</item>
-       <item>@drawable/progress_indeterminate_horizontal_material</item>
-       <item>@drawable/progress_large_material</item>
-       <item>@drawable/progress_medium_material</item>
-       <item>@drawable/progress_small_material</item>
-       <item>@drawable/ratingbar_material</item>
-       <item>@drawable/ratingbar_small_material</item>
-       <item>@drawable/ratingbar_indicator_material</item>
-       <item>@drawable/scrollbar_handle_material</item>
-       <item>@drawable/seekbar_thumb_material_anim</item>
-       <item>@drawable/seekbar_track_material</item>
-       <item>@drawable/spinner_background_material</item>
-       <item>@drawable/spinner_textfield_background_material</item>
-       <item>@drawable/switch_thumb_material_anim</item>
-       <item>@drawable/switch_track_material</item>
-       <item>@drawable/tab_indicator_material</item>
-       <item>@drawable/text_cursor_material</item>
-       <item>@drawable/textfield_search_material</item>
-       <item>@drawable/text_select_handle_left_material</item>
-       <item>@drawable/text_select_handle_middle_material</item>
-       <item>@drawable/text_select_handle_right_material</item>
-       <item>@drawable/ic_account_circle</item>
+        <item>@drawable/ab_share_pack_material</item>
+        <item>@drawable/ab_solid_shadow_material</item>
+        <item>@drawable/action_bar_item_background_material</item>
+        <item>@drawable/activated_background_material</item>
+        <item>@drawable/btn_borderless_material</item>
+        <item>@drawable/btn_check_material_anim</item>
+        <item>@drawable/btn_colored_material</item>
+        <item>@drawable/btn_default_material</item>
+        <item>@drawable/btn_group_holo_dark</item>
+        <item>@drawable/btn_group_holo_light</item>
+        <item>@drawable/btn_radio_material_anim</item>
+        <item>@drawable/btn_star_material</item>
+        <item>@drawable/btn_toggle_material</item>
+        <item>@drawable/button_inset</item>
+        <item>@drawable/cab_background_bottom_material</item>
+        <item>@drawable/cab_background_top_material</item>
+        <item>@drawable/control_background_32dp_material</item>
+        <item>@drawable/control_background_40dp_material</item>
+        <item>@drawable/dialog_background_material</item>
+        <item>@drawable/editbox_dropdown_background_dark</item>
+        <item>@drawable/edit_text_material</item>
+        <item>@drawable/expander_group_material</item>
+        <item>@drawable/fastscroll_label_left_material</item>
+        <item>@drawable/fastscroll_label_right_material</item>
+        <item>@drawable/fastscroll_thumb_material</item>
+        <item>@drawable/fastscroll_track_material</item>
+        <item>@drawable/floating_popup_background_dark</item>
+        <item>@drawable/floating_popup_background_light</item>
+        <item>@drawable/gallery_item_background</item>
+        <item>@drawable/ic_ab_back_material</item>
+        <item>@drawable/ic_ab_back_material_dark</item>
+        <item>@drawable/ic_ab_back_material_light</item>
+        <item>@drawable/ic_account_circle</item>
+        <item>@drawable/ic_arrow_drop_right_black_24dp</item>
+        <item>@drawable/ic_clear</item>
+        <item>@drawable/ic_clear_disabled</item>
+        <item>@drawable/ic_clear_material</item>
+        <item>@drawable/ic_clear_normal</item>
+        <item>@drawable/ic_commit_search_api_material</item>
+        <item>@drawable/ic_dialog_alert_material</item>
+        <item>@drawable/ic_find_next_material</item>
+        <item>@drawable/ic_find_previous_material</item>
+        <item>@drawable/ic_go</item>
+        <item>@drawable/ic_go_search_api_material</item>
+        <item>@drawable/ic_media_route_connecting_material</item>
+        <item>@drawable/ic_media_route_material</item>
+        <item>@drawable/ic_menu_close_clear_cancel</item>
+        <item>@drawable/ic_menu_copy_material</item>
+        <item>@drawable/ic_menu_cut_material</item>
+        <item>@drawable/ic_menu_find_material</item>
+        <item>@drawable/ic_menu_more</item>
+        <item>@drawable/ic_menu_moreoverflow_material</item>
+        <item>@drawable/ic_menu_paste_material</item>
+        <item>@drawable/ic_menu_search_material</item>
+        <item>@drawable/ic_menu_selectall_material</item>
+        <item>@drawable/ic_menu_share_material</item>
+        <item>@drawable/ic_search_api_material</item>
+        <item>@drawable/ic_voice_search_api_material</item>
+        <item>@drawable/indicator_check_mark_dark</item>
+        <item>@drawable/indicator_check_mark_light</item>
+        <item>@drawable/item_background_borderless_material</item>
+        <item>@drawable/item_background_borderless_material_dark</item>
+        <item>@drawable/item_background_borderless_material_light</item>
+        <item>@drawable/item_background_material</item>
+        <item>@drawable/item_background_material_dark</item>
+        <item>@drawable/item_background_material_light</item>
+        <item>@drawable/list_choice_background_material</item>
+        <item>@drawable/list_divider_material</item>
+        <item>@drawable/list_section_divider_material</item>
+        <item>@drawable/menu_background_fill_parent_width</item>
+        <item>@drawable/notification_material_action_background</item>
+        <item>@drawable/notification_material_media_action_background</item>
+        <item>@drawable/number_picker_divider_material</item>
+        <item>@drawable/popup_background_material</item>
+        <item>@drawable/popup_inline_error_above_holo_dark</item>
+        <item>@drawable/popup_inline_error_above_holo_light</item>
+        <item>@drawable/popup_inline_error_holo_dark</item>
+        <item>@drawable/popup_inline_error_holo_light</item>
+        <item>@drawable/progress_horizontal_material</item>
+        <item>@drawable/progress_indeterminate_horizontal_material</item>
+        <item>@drawable/progress_large_material</item>
+        <item>@drawable/progress_medium_material</item>
+        <item>@drawable/progress_small_material</item>
+        <item>@drawable/quickcontact_badge_overlay_dark</item>
+        <item>@drawable/quickcontact_badge_overlay_light</item>
+        <item>@drawable/quickcontact_badge_overlay_normal_dark</item>
+        <item>@drawable/quickcontact_badge_overlay_normal_light</item>
+        <item>@drawable/quickcontact_badge_overlay_pressed_dark</item>
+        <item>@drawable/quickcontact_badge_overlay_pressed_light</item>
+        <item>@drawable/ratingbar_indicator_material</item>
+        <item>@drawable/ratingbar_material</item>
+        <item>@drawable/ratingbar_small_material</item>
+        <item>@drawable/screen_background_dark</item>
+        <item>@drawable/screen_background_dark_transparent</item>
+        <item>@drawable/screen_background_light</item>
+        <item>@drawable/screen_background_light_transparent</item>
+        <item>@drawable/screen_background_selector_dark</item>
+        <item>@drawable/screen_background_selector_light</item>
+        <item>@drawable/scrollbar_handle_material</item>
+        <item>@drawable/seekbar_thumb_material_anim</item>
+        <item>@drawable/seekbar_tick_mark_material</item>
+        <item>@drawable/seekbar_track_material</item>
+        <item>@drawable/spinner_background_material</item>
+        <item>@drawable/spinner_textfield_background_material</item>
+        <item>@drawable/switch_thumb_material_anim</item>
+        <item>@drawable/switch_track_material</item>
+        <item>@drawable/tab_indicator_material</item>
+        <item>@drawable/text_cursor_material</item>
+        <item>@drawable/text_edit_paste_window</item>
+        <item>@drawable/textfield_search_material</item>
+        <item>@drawable/text_select_handle_left_material</item>
+        <item>@drawable/text_select_handle_middle_material</item>
+        <item>@drawable/text_select_handle_right_material</item>
+        <item>@drawable/toast_frame</item>
     </array>
 
     <!-- Do not translate. These are all of the color state list resources that should be
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8e9e978..fee2469 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2726,6 +2726,8 @@
     <public type="style" name="Widget.Material.Light.CompoundButton.Switch" />
     <public type="style" name="Widget.Material.NumberPicker" />
     <public type="style" name="Widget.Material.Light.NumberPicker" />
+    <public type="style" name="TextAppearance.Material.Widget.Button.Colored" />
+    <public type="style" name="TextAppearance.Material.Widget.Button.Borderless.Colored" />
 
     <public type="id" name="accessibilityActionSetProgress" />
     <public type="id" name="icon_frame" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 45ee778..2232942 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4318,6 +4318,6 @@
     <string name="audit_safemode_notification_details">Touch to learn more.</string>
 
     <!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
-    <string name="suspended_widget_accessibility">Suspended <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
+    <string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
 
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 3ed8daa..c0060fd 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -298,6 +298,14 @@
         <item name="textColor">?attr/textColorPrimaryInverse</item>
     </style>
 
+    <style name="TextAppearance.Material.Widget.Button.Colored">
+        <item name="textColor">@color/btn_colored_text_material</item>
+    </style>
+
+    <style name="TextAppearance.Material.Widget.Button.Borderless.Colored" parent="TextAppearance.Material.Widget.Button">
+        <item name="textColor">@color/btn_colored_text_material</item>
+    </style>
+
     <style name="TextAppearance.Material.Widget.EditText">
         <item name="textColor">?attr/textColorPrimaryInverse</item>
         <item name="textColorHint">?attr/textColorHintInverse</item>
@@ -485,8 +493,7 @@
     <!-- Colored bordered ink button -->
     <style name="Widget.Material.Button.Colored">
         <item name="background">@drawable/btn_colored_material</item>
-        <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Inverse</item>
-        <item name="textColor">@color/btn_colored_text_material</item>
+        <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Colored</item>
     </style>
 
     <!-- Small bordered ink button -->
@@ -503,7 +510,7 @@
 
     <!-- Colored borderless ink button -->
     <style name="Widget.Material.Button.Borderless.Colored">
-        <item name="textColor">@color/btn_colored_borderless_text_material</item>
+        <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Borderless.Colored</item>
     </style>
 
     <!-- Alert dialog button bar button -->
diff --git a/docs/html-intl/intl/es/preview/setup-sdk.jd b/docs/html-intl/intl/es/preview/setup-sdk.jd
index 769121d..39e84a8 100644
--- a/docs/html-intl/intl/es/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/es/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 y <a href="{@docRoot}preview/api-overview.html">API y funciones de Android N
 </a>.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/in/preview/setup-sdk.jd b/docs/html-intl/intl/in/preview/setup-sdk.jd
index c6e43f1..2502d7d 100644
--- a/docs/html-intl/intl/in/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/in/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 dan <a href="{@docRoot}preview/api-overview.html">Android N API
 dan Fiturnya</a>.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/ja/preview/setup-sdk.jd b/docs/html-intl/intl/ja/preview/setup-sdk.jd
index 4331641..36c2144 100644
--- a/docs/html-intl/intl/ja/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ja/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 
 </li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/ko/preview/setup-sdk.jd b/docs/html-intl/intl/ko/preview/setup-sdk.jd
index 91f17c1..d04acef 100644
--- a/docs/html-intl/intl/ko/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ko/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 및 기능</a>에서 Android N 플랫폼에
 대해 자세히 알아봅니다.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/pt-br/preview/setup-sdk.jd b/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
index 9035e50..a917da3 100644
--- a/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/pt-br/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 e <a href="{@docRoot}preview/api-overview.html">Recursos de APIs do
 Android N</a>.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/ru/preview/setup-sdk.jd b/docs/html-intl/intl/ru/preview/setup-sdk.jd
index 582fe9f..6ae86e9 100644
--- a/docs/html-intl/intl/ru/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/ru/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 и в описании <a href="{@docRoot}preview/api-overview.html">API-интерфейсов и возможностей Android N</a>.
 </li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/vi/preview/setup-sdk.jd b/docs/html-intl/intl/vi/preview/setup-sdk.jd
index 6f6cd20..bdba713 100644
--- a/docs/html-intl/intl/vi/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/vi/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 và<a href="{@docRoot}preview/api-overview.html">API Android N
 và Các tính năng</a>.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd b/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
index eaef7a1..69971d8 100644
--- a/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/zh-cn/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1:6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 
 </li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd b/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
index 7a46aca..b486ed4 100644
--- a/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
+++ b/docs/html-intl/intl/zh-tw/preview/setup-sdk.jd
@@ -130,7 +130,7 @@
       SHA-1:6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -221,4 +221,3 @@
 
 </li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html/preview/features/security-config.jd b/docs/html/preview/features/security-config.jd
index 633c0e5..f8c0325 100644
--- a/docs/html/preview/features/security-config.jd
+++ b/docs/html/preview/features/security-config.jd
@@ -18,7 +18,7 @@
       </ol>
   </li>
   <li><a href="#TrustingDebugCa">Debugging-only CAs</a></li>
-  <li><a href="#UsesCleartextTraffic">Opting Out of Cleartext Traffic</a></li>
+  <li><a href="#CleartextTrafficPermitted">Opting Out of Cleartext Traffic</a></li>
   <li><a href="#CertificatePinning">Pinning Certificates</a></li>
   <li><a href="#ConfigInheritance">Configuration Inheritance Behavior</a></li>
   <li><a href="#FileFormat">Configuration File Format</a></li>
@@ -240,7 +240,7 @@
 </p>
 
 
-<h2 id="UsesCleartextTraffic">Opting Out of Cleartext Traffic</h2>
+<h2 id="CleartextTrafficPermitted">Opting Out of Cleartext Traffic</h2>
 
 <p>
   Applications intending to connect to destinations using only secure
@@ -263,7 +263,7 @@
 <pre>
 &lt;?xml version="1.0" encoding="utf-8"?&gt;
 &lt;network-security-config&gt;
-    &lt;domain-config usesCleartextTraffic="false"&gt;
+    &lt;domain-config cleartextTrafficPermitted="false"&gt;
         &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
     &lt;/domain-config&gt;
 &lt;/network-security-config&gt;
@@ -436,7 +436,7 @@
 
 <pre class="stx">
 &lt;base-config <a href=
-"#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
+"#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]&gt;
     ...
 &lt;/base-config&gt;
 </pre>
@@ -463,7 +463,7 @@
 </p>
 
 <pre>
-&lt;base-config usesCleartextTraffic="true"&gt;
+&lt;base-config cleartextTrafficPermitted="true"&gt;
     &lt;trust-anchors&gt;
         &lt;certificates src="system" /&gt;
     &lt;/trust-anchors&gt;
@@ -471,7 +471,7 @@
 </pre>
 The default configuration for apps targeting API level 23 and below is:
 <pre>
-&lt;base-config usesCleartextTraffic="true"&gt;
+&lt;base-config cleartextTrafficPermitted="true"&gt;
     &lt;trust-anchors&gt;
         &lt;certificates src="system" /&gt;
         &lt;certificates src="user" /&gt;
@@ -486,7 +486,7 @@
 <dl class="xml">
 <dt>syntax:</dt>
 <dd>
-<pre class="stx">&lt;domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
+<pre class="stx">&lt;domain-config <a href="#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]&gt;
     ...
 &lt;/domain-config&gt;</pre>
 </dd>
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index ebeae74..3b479e2 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -98,7 +98,7 @@
       SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7 
     </td>
   </tr>
-<table>
+</table>
 
 
 
@@ -189,4 +189,3 @@
 and <a href="{@docRoot}preview/api-overview.html">Android N APIs
 and Features</a>.</li>
 </ul>
-<div class="end-content-title"></div>
diff --git a/docs/html/topic/instant-apps/faqs.jd b/docs/html/topic/instant-apps/faqs.jd
index 0a1f571..bf37241 100644
--- a/docs/html/topic/instant-apps/faqs.jd
+++ b/docs/html/topic/instant-apps/faqs.jd
@@ -63,7 +63,9 @@
   <strong>How can developers get involved?</strong>
   <br/>
   Developers interested in upgrading their Android apps can visit
-  <a class="external-link" href="g.co/InstantApps">g.co/InstantApps</a> to
+  <a class="external-link"
+  href="http://g.co/InstantApps">
+  g.co/InstantApps</a> to
   sign up. We will be reaching out to interested
   developers in the coming months.
 </p>
\ No newline at end of file
diff --git a/docs/html/topic/instant-apps/index.jd b/docs/html/topic/instant-apps/index.jd
index d8de0b5..e2da9c5 100644
--- a/docs/html/topic/instant-apps/index.jd
+++ b/docs/html/topic/instant-apps/index.jd
@@ -12,17 +12,8 @@
 <!-- Hero section -->
 <section class="dac-expand dac-hero dac-section-light">
 <div class="wrap">
-  <div class="cols dac-hero-content">
-
-    <div class="col-1of2 col-push-1of2 dac-hero-figure">
-      <div class="dev-bytes-video">
-        <iframe width="560" height="350" src=
-        "https://www.youtube.com/embed/cosqlfqrpFA" frameborder="0"
-        allowfullscreen=""></iframe>
-      </div>
-    </div>
-
-    <div class="col-1of2 col-pull-1of2" style="margin-bottom:40px">
+  <div class="dac-hero-content">
+    <div style="margin-bottom:40px">
       <h1>
         Android Instant Apps
       </h1>
@@ -47,6 +38,11 @@
         <a class="landing-button green download-bundle-button" href=
         "https://docs.google.com/a/google.com/forms/d/1S3MzsMVIlchLCqyNLaFbv64llxWaf90QSeYLeswco90/viewform"
         target="_blank">I'M INTERESTED IN ANDROID INSTANT APPS<br></a>
+        <a class="dac-hero-cta dev-bytes"
+          href="https://www.youtube.com/watch?v=cosqlfqrpFA">
+          <span class="dac-sprite dac-auto-chevron"></span>
+          Watch a video about Instant Apps
+        </a>
       </p>
     </div>
 
@@ -56,7 +52,7 @@
 
 <!-- Second section -->
 
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
 <div class="cols dac-hero-content">
   <div class="col-1of2 dac-hero-figure">
     <img src="/images/topic/instant-apps/instant-apps-section-2.png">
@@ -64,7 +60,7 @@
 <div class="col-1of2">
 <div class="dac-hero-tag"></div>
 
-  <h2 id="section-2">Run Android Apps Without Installation</h2>
+  <h2 id="section-2" class="norule">Run Android Apps Without Installation</h2>
   <p class="dac-hero-description">
     Android Instant Apps lets you experience beautiful and immersive
     apps, with material design and smooth animations, without installing them
@@ -77,9 +73,9 @@
 
 <!-- Third section -->
 
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
 
-  <h2 id="section-3">Access Apps From Anywhere</h2>
+  <h2 id="section-3" class="norule">Access Apps From Anywhere</h2>
 
   <p>
     Get people to your flagship Android experience from links that would
@@ -126,7 +122,7 @@
 
 <!-- Fourth section -->
 
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
 <div class="cols dac-hero-content">
   <div class="col-1of2 dac-hero-figure">
     <img src="/images/topic/instant-apps/instant-apps-section-4.png">
@@ -134,9 +130,10 @@
 <div class="col-1of2">
 <div class="dac-hero-tag"></div>
 
-  <h2 id="section-4">Built On Google Play Services</h2>
+  <h2 id="section-4" class="norule">Built On Google Play Services</h2>
   <p class="dac-hero-description">
-    Take advantage of Google Play services features &mdash; like location, identity,
+    Take advantage of Google Play services features &mdash; like location,
+    identity,
     payments, and Firebase &mdash; which are built right in for a seamless user
     experience.
   </p>
@@ -147,17 +144,16 @@
 
 <!-- Fifth section -->
 
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
 <div class="cols dac-hero-content">
   <div class="col-1of2 col-push-1of2 dac-hero-figure">
     <img src="/images/topic/instant-apps/instant-apps-section-5.png">
   </div>
 <div class="col-1of2 col-pull-1of2">
 <div class="dac-hero-tag"></div>
-  <h2 id="section-5">Works On Most Android Devices</h2>
+  <h2 id="section-5" class="norule">Works On Most Android Devices</h2>
 
   <p class="dac-hero-description">
-
     Android Instant Apps can work on Android devices running Android 4.1+
     (API Level 16) or higher with Google Play services.
   </p>
@@ -168,7 +164,7 @@
 
 <!-- Sixth section -->
 
-<div class="wrap" style="margin-top:60px">
+<div class="wrap sub-section">
 <div class="cols dac-hero-content">
   <div class="col-1of2 dac-hero-figure">
     <img src="/images/topic/instant-apps/upgrade-your-app-2x.png">
@@ -176,7 +172,7 @@
 <div class="col-1of2">
 <div class="dac-hero-tag"></div>
 
-  <h2 id="section-6">Upgrade Your Existing App</h2>
+  <h2 id="section-6" class="norule">Upgrade Your Existing App</h2>
   <p class="dac-hero-description">
     Android Instant Apps functionality is an upgrade to your existing Android
     app, not a new, separate app. It's the same Android APIs, the same
@@ -192,18 +188,18 @@
 
 <!-- Seventh section -->
 
-<div class="wrap" style="margin-top:60px" id="section-7">
-  <h2 id="sign-up-docs" style="margin-bottom: 0px;">
+<div class="wrap sub-section" id="section-7">
+  <h2 id="sign-up-docs" class="dac-section-title norule" style="margin-bottom: 0px;">
     Sign up for access to Android Instant Apps documentation
   </h2>
 
-  <p>
+  <p class="dac-section-subtitle" style="margin-top:0px">
     We’ll let you know if you’re selected for early access
     to Android Instant
     Apps.
   </p>
 
-  <p>
+  <p class="dac-section-subtitle">
     <a class="landing-button green download-bundle-button"
       href="https://docs.google.com/forms/d/1S3MzsMVIlchLCqyNLaFbv64llxWaf90QSeYLeswco90/viewform"
       target="_blank">
@@ -211,7 +207,7 @@
     </a>
   </p>
 
-  <p style="margin-top:24px">
+  <p  class="dac-section-subtitle" style="margin-top:24px">
     Check out our <a href="faqs.html">frequently asked questions</a> to find out
     more about Android Instant Apps.
   </p>
@@ -230,28 +226,14 @@
     background: #B0BEC5;
   }
 
-  /* Styling and layout for video. */
-  .dev-bytes-video {
-    margin-top: 30px;
-    position: relative;
-    padding-bottom: 56.25%; /* 16:9 */
-    padding-top: 30px;
-    height: 0;
-  }
-
-  .dev-bytes-video iframe,
-  .dev-bytes-video object,
-  .dev-bytes-video embed {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-  }
-
   /* Increase top margin for sections */
-  .wrap {
-    margin-top: 1.5em;
+  .sub-section {
+    margin-top: 2em;
+  }
+
+  a.dev-bytes {
+   padding-top: 1em;
+   padding-left: 1em;
   }
 
   #section-3, #sign-up-docs {
@@ -259,11 +241,6 @@
     border-top: 0px;
   }
 
-  /* Align the seventh section in the center. */
-  #section-7 {
-    text-align: center;
-  }
-
   /* GIF section styling */
   .figure-caption {
     text-align: center;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index c67b008..1864206 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -104,6 +104,9 @@
     private Rect mHotspotBounds;
     private boolean mMutated;
 
+    private boolean mSuspendChildInvalidation;
+    private boolean mChildRequestedInvalidation;
+
     /**
      * Creates a new layer drawable with the list of specified layers.
      *
@@ -944,9 +947,37 @@
       return mLayerState.mPaddingMode;
     }
 
+    /**
+     * Temporarily suspends child invalidation.
+     *
+     * @see #resumeChildInvalidation()
+     */
+    private void suspendChildInvalidation() {
+        mSuspendChildInvalidation = true;
+    }
+
+    /**
+     * Resumes child invalidation after suspension, immediately performing an
+     * invalidation if one was requested by a child during suspension.
+     *
+     * @see #suspendChildInvalidation()
+     */
+    private void resumeChildInvalidation() {
+        mSuspendChildInvalidation = false;
+
+        if (mChildRequestedInvalidation) {
+            mChildRequestedInvalidation = false;
+            invalidateSelf();
+        }
+    }
+
     @Override
     public void invalidateDrawable(@NonNull Drawable who) {
-        invalidateSelf();
+        if (mSuspendChildInvalidation) {
+            mChildRequestedInvalidation = true;
+        } else {
+            invalidateSelf();
+        }
     }
 
     @Override
@@ -1482,6 +1513,15 @@
     }
 
     private void updateLayerBounds(Rect bounds) {
+        try {
+            suspendChildInvalidation();
+            updateLayerBoundsInternal(bounds);
+        } finally {
+            resumeChildInvalidation();
+        }
+    }
+
+    private void updateLayerBoundsInternal(Rect bounds) {
         int paddingL = 0;
         int paddingT = 0;
         int paddingR = 0;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 746e99a..cb8e55f 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -878,11 +878,49 @@
 
     restoreForLayer();
 
+    // saveLayer will clip & translate the draw contents, so we need
+    // to translate the drawLayer by how much the contents was translated
+    // TODO: Unify this with beginLayerOp so we don't have to calculate this
+    // twice
+    uint32_t layerWidth = (uint32_t) beginLayerOp.unmappedBounds.getWidth();
+    uint32_t layerHeight = (uint32_t) beginLayerOp.unmappedBounds.getHeight();
+
+    auto previous = mCanvasState.currentSnapshot();
+    Vector3 lightCenter = previous->getRelativeLightCenter();
+
+    // Combine all transforms used to present saveLayer content:
+    // parent content transform * canvas transform * bounds offset
+    Matrix4 contentTransform(*(previous->transform));
+    contentTransform.multiply(beginLayerOp.localMatrix);
+    contentTransform.translate(beginLayerOp.unmappedBounds.left,
+            beginLayerOp.unmappedBounds.top);
+
+    Matrix4 inverseContentTransform;
+    inverseContentTransform.loadInverse(contentTransform);
+
+    // map the light center into layer-relative space
+    inverseContentTransform.mapPoint3d(lightCenter);
+
+    // Clip bounds of temporary layer to parent's clip rect, so:
+    Rect saveLayerBounds(layerWidth, layerHeight);
+    //     1) transform Rect(width, height) into parent's space
+    //        note: left/top offsets put in contentTransform above
+    contentTransform.mapRect(saveLayerBounds);
+    //     2) intersect with parent's clip
+    saveLayerBounds.doIntersect(previous->getRenderTargetClip());
+    //     3) and transform back
+    inverseContentTransform.mapRect(saveLayerBounds);
+    saveLayerBounds.doIntersect(Rect(layerWidth, layerHeight));
+    saveLayerBounds.roundOut();
+
+    Matrix4 localMatrix(beginLayerOp.localMatrix);
+    localMatrix.translate(saveLayerBounds.left, saveLayerBounds.top);
+
     // record the draw operation into the previous layer's list of draw commands
     // uses state from the associated beginLayerOp, since it has all the state needed for drawing
     LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
             beginLayerOp.unmappedBounds,
-            beginLayerOp.localMatrix,
+            localMatrix,
             beginLayerOp.localClip,
             beginLayerOp.paint,
             &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index cab93e8..ec9ffde 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -45,5 +45,9 @@
     }
 }
 
+const char* OpDumper::opName(const RecordedOp& op) {
+    return sOpNameLut[op.opId];
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/hwui/OpDumper.h b/libs/hwui/OpDumper.h
index c99b517..a82289c 100644
--- a/libs/hwui/OpDumper.h
+++ b/libs/hwui/OpDumper.h
@@ -26,6 +26,7 @@
 class OpDumper {
 public:
     static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
+    static const char* opName(const RecordedOp& op);
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 0f16b15..af1fbd8 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -2025,6 +2025,7 @@
     uint32_t layerHeight = 0;
     Rect rectClippedBounds;
     Matrix4 rectMatrix;
+    Matrix4 drawLayerMatrix;
 };
 /**
  * Constructs a view to hit the temporary layer alpha property implementation:
@@ -2060,6 +2061,7 @@
         }
         void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
             EXPECT_EQ(3, mIndex++);
+            mOutData->drawLayerMatrix = state.computedState.transform;
         }
         void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
             EXPECT_EQ(4, mIndex++);
@@ -2108,6 +2110,9 @@
     expected.loadTranslate(0, -2000, 0);
     EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
             << "expect content to be translated as part of being clipped";
+    expected.loadTranslate(10, 0, 0);
+    EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
+                << "expect drawLayer to be translated as part of being clipped";
 }
 
 RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
index e718742..423c3b0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
@@ -38,6 +38,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.media.ImageReader;
+import android.graphics.SurfaceTexture;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -67,6 +68,7 @@
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedPreviewSizes;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedStillSizes;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSortedSizesForFormat;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.makeImageReader;
 
 /**
@@ -122,6 +124,8 @@
     protected List<Size> mOrderedPreviewSizes; // In descending order.
     protected List<Size> mOrderedVideoSizes; // In descending order.
     protected List<Size> mOrderedStillSizes; // In descending order.
+    protected List<Size> mOrderedRAW10Sizes; // In descending order.
+    protected List<Size> mOrderedYUV420888Sizes; // In descending order.
     protected HashMap<Size, Long> mMinPreviewFrameDurationMap;
 
     protected WindowManager mWindowManager;
@@ -589,6 +593,7 @@
         mReaderSurface = null;
     }
 
+
     /**
      * Open a camera device and get the StaticMetadata for a given camera id.
      *
@@ -603,8 +608,13 @@
         if (mStaticInfo.isColorOutputSupported()) {
             mOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager,
                     getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
-            mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+            mOrderedVideoSizes = getSupportedVideoSizes(
+                    cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
             mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
+            mOrderedRAW10Sizes = getSortedSizesForFormat(
+                    cameraId, mCameraManager, ImageFormat.RAW10, null);
+            mOrderedYUV420888Sizes = getSortedSizesForFormat(
+                    cameraId, mCameraManager, ImageFormat.YUV_420_888, null);
             // Use ImageFormat.YUV_420_888 for now. TODO: need figure out what's format for preview
             // in public API side.
             mMinPreviewFrameDurationMap =
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
new file mode 100644
index 0000000..11327ca
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.stress;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+import com.android.mediaframeworktest.Camera2SurfaceViewTestCase;
+import com.android.mediaframeworktest.helpers.Camera2Focuser;
+import com.android.mediaframeworktest.helpers.CameraTestUtils;
+import com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleCaptureCallback;
+
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.DngCreator;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.CamcorderProfile;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaRecorder;
+import android.os.ConditionVariable;
+import android.os.Environment;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Rational;
+import android.util.Size;
+import android.view.Surface;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.util.Range;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.MAX_READER_IMAGES;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleImageReaderListener;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.basicValidateJpegImage;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.configureCameraSession;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.dumpFile;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getDataFromImage;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getValueNotNull;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.makeImageReader;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.SESSION_CLOSED;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_1080P;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_2160P;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.mediaframeworktest.Camera2SurfaceViewTestCase;
+import com.android.mediaframeworktest.helpers.CameraTestUtils;
+
+import junit.framework.AssertionFailedError;
+
+/**
+ * <p>Tests Back/Front camera switching and Camera/Video modes witching.</p>
+ *
+ * adb shell am instrument \
+ *    -e class com.android.mediaframeworktest.stress.Camera2SwitchPreviewTest \
+ *    -e iterations 200 \
+ *    -e waitIntervalMs 1000 \
+ *    -e resultToFile false \
+ *    -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
+ */
+public class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase {
+    private static final String TAG = "SwitchPreviewTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    // 60 second to accommodate the possible long exposure time.
+    private static final int MAX_REGIONS_AE_INDEX = 0;
+    private static final int MAX_REGIONS_AWB_INDEX = 1;
+    private static final int MAX_REGIONS_AF_INDEX = 2;
+    private static final int WAIT_FOR_FOCUS_DONE_TIMEOUT_MS = 6000;
+    private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2;
+    // 5 percent error margin for resulting metering regions
+    private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f;
+    private final String VIDEO_FILE_PATH = Environment.getExternalStorageDirectory().getPath();
+
+    private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int RECORDING_DURATION_MS = 3000;
+    private static final float DURATION_MARGIN = 0.2f;
+    private static final double FRAME_DURATION_ERROR_TOLERANCE_MS = 3.0;
+    private static final int BIT_RATE_1080P = 16000000;
+    private static final int BIT_RATE_MIN = 64000;
+    private static final int BIT_RATE_MAX = 40000000;
+    private static final int VIDEO_FRAME_RATE = 30;
+    private static final int[] mCamcorderProfileList = {
+            CamcorderProfile.QUALITY_HIGH,
+            CamcorderProfile.QUALITY_2160P,
+            CamcorderProfile.QUALITY_1080P,
+            CamcorderProfile.QUALITY_720P,
+            CamcorderProfile.QUALITY_480P,
+            CamcorderProfile.QUALITY_CIF,
+            CamcorderProfile.QUALITY_QCIF,
+            CamcorderProfile.QUALITY_QVGA,
+            CamcorderProfile.QUALITY_LOW,
+    };
+    private static final int MAX_VIDEO_SNAPSHOT_IMAGES = 5;
+    private static final int BURST_VIDEO_SNAPSHOT_NUM = 3;
+    private static final int SLOWMO_SLOW_FACTOR = 4;
+    private static final int MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED = 4;
+    private List<Size> mSupportedVideoSizes;
+    private Surface mRecordingSurface;
+    private Surface mPersistentSurface;
+    private MediaRecorder mMediaRecorder;
+    private String mOutMediaFileName;
+    private int mVideoFrameRate;
+    private Size mVideoSize;
+    private long mRecordingStartTime;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test normal still preview switch.
+     * <p>
+     * Preview jpeg output streams are configured. Max still capture
+     * size is used for jpeg capture.
+     * </p>
+     */
+    public void testPreviewSwitchBackFrontCamera() throws Exception {
+        List<String> mCameraColorOutputIds = cameraColorOutputCheck();
+        // Test iteration starts...
+        Log.i(TAG, "Testing preview switch back/front camera in still capture mode");
+        for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+            for (String id : mCameraColorOutputIds) {
+                try {
+                    openDevice(id);
+                    // Preview for basic still capture:
+                    Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+                            getIterationCount()));
+                    stillCapturePreviewPreparer(id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+                } finally {
+                    closeDevice();
+                    closeImageReader();
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Test basic video preview switch.
+     * </p>
+     * <p>
+     * This test covers the typical basic use case of video preview switch.
+     * MediaRecorder is used to record the audio and video, CamcorderProfile is
+     * used to configure the MediaRecorder. Preview is set to the video size.
+     * </p>
+     */
+    public void testPreviewSwitchBackFrontVideo() throws Exception {
+        List<String> mCameraColorOutputIds = cameraColorOutputCheck();
+        // Test iteration starts...
+        Log.i(TAG, "Testing preview switch back/front camera in video mode");
+        for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+            for (String id : mCameraColorOutputIds) {
+                try {
+                    openDevice(id);
+                    // Preview for basic video recording:
+                    Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+                            getIterationCount()));
+                    recordingPreviewPreparer(id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+                } finally {
+                    closeDevice();
+                    releaseRecorder();
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Test back camera preview switch between still capture and recording mode.
+     * <p>
+     * This test covers the basic case of preview switch camera mode, between
+     * still capture (photo) and recording (video) mode. The preview settings
+     * are same with the settings in "testPreviewSwitchBackFrontCamera" and
+     * "testPreviewSwitchBackFrontVideo"
+     * </p>
+     */
+    public void testPreviewSwitchBackCameraVideo() throws Exception {
+        String id = mCameraIds[0];
+        openDevice(id);
+        if (!mStaticInfo.isColorOutputSupported()) {
+            Log.i(TAG, "Camera " + id +
+                    " does not support color outputs, skipping");
+            return;
+        }
+        closeDevice();
+        // Test iteration starts...
+        Log.i(TAG, "Testing preview switch between still capture/video modes for back camera");
+        for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+            try {
+                openDevice(id);
+
+                // Preview for basic still capture:
+                Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+                        getIterationCount()));
+                stillCapturePreviewPreparer(id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+
+                // Preview for basic video recording:
+                Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+                        getIterationCount()));
+                recordingPreviewPreparer(id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test front camera preview switch between still capture and recording mode.
+     * <p>
+     * This test covers the basic case of preview switch camera mode, between
+     * still capture (photo) and recording (video) mode. The preview settings
+     * are same with the settings in "testPreviewSwitchBackFrontCamera" and
+     * "testPreviewSwitchBackFrontVideo"
+     * </p>
+     */
+    public void testPreviewSwitchFrontCameraVideo() throws Exception{
+        String id = mCameraIds[1];
+        openDevice(id);
+        if (!mStaticInfo.isColorOutputSupported()) {
+            Log.i(TAG, "Camera " + id +
+                    " does not support color outputs, skipping");
+            return;
+        }
+        closeDevice();
+        // Test iteration starts...
+        Log.i(TAG, "Testing preview switch between still capture/video modes for front camera");
+        for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+            try {
+                openDevice(id);
+
+                // Preview for basic still capture:
+                Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1,
+                        getIterationCount()));
+                stillCapturePreviewPreparer(id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+
+                // Preview for basic video recording:
+                Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1,
+                        getIterationCount()));
+                recordingPreviewPreparer(id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    private void stillCapturePreviewPreparer(String id) throws Exception{
+        CaptureResult result;
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder stillRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        // Preview Setup:
+        prepareCapturePreview(previewRequest, stillRequest, resultListener, imageListener);
+
+        Thread.sleep(getTestWaitIntervalMs());
+    }
+
+    private void recordingPreviewPreparer(String id) throws Exception{
+        // Re-use the MediaRecorder object for the same camera device.
+        mMediaRecorder = new MediaRecorder();
+        initSupportedVideoSize(id);
+        // preview Setup:
+        basicRecordingPreviewTestByCamera(mCamcorderProfileList);
+
+        Thread.sleep(getTestWaitIntervalMs());
+    }
+
+
+    /**
+     * Initialize the supported video sizes.
+     */
+    private void initSupportedVideoSize(String cameraId)  throws Exception {
+        Size maxVideoSize = SIZE_BOUND_1080P;
+        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
+            maxVideoSize = SIZE_BOUND_2160P;
+        }
+        mSupportedVideoSizes =
+                getSupportedVideoSizes(cameraId, mCameraManager, maxVideoSize);
+    }
+
+
+    /**
+     * Test camera recording preview by using each available CamcorderProfile for a
+     * given camera. preview size is set to the video size.
+     */
+    private void basicRecordingPreviewTestByCamera(int[] camcorderProfileList)
+            throws Exception {
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        List<Range<Integer> > fpsRanges = Arrays.asList(
+                mStaticInfo.getAeAvailableTargetFpsRangesChecked());
+        int cameraId = Integer.parseInt(mCamera.getId());
+        int maxVideoFrameRate = -1;
+        int profileId = camcorderProfileList[0];
+        if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
+                allowedUnsupported(cameraId, profileId)) {
+            return;
+        }
+
+        CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+        Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+        Range<Integer> fpsRange = new Range(profile.videoFrameRate, profile.videoFrameRate);
+        if (maxVideoFrameRate < profile.videoFrameRate) {
+                maxVideoFrameRate = profile.videoFrameRate;
+        }
+        if (mStaticInfo.isHardwareLevelLegacy() &&
+                (videoSz.getWidth() > maxPreviewSize.getWidth() ||
+                        videoSz.getHeight() > maxPreviewSize.getHeight())) {
+            // Skip. Legacy mode can only do recording up to max preview size
+            return;
+        }
+        assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId +
+                            " must be one of the camera device supported video size!",
+                    mSupportedVideoSizes.contains(videoSz));
+        assertTrue("Frame rate range " + fpsRange + " (for profile ID " + profileId +
+                            ") must be one of the camera device available FPS range!",
+                fpsRanges.contains(fpsRange));
+
+        if (VERBOSE) {
+            Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
+        }
+
+        // Configure preview and recording surfaces.
+        mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
+        if (DEBUG_DUMP) {
+            mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_"
+                    + videoSz.toString() + ".mp4";
+        }
+
+        prepareRecordingWithProfile(profile);
+
+        // prepare preview surface by using video size.
+        updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
+
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder recordingRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+
+        prepareVideoPreview(previewRequest, recordingRequest, resultListener, imageListener);
+
+        // Can reuse the MediaRecorder object after reset.
+        mMediaRecorder.reset();
+
+        if (maxVideoFrameRate != -1) {
+            // At least one CamcorderProfile is present, check FPS
+            assertTrue("At least one CamcorderProfile must support >= 24 FPS",
+                    maxVideoFrameRate >= 24);
+        }
+    }
+
+    private void releaseRecorder() {
+        if (mMediaRecorder != null) {
+            mMediaRecorder.release();
+            mMediaRecorder = null;
+        }
+    }
+
+    private List<String> cameraColorOutputCheck() throws Exception {
+        List<String> mCameraColorOutputIds = new ArrayList<String>();
+        for (String id : mCameraIds) {
+            openDevice(id);
+            if (!mStaticInfo.isColorOutputSupported()) {
+                Log.i(TAG, "Camera " + id +
+                        " does not support color outputs, skipping");
+                continue;
+            }
+            mCameraColorOutputIds.add(id);
+            closeDevice();
+        }
+        return mCameraColorOutputIds;
+    }
+
+    /**
+     * Returns {@code true} if the {@link CamcorderProfile} ID is allowed to be unsupported.
+     *
+     * <p>This only allows unsupported profiles when using the LEGACY mode of the Camera API.</p>
+     *
+     * @param profileId a {@link CamcorderProfile} ID to check.
+     * @return {@code true} if supported.
+     */
+    private boolean allowedUnsupported(int cameraId, int profileId) {
+        if (!mStaticInfo.isHardwareLevelLegacy()) {
+            return false;
+        }
+
+        switch(profileId) {
+            case CamcorderProfile.QUALITY_2160P:
+            case CamcorderProfile.QUALITY_1080P:
+            case CamcorderProfile.QUALITY_HIGH:
+                return !CamcorderProfile.hasProfile(cameraId, profileId) ||
+                        CamcorderProfile.get(cameraId, profileId).videoFrameWidth >= 1080;
+        }
+        return false;
+    }
+
+    /**
+     * Configure MediaRecorder recording session with CamcorderProfile, prepare
+     * the recording surface.
+     */
+    private void prepareRecordingWithProfile(CamcorderProfile profile)
+            throws Exception {
+        // Prepare MediaRecorder.
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+        mMediaRecorder.setProfile(profile);
+        mMediaRecorder.setOutputFile(mOutMediaFileName);
+        if (mPersistentSurface != null) {
+            mMediaRecorder.setInputSurface(mPersistentSurface);
+            mRecordingSurface = mPersistentSurface;
+        }
+        mMediaRecorder.prepare();
+        if (mPersistentSurface == null) {
+            mRecordingSurface = mMediaRecorder.getSurface();
+        }
+        assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        mVideoFrameRate = profile.videoFrameRate;
+        mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+    }
+
+    /**
+     * Update preview size with video size.
+     *
+     * <p>Preview size will be capped with max preview size.</p>
+     *
+     * @param videoSize The video size used for preview.
+     * @param videoFrameRate The video frame rate
+     *
+     */
+    private void updatePreviewSurfaceWithVideo(Size videoSize, int videoFrameRate)  throws Exception {
+        if (mOrderedPreviewSizes == null) {
+            throw new IllegalStateException("supported preview size list is not initialized yet");
+        }
+        final float FRAME_DURATION_TOLERANCE = 0.01f;
+        long videoFrameDuration = (long) (1e9 / videoFrameRate *
+                (1.0 + FRAME_DURATION_TOLERANCE));
+        HashMap<Size, Long> minFrameDurationMap = mStaticInfo.
+                getAvailableMinFrameDurationsForFormatChecked(ImageFormat.PRIVATE);
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        Size previewSize = null;
+        if (videoSize.getWidth() > maxPreviewSize.getWidth() ||
+                videoSize.getHeight() > maxPreviewSize.getHeight()) {
+            for (Size s : mOrderedPreviewSizes) {
+                Long frameDuration = minFrameDurationMap.get(s);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    // Legacy doesn't report min frame duration
+                    frameDuration = new Long(0);
+                }
+                assertTrue("Cannot find minimum frame duration for private size" + s,
+                        frameDuration != null);
+                if (frameDuration <= videoFrameDuration &&
+                        s.getWidth() <= videoSize.getWidth() &&
+                        s.getHeight() <= videoSize.getHeight()) {
+                    Log.w(TAG, "Overwrite preview size from " + videoSize.toString() +
+                            " to " + s.toString());
+                    previewSize = s;
+                    break;
+                    // If all preview size doesn't work then we fallback to video size
+                }
+            }
+        }
+        if (previewSize == null) {
+            previewSize = videoSize;
+        }
+
+        updatePreviewSurface(previewSize);
+    }
+
+    protected void prepareVideoPreview(CaptureRequest.Builder previewRequest,
+                                                 CaptureRequest.Builder recordingRequest,
+                                                 CaptureCallback resultListener,
+                                                 ImageReader.OnImageAvailableListener imageListener) throws Exception {
+
+        // Configure output streams with preview and jpeg streams.
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(mPreviewSurface);
+        outputSurfaces.add(mRecordingSurface);
+
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        previewRequest.addTarget(mPreviewSurface);
+        recordingRequest.addTarget(mPreviewSurface);
+        recordingRequest.addTarget(mRecordingSurface);
+
+        // Start preview.
+        mSession.setRepeatingRequest(previewRequest.build(), null, mHandler);
+    }
+
+    protected void prepareCapturePreview(CaptureRequest.Builder previewRequest,
+                                                 CaptureRequest.Builder stillRequest,
+                                                 CaptureCallback resultListener,
+                                                 ImageReader.OnImageAvailableListener imageListener) throws Exception {
+
+        Size captureSz = mOrderedStillSizes.get(0);
+        Size previewSz = mOrderedPreviewSizes.get(1);
+
+        if (VERBOSE) {
+            Log.v(TAG, String.format("Prepare single capture (%s) and preview (%s)",
+                    captureSz.toString(), previewSz.toString()));
+        }
+
+        // Update preview size.
+        updatePreviewSurface(previewSz);
+
+        // Create ImageReader.
+        createImageReader(captureSz, ImageFormat.JPEG, MAX_READER_IMAGES, imageListener);
+
+        // Configure output streams with preview and jpeg streams.
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(mPreviewSurface);
+        outputSurfaces.add(mReaderSurface);
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        // Configure the requests.
+        previewRequest.addTarget(mPreviewSurface);
+        stillRequest.addTarget(mPreviewSurface);
+        stillRequest.addTarget(mReaderSurface);
+
+        // Start preview.
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+    }
+
+}
diff --git a/packages/PrintRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml
index 68effbf..86027cd 100644
--- a/packages/PrintRecommendationService/res/values/donottranslate.xml
+++ b/packages/PrintRecommendationService/res/values/donottranslate.xml
@@ -32,8 +32,15 @@
         <item>Hewlett Packard</item>
     </string-array>
 
+    <string-array name="known_print_vendor_info_for_samsung" translatable="false">
+        <item>com.sec.app.samsungprintservice</item>
+        <item>Samsung Electronics</item>
+        <item>Samsung</item>
+    </string-array>
+
     <array name="known_print_plugin_vendors" translatable="false">
         <item>@array/known_print_vendor_info_for_mopria</item>
         <item>@array/known_print_vendor_info_for_hp</item>
+        <item>@array/known_print_vendor_info_for_samsung</item>
     </array>
 </resources>
diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
index 97281de..348fcac 100644
--- a/packages/PrintRecommendationService/res/values/strings.xml
+++ b/packages/PrintRecommendationService/res/values/strings.xml
@@ -23,7 +23,7 @@
     <string name="plugin_vendor_brother">Brother</string>
     <string name="plugin_vendor_canon">Canon</string>
     <string name="plugin_vendor_xerox">Xerox</string>
-    <string name="plugin_vendor_samsung">Samsung Electronics</string>
+    <string name="plugin_vendor_samsung">Samsung</string>
     <string name="plugin_vendor_epson">Epson</string>
     <string name="plugin_vendor_konica_minolta">Konica Minolta</string>
     <string name="plugin_vendor_fuji">Fuji</string>
diff --git a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
index b7925df..108ea66 100644
--- a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
@@ -51,14 +51,6 @@
     </vendor>
 
     <vendor>
-        <name>@string/plugin_vendor_samsung</name>
-        <package>com.sec.app.samsungprintservice</package>
-        <mdns-names>
-            <mdns-name>Samsung</mdns-name>
-        </mdns-names>
-    </vendor>
-
-    <vendor>
         <name>@string/plugin_vendor_epson</name>
         <package>com.epson.mobilephone.android.epsonprintserviceplugin</package>
         <mdns-names>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index 4b4b470..d95654f 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -25,6 +25,7 @@
 import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin;
 import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig;
 import com.android.printservice.recommendation.plugin.mopria.MopriaRecommendationPlugin;
+import com.android.printservice.recommendation.plugin.samsung.SamsungRecommendationPlugin;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
@@ -74,6 +75,14 @@
                     " plugin", e);
         }
 
+        try {
+            mPlugins.add(new RemotePrintServicePlugin(new SamsungRecommendationPlugin(this), this,
+                    false));
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Could not initiate " + getString(R.string.plugin_vendor_samsung) +
+                    " plugin", e);
+        }
+
         final int numPlugins = mPlugins.size();
         for (int i = 0; i < numPlugins; i++) {
             try {
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
new file mode 100644
index 0000000..963e09b
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.Map;
+
+public class MDnsUtils {
+    public static final String ATTRIBUTE__TY = "ty";
+    public static final String ATTRIBUTE__PRODUCT = "product";
+    public static final String ATTRIBUTE__USB_MFG = "usb_MFG";
+    public static final String ATTRIBUTE__MFG = "mfg";
+
+    public static String getString(byte[] value) {
+        if (value != null) return new String(value,StandardCharsets.UTF_8);
+        return null;
+    }
+
+    public static boolean isVendorPrinter(NsdServiceInfo networkDevice, String[] vendorValues) {
+
+        Map<String,byte[]> attributes = networkDevice.getAttributes();
+        String product = getString(attributes.get(ATTRIBUTE__PRODUCT));
+        String ty = getString(attributes.get(ATTRIBUTE__TY));
+        String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG));
+        String mfg = getString(attributes.get(ATTRIBUTE__MFG));
+        return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues);
+
+    }
+
+    public static String getVendor(NsdServiceInfo networkDevice) {
+        String vendor;
+
+        Map<String,byte[]> attributes = networkDevice.getAttributes();
+        vendor = getString(attributes.get(ATTRIBUTE__MFG));
+        if (!TextUtils.isEmpty(vendor)) return vendor;
+        vendor = getString(attributes.get(ATTRIBUTE__USB_MFG));
+        if (!TextUtils.isEmpty(vendor)) return vendor;
+
+        return null;
+    }
+
+    private static boolean containsVendor(String container, String[] vendorValues) {
+        if ((container == null) || (vendorValues == null)) return false;
+        for (String value : vendorValues) {
+            if (containsString(container, value)
+                || containsString(container.toLowerCase(Locale.US), value.toLowerCase(Locale.US))
+                || containsString(container.toUpperCase(Locale.US), value.toUpperCase(Locale.US)))
+                return true;
+        }
+        return false;
+    }
+
+    private static boolean containsString(String container, String contained) {
+        return (container != null) && (contained != null) && (container.equalsIgnoreCase(contained) || container.contains(contained + " "));
+    }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
new file mode 100644
index 0000000..032fe22
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+
+import java.util.HashMap;
+
+final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
+    public static String getKey(NsdServiceInfo serviceInfo) {
+        return serviceInfo.getServiceName();
+    }
+    public NsdServiceInfo addPrinter(NsdServiceInfo device) {
+        return put(getKey(device), device);
+    }
+    public NsdServiceInfo removePrinter(NsdServiceInfo device) {
+        return remove(getKey(device));
+    }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
new file mode 100644
index 0000000..e5b8a0f
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
@@ -0,0 +1,102 @@
+/*

+(c) Copyright 2016 Samsung Electronics..

+

+Licensed under the Apache License, Version 2.0 (the "License");

+you may not use this file except in compliance with the License.

+You may obtain a copy of the License at

+

+http://www.apache.org/licenses/LICENSE-2.0

+

+Unless required by applicable law or agreed to in writing, software

+distributed under the License is distributed on an "AS IS" BASIS,

+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+See the License for the specific language governing permissions and

+limitations under the License.

+*/

+

+

+package com.android.printservice.recommendation.plugin.samsung;

+

+import android.content.Context;

+import android.net.nsd.NsdServiceInfo;

+import android.text.TextUtils;

+

+import java.util.Locale;

+import java.util.Map;

+

+import com.android.printservice.recommendation.R;

+

+public class SamsungRecommendationPlugin extends ServiceRecommendationPlugin {

+

+    private static final String TAG = "SamsungRecommendation";

+

+    private static final String ATTR_USB_MFG = "usb_MFG";

+    private static final String ATTR_MFG = "mfg";

+    private static final String ATTR_USB_MDL = "usb_MDL";

+    private static final String ATTR_MDL = "mdl";

+    private static final String ATTR_PRODUCT = "product";

+    private static final String ATTR_TY = "ty";

+

+    private static String[] mNotSupportedDevices = new String[]{

+            "SCX-5x15",

+            "SF-555P",

+            "CF-555P",

+            "SCX-4x16",

+            "SCX-4214F",

+            "CLP-500",

+            "CJX-",

+            "MJC-"

+    };

+

+    private static boolean isSupportedModel(String model) {

+        if (!TextUtils.isEmpty(model)) {

+            String modelToUpper = model.toUpperCase(Locale.US);

+            for (String unSupportedPrinter : mNotSupportedDevices) {

+                if (modelToUpper.contains(unSupportedPrinter)) {

+                    return  false;

+                }

+            }

+        }

+        return true;

+    }

+

+    public SamsungRecommendationPlugin(Context context) {

+        super(context, R.string.plugin_vendor_samsung, new VendorInfo(context.getResources(), R.array.known_print_vendor_info_for_samsung), new String[]{"_pdl-datastream._tcp"});

+    }

+

+    @Override

+    public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {

+        if (!TextUtils.equals(vendor, mVendorInfo.mVendorID)) return false;

+

+        String modelName = getModelName(nsdServiceInfo);

+        if (modelName != null) {

+            return (isSupportedModel(modelName));

+        }

+        return false;

+    }

+

+    private String getModelName(NsdServiceInfo resolvedDevice) {

+        Map<String,byte[]> attributes = resolvedDevice.getAttributes();

+        String usb_mfg = MDnsUtils.getString(attributes.get(ATTR_USB_MFG));

+        if (TextUtils.isEmpty(usb_mfg)) {

+            usb_mfg = MDnsUtils.getString(attributes.get(ATTR_MFG));

+        }

+

+        String usb_mdl = MDnsUtils.getString(attributes.get(ATTR_USB_MDL));

+        if (TextUtils.isEmpty(usb_mdl)) {

+            usb_mdl = MDnsUtils.getString(attributes.get(ATTR_MDL));

+        }

+

+        String modelName = null;

+        if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {

+            modelName = usb_mfg.trim() + " " + usb_mdl.trim();

+        } else {

+            modelName = MDnsUtils.getString(attributes.get(ATTR_PRODUCT));

+            if (TextUtils.isEmpty(modelName)) {

+                modelName = MDnsUtils.getString(attributes.get(ATTR_TY));

+            }

+        }

+

+        return modelName;

+    }

+}

diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
new file mode 100644
index 0000000..7bb83c9
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
+
+public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
+
+    private final NsdManager mNSDManager;
+    private final Map<String, VendorInfo> mVendorInfoHashMap;
+    private final String[] mServiceType;
+    private final Observer mObserver;
+    private final ServiceResolveQueue mResolveQueue;
+    private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();
+    public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();
+
+    public interface Observer {
+        boolean matchesCriteria(String vendor, NsdServiceInfo serviceInfo);
+        void dataSetChanged();
+    }
+
+    public ServiceListener(Context context, Observer observer, String[] serviceTypes) {
+        mObserver = observer;
+        mServiceType = serviceTypes;
+        mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
+        mResolveQueue = ServiceResolveQueue.getInstance(mNSDManager);
+
+        Map<String, VendorInfo> vendorInfoMap = new HashMap<>();
+        TypedArray testArray = context.getResources().obtainTypedArray(R.array.known_print_plugin_vendors);
+        for(int i = 0; i < testArray.length(); i++) {
+            int arrayID = testArray.getResourceId(i, 0);
+            if (arrayID != 0) {
+                VendorInfo info = new VendorInfo(context.getResources(), arrayID);
+                vendorInfoMap.put(info.mVendorID, info);
+                vendorInfoMap.put(info.mPackageName, info);
+            }
+        }
+        testArray.recycle();
+        mVendorInfoHashMap = vendorInfoMap;
+    }
+
+    @Override
+    public void serviceResolved(NsdServiceInfo nsdServiceInfo) {
+        printerFound(nsdServiceInfo);
+    }
+
+    private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
+        if (nsdServiceInfo == null) return;
+        if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
+        String vendor = MDnsUtils.getVendor(nsdServiceInfo);
+        if (vendor == null) vendor = "";
+        for(Map.Entry<String,VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
+            for(String vendorValues : entry.getValue().mDNSValues) {
+                if (vendor.equalsIgnoreCase(vendorValues)) {
+                    vendor = entry.getValue().mVendorID;
+                    break;
+                }
+            }
+            // intentional pointer check
+            //noinspection StringEquality
+            if ((vendor != entry.getValue().mVendorID) &&
+                    MDnsUtils.isVendorPrinter(nsdServiceInfo, entry.getValue().mDNSValues)) {
+                vendor = entry.getValue().mVendorID;
+            }
+            // intentional pointer check
+            //noinspection StringEquality
+            if (vendor == entry.getValue().mVendorID) break;
+        }
+
+        if (TextUtils.isEmpty(vendor)) {
+            return;
+        }
+
+        if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
+            return;
+        boolean mapsChanged;
+
+        PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
+        if (vendorHash == null) {
+            vendorHash = new PrinterHashMap();
+        }
+        mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
+        mVendorHashMap.put(vendor, vendorHash);
+
+        if (mapsChanged) {
+            mObserver.dataSetChanged();
+        }
+    }
+
+    private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
+        boolean wasRemoved = false;
+        Set<String> vendors = mVendorHashMap.keySet();
+        for(String vendor : vendors) {
+            PrinterHashMap map = mVendorHashMap.get(vendor);
+            wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
+            if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
+        }
+        if (wasRemoved) {
+            mObserver.dataSetChanged();
+        }
+    }
+
+    public void start() {
+        stop();
+        for(final String service :mServiceType) {
+            NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
+                @Override
+                public void onStartDiscoveryFailed(String s, int i) {
+
+                }
+
+                @Override
+                public void onStopDiscoveryFailed(String s, int i) {
+
+                }
+
+                @Override
+                public void onDiscoveryStarted(String s) {
+
+                }
+
+                @Override
+                public void onDiscoveryStopped(String s) {
+
+                }
+
+                @Override
+                public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
+                    mResolveQueue.queueRequest(nsdServiceInfo, ServiceListener.this);
+                }
+
+                @Override
+                public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
+                    mResolveQueue.removeRequest(nsdServiceInfo, ServiceListener.this);
+                    printerRemoved(nsdServiceInfo);
+                }
+            };
+            DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener);
+            mListeners.add(listener);
+        }
+    }
+
+    public void stop() {
+        for(NsdManager.DiscoveryListener listener : mListeners) {
+            DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
+        }
+        mVendorHashMap.clear();
+        mListeners.clear();
+    }
+
+    public Pair<Integer, Integer> getCount() {
+        int count = 0;
+        for (PrinterHashMap map : mVendorHashMap.values()) {
+            count += map.size();
+        }
+        return Pair.create(mVendorHashMap.size(), count);
+    }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
new file mode 100644
index 0000000..9d15f30
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.text.TextUtils;
+import com.android.printservice.recommendation.PrintServicePlugin;
+
+public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, ServiceListener.Observer {
+
+    protected static final String PDL_ATTRIBUTE = "pdl";
+
+    protected final Object mLock = new Object();
+    protected PrinterDiscoveryCallback mCallback = null;
+    protected final ServiceListener mListener;
+    protected final NsdManager mNSDManager;
+    protected final VendorInfo mVendorInfo;
+    private final int mVendorStringID;
+
+    protected ServiceRecommendationPlugin(Context context, int vendorStringID, VendorInfo vendorInfo, String[] services) {
+        mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
+        mVendorStringID = vendorStringID;
+        mVendorInfo = vendorInfo;
+        mListener = new ServiceListener(context, this, services);
+    }
+
+    @Override
+    public int getName() {
+        return mVendorStringID;
+    }
+
+    @NonNull
+    @Override
+    public CharSequence getPackageName() {
+        return mVendorInfo.mPackageName;
+    }
+
+    @Override
+    public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+        synchronized (mLock) {
+            mCallback = callback;
+        }
+        mListener.start();
+    }
+
+    @Override
+    public void stop() throws Exception {
+        synchronized (mLock) {
+            mCallback = null;
+        }
+        mListener.stop();
+    }
+
+    @Override
+    public void dataSetChanged() {
+        synchronized (mLock) {
+            if (mCallback != null) mCallback.onChanged(getCount());
+        }
+    }
+
+    @Override
+    public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
+        return TextUtils.equals(vendor, mVendorInfo.mVendorID);
+    }
+
+    public int getCount() {
+        return mListener.getCount().second;
+    }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
new file mode 100644
index 0000000..e5691b7
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Pair;
+import com.android.printservice.recommendation.util.NsdResolveQueue;
+
+import java.util.LinkedList;
+
+final class ServiceResolveQueue {
+
+    private final NsdManager mNsdManager;
+    private final LinkedList<Pair<NsdServiceInfo, ResolveCallback>> mQueue = new LinkedList<>();
+    private final Object mLock = new Object();
+
+    private static Object sLock = new Object();
+    private static ServiceResolveQueue sInstance = null;
+    private final NsdResolveQueue mNsdResolveQueue;
+    private Pair<NsdServiceInfo, ResolveCallback> mCurrentRequest = null;
+
+    public static void createInstance(NsdManager nsdManager) {
+        if (sInstance == null) sInstance = new ServiceResolveQueue(nsdManager);
+    }
+
+    public static ServiceResolveQueue getInstance(NsdManager nsdManager) {
+        synchronized (sLock) {
+            createInstance(nsdManager);
+            return sInstance;
+        }
+    }
+
+    public static void destroyInstance() {
+        sInstance = null;
+    }
+
+    public interface ResolveCallback {
+        void serviceResolved(NsdServiceInfo nsdServiceInfo);
+    }
+
+    public ServiceResolveQueue(NsdManager nsdManager) {
+        mNsdManager = nsdManager;
+        mNsdResolveQueue = NsdResolveQueue.getInstance();
+    }
+
+    public void queueRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
+        synchronized (mLock) {
+            Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
+            if (mQueue.contains(newRequest)) return;
+            mQueue.add(newRequest);
+            makeNextRequest();
+        }
+    }
+
+    public void removeRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
+        synchronized (mLock) {
+            Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
+            mQueue.remove(newRequest);
+            if ((mCurrentRequest != null) && newRequest.equals(mCurrentRequest)) mCurrentRequest = null;
+        }
+    }
+
+    private void makeNextRequest() {
+        synchronized (mLock) {
+            if (mCurrentRequest != null) return;
+            if (mQueue.isEmpty()) return;
+            mCurrentRequest = mQueue.removeFirst();
+            mNsdResolveQueue.resolve(mNsdManager, mCurrentRequest.first,
+                    new NsdManager.ResolveListener() {
+                        @Override
+                        public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
+                            synchronized (mLock) {
+                                if (mCurrentRequest != null) mQueue.add(mCurrentRequest);
+                                makeNextRequest();
+                            }
+                        }
+
+                        @Override
+                        public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
+                            synchronized (mLock) {
+                                if (mCurrentRequest != null) {
+                                    mCurrentRequest.second.serviceResolved(nsdServiceInfo);
+                                    mCurrentRequest = null;
+                                }
+                                makeNextRequest();
+                            }
+                        }
+                    });
+
+        }
+    }
+
+
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
new file mode 100644
index 0000000..0ebb4e4
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.content.res.Resources;
+
+import java.util.Arrays;
+
+public final class VendorInfo {
+
+    public final String mPackageName;
+    public final String mVendorID;
+    public final String[] mDNSValues;
+    public final int mID;
+
+    public VendorInfo(Resources resources, int vendor_info_id) {
+        mID = vendor_info_id;
+        String[] data = resources.getStringArray(vendor_info_id);
+        if ((data == null) || (data.length < 2)) {
+            data = new String[] { null, null };
+        }
+        mPackageName = data[0];
+        mVendorID = data[1];
+        mDNSValues = (data.length > 2) ? Arrays.copyOfRange(data, 2, data.length) : new String[]{};
+    }
+}
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index 6438564..ca0248e 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -35,6 +35,7 @@
         android:importantForAccessibility="no" />
 
     <View
+        android:id="@+id/nav_bar_background"
         android:layout_width="match_parent"
         android:layout_height="@dimen/navigation_bar_size"
         android:layout_gravity="bottom"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 61933b4..4bf85c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -19,6 +19,7 @@
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.support.v7.widget.DefaultItemAnimator;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
@@ -103,6 +104,17 @@
         mRecyclerView.setItemAnimator(animator);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        View navBackdrop = findViewById(R.id.nav_bar_background);
+        if (navBackdrop != null) {
+            boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
+                    || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
+            navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+        }
+    }
+
     public void setHost(QSTileHost host) {
         mHost = host;
         mPhoneStatusBar = host.getPhoneStatusBar();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 61a92b4..60c24d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -286,10 +286,11 @@
     private void selectPosition(int position, View v) {
         // Remove the placeholder.
         mAccessibilityMoving = false;
-        move(mAccessibilityFromIndex, position, v);
-        mTiles.remove(mEditIndex);
+        mTiles.remove(mEditIndex--);
         notifyItemRemoved(mEditIndex - 1);
+        move(mAccessibilityFromIndex, position, v);
         updateDividerLocations();
+        notifyDataSetChanged();
         saveSpecs(mHost);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 212f179..16b1158 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -81,6 +81,8 @@
     private IQSService mService;
     private boolean mUnbindImmediate;
     private TileChangeListener mChangeListener;
+    // Return value from bindServiceAsUser, determines whether safe to call unbind.
+    private boolean mIsBound;
 
     public TileLifecycleManager(Handler handler, Context context, Intent intent, UserHandle user) {
         mContext = context;
@@ -132,7 +134,7 @@
             }
             if (DEBUG) Log.d(TAG, "Binding service " + mIntent + " " + mUser);
             mBindTryCount++;
-            mContext.bindServiceAsUser(mIntent, this,
+            mIsBound = mContext.bindServiceAsUser(mIntent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     mUser);
         } else {
@@ -140,7 +142,10 @@
             // Give it another chance next time it needs to be bound, out of kindness.
             mBindTryCount = 0;
             mWrapper = null;
-            mContext.unbindService(this);
+            if (mIsBound) {
+                mContext.unbindService(this);
+                mIsBound = false;
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 32b61cd..f3c666f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -263,6 +263,7 @@
         invalidateOutline();
         selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
         mForceSelectNextLayout = false;
+        updateExpandButtons(mExpandable);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 4e643f0..7d3da1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -463,9 +463,7 @@
         mTransformedView.animate().cancel();
         mTransformedView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         mTransformedView.setAlpha(visible ? 1.0f : 0.0f);
-        if (visible) {
-            resetTransformedView();
-        }
+        resetTransformedView();
     }
 
     public void prepareFadeIn() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6a37099..522f250 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -220,6 +220,20 @@
         super.onFinishInflate();
         mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
         mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
+        mClockView = (TextView) findViewById(R.id.clock_view);
+
+        mNotificationContainerParent = (NotificationsQuickSettingsContainer)
+                findViewById(R.id.notification_container_parent);
+        mNotificationStackScroller = (NotificationStackScrollLayout)
+                findViewById(R.id.notification_stack_scroller);
+        mNotificationStackScroller.setOnHeightChangedListener(this);
+        mNotificationStackScroller.setOverscrollTopChangedListener(this);
+        mNotificationStackScroller.setOnEmptySpaceClickListener(this);
+        mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
+        mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
+        mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
+        mLastOrientation = getResources().getConfiguration().orientation;
+
         mQsAutoReinflateContainer =
                 (AutoReinflateContainer) findViewById(R.id.qs_auto_reinflate_container);
         mQsAutoReinflateContainer.addInflateListener(new InflateListener() {
@@ -229,32 +243,20 @@
                 mQsContainer.setPanelView(NotificationPanelView.this);
                 mQsContainer.getHeader().findViewById(R.id.expand_indicator)
                         .setOnClickListener(NotificationPanelView.this);
-            }
-        });
-        mClockView = (TextView) findViewById(R.id.clock_view);
-        mNotificationContainerParent = (NotificationsQuickSettingsContainer)
-                findViewById(R.id.notification_container_parent);
-        mNotificationStackScroller = (NotificationStackScrollLayout)
-                findViewById(R.id.notification_stack_scroller);
-        mNotificationStackScroller.setOnHeightChangedListener(this);
-        mNotificationStackScroller.setOverscrollTopChangedListener(this);
-        mNotificationStackScroller.setOnEmptySpaceClickListener(this);
-        mNotificationStackScroller.setQsContainer(mQsContainer);
-        mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
-        mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
-        mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
-        mLastOrientation = getResources().getConfiguration().orientation;
 
-        // recompute internal state when qspanel height changes
-        mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                final int height = bottom - top;
-                final int oldHeight = oldBottom - oldTop;
-                if (height != oldHeight) {
-                    onQsHeightChanged();
-                }
+                // recompute internal state when qspanel height changes
+                mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+                    @Override
+                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                        final int height = bottom - top;
+                        final int oldHeight = oldBottom - oldTop;
+                        if (height != oldHeight) {
+                            onQsHeightChanged();
+                        }
+                    }
+                });
+                mNotificationStackScroller.setQsContainer(mQsContainer);
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4c242cc..19f4074 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2511,9 +2511,9 @@
             mNeedsAnimation = false;
         }
         if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
+            setAnimationRunning(true);
             mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
                     mGoToFullShadeDelay);
-            setAnimationRunning(true);
             mAnimationEvents.clear();
             updateBackground();
             updateViewShadows();
@@ -3131,6 +3131,7 @@
             mListener.onChildLocationsChanged(this);
         }
         runAnimationFinishedRunnables();
+        setAnimationRunning(false);
         updateBackground();
         updateViewShadows();
     }
@@ -3247,6 +3248,7 @@
             maxLength = Math.max(mDarkAnimationOriginIndex,
                     getNotGoneChildCount() - mDarkAnimationOriginIndex - 1);
         }
+        maxLength = Math.max(0, maxLength);
         long delay = maxLength * StackStateAnimator.ANIMATION_DELAY_PER_ELEMENT_DARK;
         fadeAnimator.setStartDelay(delay);
         fadeAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 3cc991c..ecba245 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -648,7 +648,16 @@
      * @param policyFlags The policy flags associated with the event.
      */
     private void handleMotionEventStateDragging(MotionEvent event, int policyFlags) {
-        final int pointerIdBits = (1 << mDraggingPointerId);
+        int pointerIdBits = 0;
+        // Clear the dragging pointer id if it's no longer valid.
+        if (event.findPointerIndex(mDraggingPointerId) == -1) {
+            Slog.e(LOG_TAG, "mDraggingPointerId doesn't match any pointers on current event. " +
+                    "mDraggingPointerId: " + Integer.toString(mDraggingPointerId) +
+                    ", Event: " + event);
+            mDraggingPointerId = INVALID_POINTER_ID;
+        } else {
+            pointerIdBits = (1 << mDraggingPointerId);
+        }
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 throw new IllegalStateException("Dragging state can be reached only if two "
@@ -664,6 +673,9 @@
                 sendDownForAllNotInjectedPointers(event, policyFlags);
             } break;
             case MotionEvent.ACTION_MOVE: {
+                if (mDraggingPointerId == INVALID_POINTER_ID) {
+                    break;
+                }
                 switch (event.getPointerCount()) {
                     case 1: {
                         // do nothing
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index dab7d70..b5b0cd8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -2180,8 +2180,9 @@
         Preconditions.checkNotNull(token);
         for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
             String restriction = AppOpsManager.opToRestriction(i);
-            if (restriction != null && restrictions.getBoolean(restriction, false)) {
-                setUserRestrictionNoCheck(i, true, token, userHandle, null);
+            if (restriction != null) {
+                setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token,
+                        userHandle, null);
             }
         }
     }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f30a126..1f88be5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1457,14 +1457,17 @@
                                                     BluetoothAdapter.STATE_OFF);
                         sendBluetoothServiceDownCallback();
 
-                        mBluetoothLock.writeLock().lock();
-                        if (mBluetooth != null) {
-                            mBluetooth = null;
-                            // Unbind
-                            mContext.unbindService(mConnection);
+                        try {
+                            mBluetoothLock.writeLock().lock();
+                            if (mBluetooth != null) {
+                                mBluetooth = null;
+                                // Unbind
+                                mContext.unbindService(mConnection);
+                            }
+                            mBluetoothGatt = null;
+                        } finally {
+                            mBluetoothLock.writeLock().unlock();
                         }
-                        mBluetoothGatt = null;
-                        mBluetoothLock.writeLock().unlock();
 
                         SystemClock.sleep(100);
 
@@ -1765,14 +1768,17 @@
 
         sendBluetoothServiceDownCallback();
 
-        mBluetoothLock.writeLock().lock();
-        if (mBluetooth != null) {
-            mBluetooth = null;
-            // Unbind
-            mContext.unbindService(mConnection);
+        try {
+            mBluetoothLock.writeLock().lock();
+            if (mBluetooth != null) {
+                mBluetooth = null;
+                // Unbind
+                mContext.unbindService(mConnection);
+            }
+            mBluetoothGatt = null;
+        } finally {
+            mBluetoothLock.writeLock().unlock();
         }
-        mBluetoothGatt = null;
-        mBluetoothLock.writeLock().unlock();
 
         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
         mState = BluetoothAdapter.STATE_OFF;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 95a9781..5118b3f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2245,6 +2245,11 @@
             final boolean wasDefault = isDefaultNetwork(nai);
             if (wasDefault) {
                 mDefaultInetConditionPublished = 0;
+                // Log default network disconnection before required book-keeping.
+                // Let rematchAllNetworksAndRequests() below record a new default network event
+                // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
+                // whose timestamps tell how long it takes to recover a default network.
+                logDefaultNetworkEvent(null, nai);
             }
             notifyIfacesChangedForNetworkStats();
             // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -2278,10 +2283,6 @@
             }
             mLegacyTypeTracker.remove(nai, wasDefault);
             rematchAllNetworksAndRequests(null, 0);
-            if (wasDefault && getDefaultNetwork() == null) {
-                // Log that we lost the default network and there is no replacement.
-                logDefaultNetworkEvent(null, nai);
-            }
             if (nai.created) {
                 // Tell netd to clean up the configuration for this network
                 // (routing rules, DNS, etc).
@@ -3227,9 +3228,6 @@
     @Override
     public LegacyVpnInfo getLegacyVpnInfo(int userId) {
         enforceCrossUserPermission(userId);
-        if (mLockdownEnabled) {
-            return null;
-        }
 
         synchronized(mVpns) {
             return mVpns.get(userId).getLegacyVpnInfo();
@@ -4584,7 +4582,7 @@
         teardownUnneededNetwork(oldNetwork);
     }
 
-    private void makeDefault(NetworkAgentInfo newNetwork, NetworkAgentInfo prevNetwork) {
+    private void makeDefault(NetworkAgentInfo newNetwork) {
         if (DBG) log("Switching to new default network: " + newNetwork);
         setupDataActivityTracking(newNetwork);
         try {
@@ -4596,7 +4594,6 @@
         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
         updateTcpBufferSizes(newNetwork);
         setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
-        logDefaultNetworkEvent(newNetwork, prevNetwork);
     }
 
     // Handles a network appearing or improving its score.
@@ -4747,7 +4744,9 @@
         }
         if (isNewDefault) {
             // Notify system services that this network is up.
-            makeDefault(newNetwork, oldDefaultNetwork);
+            makeDefault(newNetwork);
+            // Log 0 -> X and Y -> X default network transitions, where X is the new default.
+            logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
             synchronized (ConnectivityService.this) {
                 // have a new default network, release the transition wakelock in
                 // a second if it's held.  The second pause is to allow apps
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 4477e8b..1d8bb6b 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -43,6 +43,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IProgressListener;
 import android.os.Parcel;
@@ -111,13 +112,12 @@
     private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
     private static final boolean DEBUG = false;
 
-    private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
-    private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
     private static final int PROFILE_KEY_IV_SIZE = 12;
     private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
     private final Object mSeparateChallengeLock = new Object();
 
     private final Context mContext;
+    private final Handler mHandler;
     private final LockSettingsStorage mStorage;
     private final LockSettingsStrongAuth mStrongAuth;
     private final SynchronizedStrongAuthTracker mStrongAuthTracker;
@@ -244,6 +244,7 @@
 
     public LockSettingsService(Context context) {
         mContext = context;
+        mHandler = new Handler();
         mStrongAuth = new LockSettingsStrongAuth(context);
         // Open the database
 
@@ -367,10 +368,20 @@
         hideEncryptionNotification(new UserHandle(userId));
     }
 
-    public void onUnlockUser(int userId) {
+    public void onUnlockUser(final int userId) {
         // Hide notification first, as tie managed profile lock takes time
         hideEncryptionNotification(new UserHandle(userId));
-        tieManagedProfileLockIfNecessary(userId, null);
+
+        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+            // As tieManagedProfileLockIfNecessary() may try to unlock user, we should not do it
+            // in onUnlockUser() synchronously, otherwise it may cause a deadlock
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    tieManagedProfileLockIfNecessary(userId, null);
+                }
+            });
+        }
 
         // Now we have unlocked the parent user we should show notifications
         // about any profiles that exist.
@@ -687,7 +698,7 @@
         java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
         keyStore.load(null);
         SecretKey decryptionKey = (SecretKey) keyStore.getKey(
-                PROFILE_KEY_NAME_DECRYPT + userId, null);
+                LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
 
         Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
@@ -734,12 +745,6 @@
             }
         };
 
-        // Turn off quite mode if it's enabled, only managed profile can return true for now, it
-        // will return false if it is not a managed profile.
-        if (mUserManager.isQuietModeEnabled(new UserHandle(userId))) {
-            mUserManager.setQuietModeEnabled(userId, false);
-        }
-
         try {
             ActivityManagerNative.getDefault().unlockUser(userId, token, secret, listener);
         } catch (RemoteException e) {
@@ -758,7 +763,6 @@
                     // Unlock managed profile with unified lock
                     if (pi.isManagedProfile()
                             && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
-                            && !pi.isQuietModeEnabled()
                             && mStorage.hasChildProfileLock(pi.id)) {
                         unlockChildProfile(pi.id);
                     }
@@ -976,14 +980,14 @@
             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
             keyStore.load(null);
             keyStore.setEntry(
-                    PROFILE_KEY_NAME_ENCRYPT + userId,
+                    LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
                     new java.security.KeyStore.SecretKeyEntry(secretKey),
                     new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
                             .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                             .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                             .build());
             keyStore.setEntry(
-                    PROFILE_KEY_NAME_DECRYPT + userId,
+                    LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
                     new java.security.KeyStore.SecretKeyEntry(secretKey),
                     new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
                             .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
@@ -994,7 +998,7 @@
 
             // Key imported, obtain a reference to it.
             SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
-                    PROFILE_KEY_NAME_ENCRYPT + userId, null);
+                    LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
             // The original key can now be discarded.
 
             Cipher cipher = Cipher.getInstance(
@@ -1393,8 +1397,8 @@
         try {
             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
             keyStore.load(null);
-            keyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
-            keyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+            keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
+            keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
         } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
                 | IOException e) {
             // We have tried our best to remove all keys
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2017e48..a8a8553 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -201,6 +201,7 @@
 import android.service.voice.VoiceInteractionSession;
 import android.text.format.DateUtils;
 import android.text.format.Time;
+import android.text.style.SuggestionSpan;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -17397,15 +17398,24 @@
                     || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                     || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
                     || LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
-                    || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)) {
+                    || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
+                    || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)) {
                 // Broadcast is either protected, or it's a public action that
                 // we've relaxed, so it's fine for system internals to send.
             } else {
                 // The vast majority of broadcasts sent from system internals
                 // should be protected to avoid security holes, so yell loudly
                 // to ensure we examine these cases.
-                Log.wtf(TAG, "Sending non-protected broadcast " + action
-                        + " from system", new Throwable());
+                if (callerApp != null) {
+                    Log.wtf(TAG, "Sending non-protected broadcast " + action
+                            + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
+                            new Throwable());
+                } else {
+                    Log.wtf(TAG, "Sending non-protected broadcast " + action
+                            + " from system uid " + UserHandle.formatUid(callingUid)
+                            + " pkg " + callerPackage,
+                            new Throwable());
+                }
             }
 
         } else {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 595d086..67f96d8 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -938,6 +938,17 @@
     boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
             IProgressListener listener) {
         synchronized (mService) {
+            // TODO Move this block outside of synchronized if it causes lock contention
+            if (!StorageManager.isUserKeyUnlocked(userId)) {
+                final UserInfo userInfo = getUserInfo(userId);
+                final IMountService mountService = getMountService();
+                try {
+                    // We always want to unlock user storage, even user is not started yet
+                    mountService.unlockUserKey(userId, userInfo.serialNumber, token, secret);
+                } catch (RemoteException | RuntimeException e) {
+                    Slog.w(TAG, "Failed to unlock: " + e.getMessage());
+                }
+            }
             // Bail if user isn't actually running, otherwise register the given
             // listener to watch for unlock progress
             final UserState uss = mStartedUsers.get(userId);
@@ -948,19 +959,6 @@
                 uss.mUnlockProgress.addListener(listener);
             }
 
-            // TODO Move this block outside of synchronized if it causes lock contention
-            if (!StorageManager.isUserKeyUnlocked(userId)) {
-                final UserInfo userInfo = getUserInfo(userId);
-                final IMountService mountService = getMountService();
-                try {
-                    mountService.unlockUserKey(userId, userInfo.serialNumber, token, secret);
-                } catch (RemoteException | RuntimeException e) {
-                    Slog.w(TAG, "Failed to unlock: " + e.getMessage());
-                    notifyFinished(userId, listener);
-                    return false;
-                }
-            }
-
             finishUserUnlocking(uss);
 
             // We just unlocked a user, so let's now attempt to unlock any
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 230c2e9..ea36170 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -190,11 +190,9 @@
 
     private void handleUpdateStats(StatsContext statsContext) {
         if (mDataUsageRequests.size() == 0) {
-            if (LOGV) Slog.v(TAG, "No registered listeners of data usage");
             return;
         }
 
-        if (LOGV) Slog.v(TAG, "Checking if any registered observer needs to be notified");
         for (int i = 0; i < mDataUsageRequests.size(); i++) {
             RequestInfo requestInfo = mDataUsageRequests.valueAt(i);
             requestInfo.updateStats(statsContext);
@@ -371,9 +369,6 @@
             NetworkStats stats = mCollection.getSummary(template,
                     Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
                     mAccessLevel, mCallingUid);
-            if (LOGV) {
-                Slog.v(TAG, "Netstats for " + template + ": " + stats);
-            }
             return stats.getTotalBytes();
         }
     }
@@ -391,11 +386,6 @@
 
             for (int i = 0; i < uidsToMonitor.length; i++) {
                 long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
-
-                if (LOGV) {
-                    Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
-                            + mRequest.template + " for uid=" + uidsToMonitor[i]);
-                }
                 if (bytesSoFar > mRequest.thresholdInBytes) {
                     return true;
                 }
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 15a63ec..e3dcf14 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -36,6 +36,7 @@
 import com.android.server.notification.NotificationManagerService.DumpFilter;
 
 import java.io.PrintWriter;
+import java.util.Calendar;
 import java.util.TimeZone;
 
 /**
@@ -237,6 +238,14 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (DEBUG) Slog.d(TAG, "onReceive " + intent.getAction());
+            if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+                for (Uri conditionId : mSubscriptions.keySet()) {
+                    final ScheduleCalendar cal = mSubscriptions.get(conditionId);
+                    if (cal != null) {
+                        cal.setTimeZone(Calendar.getInstance().getTimeZone());
+                    }
+                }
+            }
             evaluateSubscriptions();
         }
     };
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2f72607..5fdb1e8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5421,7 +5421,7 @@
         // If the service process is killed, then ask it to clean up after itself
         final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
                 SYSUI_SCREENSHOT_ERROR_RECEIVER);
-        Intent errorIntent = new Intent();
+        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
         errorIntent.setComponent(errorComponent);
         errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
                 Intent.FLAG_RECEIVER_FOREGROUND);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b773a4e..f57e83aa 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -451,6 +451,16 @@
         destroySurfaces();
     }
 
+    void markSavedSurfaceExiting() {
+        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+            final WindowState w = allAppWindows.get(i);
+            if (w.isAnimatingInvisibleWithSavedSurface()) {
+                w.mAnimatingExit = true;
+                w.mWinAnimator.mAnimating = true;
+            }
+        }
+    }
+
     void restoreSavedSurfaces() {
         if (!canRestoreSurfaces()) {
             clearVisibleBeforeClientHidden();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aaed8ca..d496510 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2277,6 +2277,19 @@
         }
     }
 
+    private void setupWindowForRemoveOnExit(WindowState win) {
+        win.mRemoveOnExit = true;
+        win.setDisplayLayoutNeeded();
+        // Request a focus update as this window's input channel is already gone. Otherwise
+        // we could have no focused window in input manager.
+        final boolean focusChanged = updateFocusedWindowLocked(
+                UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+        mWindowPlacerLocked.performSurfacePlacement();
+        if (focusChanged) {
+            mInputMonitor.updateInputWindowsLw(false /*force*/);
+        }
+    }
+
     public void removeWindow(Session session, IWindow client) {
         synchronized(mWindowMap) {
             WindowState win = windowForClientLocked(session, client, false);
@@ -2358,14 +2371,7 @@
                 // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
                 // immediately after the enter animation is done. If the app is not yet drawn then
                 // it will show up as a flicker.
-                win.mRemoveOnExit = true;
-                // Request a focus update as this window's input channel is already gone. Otherwise
-                // we could have no focused window in input manager.
-                final boolean focusChanged = updateFocusedWindowLocked(
-                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
-                if (focusChanged) {
-                    mInputMonitor.updateInputWindowsLw(false /*force*/);
-                }
+                setupWindowForRemoveOnExit(win);
                 Binder.restoreCallingIdentity(origId);
                 return;
             }
@@ -2417,17 +2423,10 @@
                 // The exit animation is running or should run... wait for it!
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                         "Not removing " + win + " due to exit animation ");
-                win.mRemoveOnExit = true;
-                win.setDisplayLayoutNeeded();
-                final boolean focusChanged = updateFocusedWindowLocked(
-                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
-                mWindowPlacerLocked.performSurfacePlacement();
+                setupWindowForRemoveOnExit(win);
                 if (appToken != null) {
                     appToken.updateReportedVisibilityLocked();
                 }
-                if (focusChanged) {
-                    mInputMonitor.updateInputWindowsLw(false /*force*/);
-                }
                 Binder.restoreCallingIdentity(origId);
                 return;
             }
@@ -6387,6 +6386,11 @@
             if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
                     "Taking screenshot while rotating");
 
+            // We force pending transactions to flush before taking
+            // the screenshot by pushing an empty synchronous transaction.
+            SurfaceControl.openTransaction();
+            SurfaceControl.closeTransactionSync();
+
             bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                     inRotation, rot);
             if (bm == null) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c15afb3..be27c82 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2111,7 +2111,9 @@
     void clearHasSavedSurface() {
         mSurfaceSaved = false;
         mAnimatingWithSavedSurface = false;
-        mWasVisibleBeforeClientHidden = false;
+        if (mWasVisibleBeforeClientHidden) {
+            mAppToken.destroySavedSurfaces();
+        }
     }
 
     boolean clearAnimatingWithSavedSurface() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 308b24d..4148cd0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1301,6 +1301,14 @@
         appsCount = mService.mClosingApps.size();
         for (int i = 0; i < appsCount; i++) {
             AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
+
+            // If we still have some windows animating with saved surfaces that's
+            // either invisible or already removed, mark them exiting so that they
+            // are disposed of after the exit animation. These are not supposed to
+            // be shown, or are delayed removal until app is actually drawn (in which
+            // case the window will be removed after the animation).
+            wtoken.markSavedSurfaceExiting();
+
             final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
             appAnimator.clearThumbnail();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c1913de..1af9ccb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3810,14 +3810,13 @@
             // If caller has PO (or DO) it can change the password, so see if that's the case first.
             ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
                     null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
+            final boolean preN = getTargetSdk(admin.info.getPackageName(),
+                    userHandle) <= android.os.Build.VERSION_CODES.M;
             if (admin == null) {
                 // Otherwise, make sure the caller has any active admin with the right policy.
                 admin = getActiveAdminForCallerLocked(null,
                         DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
 
-                final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
-                        <= android.os.Build.VERSION_CODES.M;
-
                 // As of N, password resetting to empty/null is not allowed anymore.
                 // TODO Should we allow DO/PO to set an empty password?
                 if (TextUtils.isEmpty(password)) {
@@ -3838,6 +3837,30 @@
                     }
                 }
             }
+            // Do not allow to reset password when current user has a managed profile
+            if (!isManagedProfile(userHandle)) {
+                for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+                    if (userInfo.isManagedProfile()) {
+                        if (!preN) {
+                            throw new IllegalStateException(
+                                    "Cannot reset password on user has managed profile");
+                        } else {
+                            Slog.e(LOG_TAG, "Cannot reset password on user has managed profile");
+                            return false;
+                        }
+                    }
+                }
+            }
+            // Do not allow to reset password when user is locked
+            if (!mUserManager.isUserUnlocked(userHandle)) {
+                if (!preN) {
+                    throw new IllegalStateException("Cannot reset password when user is locked");
+                } else {
+                    Slog.e(LOG_TAG, "Cannot reset password when user is locked");
+                    return false;
+                }
+            }
+
             quality = getPasswordQuality(null, userHandle, /* parent */ false);
             if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
                 quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e306d89..eed4351 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -176,7 +176,7 @@
      * visual content.
      */
     private static final int DEFAULT_SYSTEM_THEME =
-            com.android.internal.R.style.Theme_Material_Light_DarkActionBar;
+            com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar;
 
     private final int mFactoryTestMode;
     private Timer mProfilerSnapshotTimer;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index cbd0415..1afd90d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -23,6 +23,7 @@
 import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
 import com.android.layoutlib.bridge.bars.AppCompatActionBar;
 import com.android.layoutlib.bridge.bars.BridgeActionBar;
 import com.android.layoutlib.bridge.bars.Config;
@@ -232,8 +233,10 @@
 
     private BridgeActionBar createActionBar(@NonNull BridgeContext context,
             @NonNull SessionParams params) {
+        boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
+
         BridgeActionBar actionBar;
-        if (mBuilder.isThemeAppCompat()) {
+        if (mBuilder.isThemeAppCompat() && !isMenu) {
             actionBar = new AppCompatActionBar(context, params);
         } else {
             actionBar = new FrameworkActionBar(context, params);