Merge "RTL support for print UI." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 5c05305..42eaef0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5499,7 +5499,7 @@
     method public void uninstallCaCert(android.content.ComponentName, byte[]);
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
-    field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+    field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
     field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
     field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
@@ -5509,11 +5509,10 @@
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
     field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -8908,6 +8907,7 @@
     field public static final java.lang.String FEATURE_PRINTING = "android.software.print";
     field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
     field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
+    field public static final java.lang.String FEATURE_SECURELY_REMOVES_USERS = "android.software.securely_removes_users";
     field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
     field public static final java.lang.String FEATURE_SENSOR_AMBIENT_TEMPERATURE = "android.hardware.sensor.ambient_temperature";
     field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
@@ -8932,6 +8932,7 @@
     field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand";
     field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
+    field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
     field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -14074,29 +14075,6 @@
     method public android.media.AudioAttributes.Builder setUsage(int);
   }
 
-  public class AudioDevice {
-    field public static final int DEVICE_TYPE_AUX_LINE = 19; // 0x13
-    field public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8; // 0x8
-    field public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7; // 0x7
-    field public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1; // 0x1
-    field public static final int DEVICE_TYPE_BUILTIN_MIC = 15; // 0xf
-    field public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2; // 0x2
-    field public static final int DEVICE_TYPE_DOCK = 13; // 0xd
-    field public static final int DEVICE_TYPE_FM = 14; // 0xe
-    field public static final int DEVICE_TYPE_FM_TUNER = 16; // 0x10
-    field public static final int DEVICE_TYPE_HDMI = 9; // 0x9
-    field public static final int DEVICE_TYPE_HDMI_ARC = 10; // 0xa
-    field public static final int DEVICE_TYPE_LINE_ANALOG = 5; // 0x5
-    field public static final int DEVICE_TYPE_LINE_DIGITAL = 6; // 0x6
-    field public static final int DEVICE_TYPE_TELEPHONY = 18; // 0x12
-    field public static final int DEVICE_TYPE_TV_TUNER = 17; // 0x11
-    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int DEVICE_TYPE_USB_ACCESSORY = 12; // 0xc
-    field public static final int DEVICE_TYPE_USB_DEVICE = 11; // 0xb
-    field public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4; // 0x4
-    field public static final int DEVICE_TYPE_WIRED_HEADSET = 3; // 0x3
-  }
-
   public class AudioFormat {
     method public int getChannelMask();
     method public int getEncoding();
@@ -14420,6 +14398,7 @@
     field public static final int QUALITY_CIF = 3; // 0x3
     field public static final int QUALITY_HIGH = 1; // 0x1
     field public static final int QUALITY_HIGH_SPEED_1080P = 2004; // 0x7d4
+    field public static final int QUALITY_HIGH_SPEED_2160P = 2005; // 0x7d5
     field public static final int QUALITY_HIGH_SPEED_480P = 2002; // 0x7d2
     field public static final int QUALITY_HIGH_SPEED_720P = 2003; // 0x7d3
     field public static final int QUALITY_HIGH_SPEED_HIGH = 2001; // 0x7d1
@@ -14664,7 +14643,7 @@
   }
 
   public static final class MediaCodec.CodecException extends java.lang.IllegalStateException {
-    method public int getErrorCode();
+    method public java.lang.String getDiagnosticInfo();
     method public boolean isRecoverable();
     method public boolean isTransient();
   }
@@ -15002,7 +14981,7 @@
 
   public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
     ctor public MediaDrm.MediaDrmStateException(int, java.lang.String);
-    method public int getErrorCode();
+    method public java.lang.String getDiagnosticInfo();
   }
 
   public static abstract interface MediaDrm.OnEventListener {
@@ -16188,12 +16167,16 @@
     method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     method public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     method public boolean getStrengthSupported();
-    method public int getVirtualizationMode() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener);
     method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     field public static final int PARAM_STRENGTH = 1; // 0x1
     field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0
+    field public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1
+    field public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2
+    field public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0
+    field public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3
   }
 
   public static abstract interface Virtualizer.OnParameterChangeListener {
diff --git a/api/removed.txt b/api/removed.txt
index 3c16276..c8a3b4b 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,14 +22,6 @@
 
 }
 
-package android.service.notification {
-
-  public static class NotificationListenerService.Ranking {
-    method public boolean meetsInterruptionFilter();
-  }
-
-}
-
 package android.view {
 
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index f4e4671..25417ed 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -92,21 +92,27 @@
      */
     public static Animator loadAnimator(Resources resources, Theme theme, int id)
             throws NotFoundException {
+        return loadAnimator(resources, theme, id, 1);
+    }
+
+    /** @hide */
+    public static Animator loadAnimator(Resources resources, Theme theme, int id,
+            float pathErrorScale) throws NotFoundException {
 
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            return createAnimatorFromXml(resources, theme, parser);
+            return createAnimatorFromXml(resources, theme, parser, pathErrorScale);
         } catch (XmlPullParserException ex) {
             Resources.NotFoundException rnf =
                     new Resources.NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
+                            Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } catch (IOException ex) {
             Resources.NotFoundException rnf =
                     new Resources.NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
+                            Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } finally {
@@ -177,7 +183,7 @@
                         }
                         if (animator == null) {
                             animator = createAnimatorFromXml(context.getResources(),
-                                    context.getTheme(), parser);
+                                    context.getTheme(), parser, 1f);
                         }
 
                         if (animator == null) {
@@ -248,9 +254,11 @@
      * @param arrayAnimator Incoming typed array for Animator's attributes.
      * @param arrayObjectAnimator Incoming typed array for Object Animator's
      *            attributes.
+     * @param pixelSize The relative pixel size, used to calculate the
+     *                  maximum error for path animations.
      */
     private static void parseAnimatorFromTypeArray(ValueAnimator anim,
-            TypedArray arrayAnimator, TypedArray arrayObjectAnimator) {
+            TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) {
         long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300);
 
         long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);
@@ -303,7 +311,7 @@
         }
 
         if (arrayObjectAnimator != null) {
-            setupObjectAnimator(anim, arrayObjectAnimator, getFloats);
+            setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize);
         }
     }
 
@@ -351,9 +359,11 @@
      * @param anim The target Animator which will be updated.
      * @param arrayObjectAnimator TypedArray for the ObjectAnimator.
      * @param getFloats True if the value type is float.
+     * @param pixelSize The relative pixel size, used to calculate the
+     *                  maximum error for path animations.
      */
     private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator,
-            boolean getFloats) {
+            boolean getFloats, float pixelSize) {
         ObjectAnimator oa = (ObjectAnimator) anim;
         String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);
 
@@ -370,7 +380,8 @@
                         + " propertyXName or propertyYName is needed for PathData");
             } else {
                 Path path = PathParser.createPathFromPathData(pathData);
-                PathKeyframes keyframeSet = KeyframeSet.ofPath(path);
+                float error = 0.5f * pixelSize; // max half a pixel error
+                PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error);
                 Keyframes xKeyframes;
                 Keyframes yKeyframes;
                 if (getFloats) {
@@ -487,13 +498,15 @@
         }
     }
 
-    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser)
+    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
+            float pixelSize)
             throws XmlPullParserException, IOException {
-        return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0);
+        return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0,
+                pixelSize);
     }
 
     private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
-            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
+            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
             throws XmlPullParserException, IOException {
 
         Animator anim = null;
@@ -513,9 +526,9 @@
             String name = parser.getName();
 
             if (name.equals("objectAnimator")) {
-                anim = loadObjectAnimator(res, theme, attrs);
+                anim = loadObjectAnimator(res, theme, attrs, pixelSize);
             } else if (name.equals("animator")) {
-                anim = loadAnimator(res, theme, attrs, null);
+                anim = loadAnimator(res, theme, attrs, null, pixelSize);
             } else if (name.equals("set")) {
                 anim = new AnimatorSet();
                 TypedArray a;
@@ -526,7 +539,8 @@
                 }
                 int ordering = a.getInt(R.styleable.AnimatorSet_ordering,
                         TOGETHER);
-                createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering);
+                createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
+                        pixelSize);
                 a.recycle();
             } else {
                 throw new RuntimeException("Unknown animator name: " + parser.getName());
@@ -556,11 +570,11 @@
 
     }
 
-    private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs)
-            throws NotFoundException {
+    private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs,
+            float pathErrorScale) throws NotFoundException {
         ObjectAnimator anim = new ObjectAnimator();
 
-        loadAnimator(res, theme, attrs, anim);
+        loadAnimator(res, theme, attrs, anim, pathErrorScale);
 
         return anim;
     }
@@ -575,7 +589,7 @@
      *            ObjectAnimator
      */
     private static ValueAnimator loadAnimator(Resources res, Theme theme,
-            AttributeSet attrs, ValueAnimator anim)
+            AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
             throws NotFoundException {
 
         TypedArray arrayAnimator = null;
@@ -601,7 +615,7 @@
             anim = new ValueAnimator();
         }
 
-        parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator);
+        parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);
 
         final int resID =
                 arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index fc9bbb1..8d15db2 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -154,6 +154,10 @@
         return new PathKeyframes(path);
     }
 
+    public static PathKeyframes ofPath(Path path, float error) {
+        return new PathKeyframes(path, error);
+    }
+
     /**
      * Sets the TypeEvaluator to be used when calculating animated values. This object
      * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet,
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 9f49194..43fa3f0 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -599,17 +599,18 @@
                 mOriginalAlphas.put(view, view.getAlpha());
             }
             view.setAlpha(0f);
-            view.setTransitionAlpha(0f);
         }
     }
 
-    protected void showViews(ArrayList<View> views) {
+    protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
         int count = views.size();
         for (int i = 0; i < count; i++) {
             View view = views.get(i);
             Float alpha = mOriginalAlphas.remove(view);
             if (alpha != null) {
                 view.setAlpha(alpha);
+            }
+            if (setTransitionAlpha) {
                 view.setTransitionAlpha(1f);
             }
         }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index f38c108..9c7728e 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -240,7 +240,7 @@
         if (!mIsCanceled) {
             mIsCanceled = true;
             if (getViewsTransition() == null || mIsViewsTransitionStarted) {
-                showViews(mSharedElements);
+                showViews(mSharedElements, true);
             } else {
                 mTransitioningViews.addAll(mSharedElements);
             }
@@ -300,7 +300,7 @@
         // Now start shared element transition
         ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
                 mSharedElementNames);
-        showViews(mSharedElements);
+        showViews(mSharedElements, true);
         scheduleSetSharedElementEnd(sharedElementSnapshots);
         ArrayList<SharedElementOriginalState> originalImageViewState =
                 setSharedElementState(sharedElementState, sharedElementSnapshots);
@@ -411,7 +411,7 @@
                     @Override
                     public void onTransitionStart(Transition transition) {
                         mEnterViewsTransition = transition;
-                        showViews(mTransitioningViews);
+                        showViews(mTransitioningViews, false);
                         super.onTransitionStart(transition);
                     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 982bbc4..e85ec63 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -126,8 +126,8 @@
     }
 
     public void resetViews() {
-        showViews(mTransitioningViews);
-        showViews(mSharedElements);
+        showViews(mTransitioningViews, true);
+        showViews(mSharedElements, true);
         mIsHidden = true;
         if (!mIsReturning && getDecor() != null) {
             getDecor().suppressLayout(false);
@@ -296,7 +296,7 @@
                     transition.removeListener(this);
                     exitTransitionComplete();
                     if (mIsHidden) {
-                        showViews(mTransitioningViews);
+                        showViews(mTransitioningViews, true);
                     }
                     if (mSharedElementBundle != null) {
                         delayCancel();
@@ -323,7 +323,7 @@
                     transition.removeListener(this);
                     sharedElementTransitionComplete();
                     if (mIsHidden) {
-                        showViews(mSharedElements);
+                        showViews(mSharedElements, true);
                     }
                 }
             });
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 672ef7b..4374622 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -166,11 +166,12 @@
  * activity: if the activity is stopped, no fragments inside of it can be
  * started; when the activity is destroyed, all fragments will be destroyed.
  *
- * <p>All subclasses of Fragment must include a public empty constructor.
+ * <p>All subclasses of Fragment must include a public no-argument constructor.
  * The framework will often re-instantiate a fragment class when needed,
  * in particular during state restore, and needs to be able to find this
- * constructor to instantiate it.  If the empty constructor is not available,
- * a runtime exception will occur in some cases during state restore.
+ * constructor to instantiate it.  If the no-argument constructor is not
+ * available, a runtime exception will occur in some cases during state
+ * restore.
  *
  * <p>Topics covered here:
  * <ol>
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2476c4b..f9e4895 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -842,6 +842,13 @@
     public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
 
     /**
+     * {@link #extras} key: the user that built the notification.
+     *
+     * @hide
+     */
+    public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
      * displayed in the heads up space.
      *
@@ -1880,6 +1887,11 @@
         private int mColor = COLOR_DEFAULT;
 
         /**
+         * The user that built the notification originally.
+         */
+        private int mOriginatingUserId;
+
+        /**
          * Contains extras related to rebuilding during the build phase.
          */
         private Bundle mRebuildBundle = new Bundle();
@@ -2599,7 +2611,7 @@
             // Note: This assumes that the current user can read the profile badge of the
             // originating user.
             return mContext.getPackageManager().getUserBadgeForDensity(
-                    new UserHandle(mContext.getUserId()), 0);
+                    new UserHandle(mOriginatingUserId), 0);
         }
 
         private Bitmap getProfileBadge() {
@@ -2739,9 +2751,9 @@
             } else {
                 contentView.setViewVisibility(R.id.text2, View.GONE);
                 if (hasProgress && (mProgressMax != 0 || mProgressIndeterminate)) {
+                    contentView.setViewVisibility(R.id.progress, View.VISIBLE);
                     contentView.setProgressBar(
                             R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
-                    contentView.setViewVisibility(R.id.progress, View.VISIBLE);
                     showLine2 = true;
                 } else {
                     contentView.setViewVisibility(R.id.progress, View.GONE);
@@ -3070,6 +3082,7 @@
          */
         public void populateExtras(Bundle extras) {
             // Store original information used in the construction of this object
+            extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
             extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
                     mContext.getApplicationInfo());
             extras.putCharSequence(EXTRA_TITLE, mContentTitle);
@@ -3301,6 +3314,7 @@
 
             // Extras.
             Bundle extras = n.extras;
+            mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
             mContentTitle = extras.getCharSequence(EXTRA_TITLE);
             mContentText = extras.getCharSequence(EXTRA_TEXT);
             mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3333,6 +3347,7 @@
          * object.
          */
         public Notification build() {
+            mOriginatingUserId = mContext.getUserId();
             mHasThreeLines = hasThreeLines();
 
             Notification n = buildUnstyled();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 926a348..ea041e8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -97,8 +97,7 @@
      * Provisioning adds a managed profile and sets the mdm as the profile owner who has full
      * control over the profile
      *
-     * <p>This intent must contain the extras {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}
-     * {@link #EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME} and {@link #EXTRA_DEVICE_ADMIN}.
+     * <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
      *
      * <p> When managed provisioning has completed, an intent of the type
      * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -112,7 +111,7 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_PROFILE
-        = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+        = "android.app.action.PROVISION_MANAGED_PROFILE";
 
     /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
@@ -139,21 +138,18 @@
      * message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
-        = "android.app.extra.deviceAdminPackageName";
+        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
 
     /**
-     * A String extra holding the default name of the profile that is created during managed profile
-     * provisioning.
+     * A String extra that, holds the email address of the account which a managed profile is
+     * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
      *
-     * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
-     */
-    public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
-        = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
-
-    /**
-     * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
-     * corresponding value holds the email address of the account which the managed profile is
-     * created for.
+     * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
+     * contains this extra, it is forwarded in the
+     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
+     * device management application that was set as the profile owner during provisioning.
+     * It is usually used to avoid that the user has to enter their email address twice.
      */
     public static final String KEY_PROVISIONING_EMAIL_ADDRESS
         = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 36d15a0..5ce968b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1525,6 +1525,22 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device supports verified boot.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device supports secure removal of users. When a user is deleted the data associated
+     * with that user is securely deleted and no longer available.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_SECURELY_REMOVES_USERS
+            = "android.software.securely_removes_users";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device has a full implementation of the android.webkit.* APIs. Devices
      * lacking this feature will not have a functioning WebView implementation.
      */
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 843f117..0057f61 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -143,7 +143,6 @@
         }
 
         checkNotClosed();
-        checkLegalToCapture();
 
         handler = checkHandler(handler, callback);
 
@@ -166,7 +165,6 @@
         }
 
         checkNotClosed();
-        checkLegalToCapture();
 
         handler = checkHandler(handler, callback);
 
@@ -188,7 +186,6 @@
         }
 
         checkNotClosed();
-        checkLegalToCapture();
 
         handler = checkHandler(handler, callback);
 
@@ -211,7 +208,6 @@
         }
 
         checkNotClosed();
-        checkLegalToCapture();
 
         handler = checkHandler(handler, callback);
 
@@ -542,13 +538,6 @@
         }
     }
 
-    private void checkLegalToCapture() {
-        if (mAborting) {
-            throw new IllegalStateException(
-                    "Session is aborting captures; new captures are not permitted");
-        }
-    }
-
     private void checkNotClosed() {
         if (mClosed) {
             throw new IllegalStateException(
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e6ff17b..e6da670 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -374,6 +374,9 @@
             }
 
             mIntermediateBufferSize = bestPreviewDimen;
+            mParams.setPreviewSize(mIntermediateBufferSize.getWidth(),
+                    mIntermediateBufferSize.getHeight());
+
             if (DEBUG) {
                 Log.d(TAG, "Intermediate buffer selected with dimens: " +
                         bestPreviewDimen.toString());
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 8df9916..80e5b91 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -223,6 +223,9 @@
      * Called by the bearer code when it has a new score for this network.
      */
     public void sendNetworkScore(int score) {
+        if (score < 0) {
+            throw new IllegalArgumentException("Score must be >= 0");
+        }
         queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4c2dc8..01fda47 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3739,6 +3739,13 @@
                 "show_note_about_notification_hiding";
 
         /**
+         * Set to 1 by the system after trust agents have been initialized.
+         * @hide
+         */
+        public static final String TRUST_AGENTS_INITIALIZED =
+                "trust_agents_initialized";
+
+        /**
          * The Logging ID (a unique 64-bit value) as a hex string.
          * Used as a pseudonymous identifier for logging.
          * @deprecated This identifier is poorly initialized and has
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index aa724f0..3a91d1a 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Parcel;
@@ -28,6 +29,7 @@
  *
  * @hide
  */
+@SystemApi
 public class Condition implements Parcelable {
 
     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 326412f..03ee726 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.app.INotificationManager;
 import android.app.Service;
 import android.content.Context;
@@ -44,6 +45,7 @@
  *
  * @hide
  */
+@SystemApi
 public abstract class ConditionProviderService extends Service {
     private final String TAG = ConditionProviderService.class.getSimpleName()
             + "[" + getClass().getSimpleName() + "]";
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index d744070..b22fd9c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -756,15 +756,6 @@
             return mVisibilityOverride;
         }
 
-        /**
-         * Returns whether the notification meets the user's interruption
-         * filter.
-         *
-         * @removed
-         */
-        public boolean meetsInterruptionFilter() {
-            return mMatchesInterruptionFilter;
-        }
 
         /**
          * Returns whether the notification matches the user's interruption
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 872f911..9cbedab 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.content.ComponentName;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -55,6 +56,11 @@
     public static final int[] WEEKNIGHT_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
             Calendar.WEDNESDAY, Calendar.THURSDAY };
 
+    public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+    private static final int SECONDS_MS = 1000;
+    private static final int MINUTES_MS = 60 * SECONDS_MS;
+    private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
+
     private static final int XML_VERSION = 1;
     private static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
@@ -445,6 +451,23 @@
         return downtime;
     }
 
+    public static Condition toTimeCondition(int minutesFromNow) {
+        final long now = System.currentTimeMillis();
+        final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
+        return toTimeCondition(now + millis, minutesFromNow);
+    }
+
+    public static Condition toTimeCondition(long time, int minutes) {
+        final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
+        final int resId = minutes < 60
+                ? com.android.internal.R.plurals.zen_mode_duration_minutes
+                : com.android.internal.R.plurals.zen_mode_duration_hours;
+        final String caption = Resources.getSystem().getQuantityString(resId, num, num);
+        final Uri id = toCountdownConditionId(time);
+        return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
+                Condition.FLAG_RELEVANT_NOW);
+    }
+
     // For built-in conditions
     private static final String SYSTEM_AUTHORITY = "android";
 
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index e7ada27..1671faa 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -211,18 +211,6 @@
      }
 
     /**
-     * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified.
-     * Arguments for this constructor have the same meanings as
-     * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean,
-     * boolean, int)} except "id" and "overridesImplicitlyEnabledSubtype".
-     * @hide
-     */
-    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
-            boolean isAuxiliary) {
-        this(nameId, iconId, locale, mode, extraValue, isAuxiliary, false);
-    }
-
-    /**
      * Constructor with no subtype ID specified.
      * @deprecated use {@link InputMethodSubtypeBuilder} instead.
      * Arguments for this constructor have the same meanings as
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8a1d5af..bf2d09b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2773,7 +2773,7 @@
         android:description="@string/permdesc_bindNotificationListenerService"
         android:protectionLevel="signature" />
 
-    <!-- Must be required by an {@link
+    <!-- @SystemApi Must be required by a {@link
          android.service.notification.ConditionProviderService},
          to ensure that only the system can bind to it.
          @hide -->
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index 7e99c5e..aeef3ab 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -45,13 +45,13 @@
             android:visibility="gone"
             />
     </LinearLayout>
-    <ProgressBar
+    <ViewStub
         android:id="@android:id/progress"
+        android:layout="@layout/notification_template_progressbar"
         android:layout_width="match_parent"
         android:layout_height="15dp"
         android:layout_marginEnd="8dp"
         android:visibility="gone"
         android:layout_weight="0"
-        style="@style/Widget.Material.Light.ProgressBar.Horizontal"
         />
 </merge>
diff --git a/core/res/res/layout/notification_template_progressbar.xml b/core/res/res/layout/notification_template_progressbar.xml
new file mode 100644
index 0000000..61480b8
--- /dev/null
+++ b/core/res/res/layout/notification_template_progressbar.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/progress"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    style="@style/Widget.Material.Light.ProgressBar.Horizontal"
+    />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5c932fd..50da1fa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4877,4 +4877,19 @@
 
     <!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
     <string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string>
+
+    <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
+    <plurals name="zen_mode_duration_minutes">
+        <item quantity="one">For one minute</item>
+        <item quantity="other">For %d minutes</item>
+    </plurals>
+
+    <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
+    <plurals name="zen_mode_duration_hours">
+        <item quantity="one">For one hour</item>
+        <item quantity="other">For %d hours</item>
+    </plurals>
+
+    <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
+    <string name="zen_mode_forever">Indefinitely</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c28f3a6..556c07f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1918,6 +1918,9 @@
   <java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
   <java-symbol type="string" name="battery_saver_description" />
   <java-symbol type="string" name="downtime_condition_summary" />
+  <java-symbol type="string" name="zen_mode_forever" />
+  <java-symbol type="plurals" name="zen_mode_duration_minutes" />
+  <java-symbol type="plurals" name="zen_mode_duration_hours" />
 
   <java-symbol type="string" name="item_is_selected" />
   <java-symbol type="string" name="day_of_week_label_typeface" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 77e1c530..80d5668 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -322,8 +322,13 @@
      * If the device is already associated with a WiFi, disconnect and forget it,
      * We don't verify whether the connection is successful or not, leave this to the test
      */
-    protected boolean connectToWifi(String knownSSID) {
-        WifiConfiguration config = WifiConfigurationHelper.createOpenConfig(knownSSID);
+    protected boolean connectToWifi(String ssid, String password) {
+        WifiConfiguration config;
+        if (password == null) {
+            config = WifiConfigurationHelper.createOpenConfig(ssid);
+        } else {
+            config = WifiConfigurationHelper.createPskConfig(ssid, password);
+        }
         return connectToWifiWithConfiguration(config);
     }
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
index b94306a..b6eb674 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -35,8 +35,9 @@
  */
 
 public class ConnectivityManagerTestRunner extends InstrumentationTestRunner {
-    public boolean mWifiOnlyFlag = false;
-    public String mTestSsid = null;
+    public boolean mWifiOnly = false;
+    public String mSsid = null;
+    public String mPassword = null;
 
     @Override
     public TestSuite getAllTests() {
@@ -54,13 +55,29 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        String testSSID = (String) icicle.get("ssid");
-        if (testSSID != null) {
-            mTestSsid = testSSID;
+        String ssid = icicle.getString("ssid");
+        if (ssid != null) {
+            mSsid = ssid;
+        }
+        String password = (String) icicle.get("password");
+        if (password != null) {
+            mPassword = password;
         }
         String wifiOnlyFlag = (String) icicle.get("wifi-only");
         if (wifiOnlyFlag != null) {
-            mWifiOnlyFlag = true;
+            mWifiOnly = true;
         }
     }
+
+    public String getWifiSsid() {
+        return mSsid;
+    }
+
+    public String getWifiPassword() {
+        return mPassword;
+    }
+
+    public boolean isWifiOnly() {
+        return mWifiOnly;
+    }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index b280106..d5051df 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -33,7 +33,8 @@
         super(ConnectivityManagerMobileTest.class.getSimpleName());
     }
 
-    private String mTestAccessPoint;
+    private String mSsid;
+    private String mPassword;
     private boolean mWifiOnlyFlag;
 
     @Override
@@ -41,8 +42,9 @@
         super.setUp();
         ConnectivityManagerTestRunner mRunner =
                 (ConnectivityManagerTestRunner)getInstrumentation();
-        mTestAccessPoint = mRunner.mTestSsid;
-        mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
+        mSsid = mRunner.getWifiSsid();
+        mPassword = mRunner.getWifiPassword();
+        mWifiOnlyFlag = mRunner.isWifiOnly();
 
         // Each test case will start with cellular connection
         if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
@@ -120,11 +122,10 @@
     // Test case 2: test connection to a given AP
     @LargeTest
     public void testConnectToWifi() {
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
 
         // assert that we are able to connect to the ap
-        assertTrue("failed to connect to " + mTestAccessPoint,
-                connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
         // assert that WifiManager reports correct state
         assertTrue("wifi not enabled", waitForWifiState(
                 WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
@@ -144,14 +145,14 @@
     // Test case 3: connect & reconnect to Wifi with known AP
     @LargeTest
     public void testConnectToWifWithKnownAP() {
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
         // enable WiFi
         assertTrue("failed to enable wifi", enableWifi());
         // wait for wifi enable
         assertTrue("wifi not enabled", waitForWifiState(
                 WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
         // Connect to AP
-        assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
         // verify wifi connected as reported by ConnectivityManager
         assertTrue("wifi not connected", waitForNetworkState(
                 ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -191,7 +192,7 @@
     // Test case 4:  test disconnect and clear wifi settings
     @LargeTest
     public void testDisconnectWifi() {
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
 
         // enable WiFi
         assertTrue("failed to enable wifi", enableWifi());
@@ -199,8 +200,7 @@
         assertTrue("wifi not enabled", waitForWifiState(
                 WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
         // connect to Wifi
-        assertTrue("failed to connect to " + mTestAccessPoint,
-                connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
 
         assertTrue("wifi not connected", waitForNetworkState(
                 ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -257,7 +257,7 @@
     // Test case 6: test connectivity with airplane mode on but wifi enabled
     @LargeTest
     public void testDataConnectionOverAMWithWifi() {
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
         // enable airplane mode
         mCm.setAirplaneMode(true);
         // assert there is active network connection after airplane mode disabled
@@ -265,8 +265,7 @@
                 waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
 
         // connect to Wifi
-        assertTrue("failed to connect to " + mTestAccessPoint,
-                connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
         assertTrue("wifi not connected", waitForNetworkState(
                 ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
         // verify that connection actually works
@@ -280,15 +279,14 @@
     @LargeTest
     public void testDataConnectionWithWifiToAMToWifi () {
         // connect to mTestAccessPoint
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
         // enable WiFi
         assertTrue("failed to enable wifi", enableWifi());
         // wait for wifi enable
         assertTrue("wifi not enabled", waitForWifiState(
                 WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
         // connect to Wifi
-        assertTrue("failed to connect to " + mTestAccessPoint,
-                connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
         assertTrue("wifi not connected", waitForNetworkState(
                 ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
 
@@ -313,15 +311,14 @@
     // Test case 8: test wifi state change while connecting/disconnecting to/from an AP
     @LargeTest
     public void testWifiStateChange () {
-        assertNotNull("SSID is null", mTestAccessPoint);
+        assertNotNull("SSID is null", mSsid);
         // enable WiFi
         assertTrue("failed to enable wifi", enableWifi());
         // wait for wifi enable
         assertTrue("wifi not enabled", waitForWifiState(
                 WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
         // connect to Wifi
-        assertTrue("failed to connect to " + mTestAccessPoint,
-                connectToWifi(mTestAccessPoint));
+        assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
         assertTrue("wifi not connected", waitForNetworkState(
                 ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
         assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID());
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index fa1bd8f..5958c3a 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -26,6 +26,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -159,8 +160,15 @@
 
     private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
             boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
-        return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary,
-                overridesImplicitlyEnabledSubtype);
+        return new InputMethodSubtypeBuilder()
+                .setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeLocale(locale)
+                .setSubtypeMode(mode)
+                .setSubtypeExtraValue("")
+                .setIsAuxiliary(isAuxiliary)
+                .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
+                .build();
     }
 
     private static InputMethodInfo createDefaultAutoDummyVoiceIme() {
diff --git a/docs/html/tools/building/index.jd b/docs/html/tools/building/index.jd
index c64942f..c1f3019 100644
--- a/docs/html/tools/building/index.jd
+++ b/docs/html/tools/building/index.jd
@@ -79,3 +79,14 @@
     running on a device.</li>
   </ul>
 
+<p class="note"><b>Note:</b> Apps are limited to a 64K method reference limit. If your app reaches
+this limit, the build process outputs the following error message:
+
+<pre>Unable to execute dex: method ID not in [0, 0xffff]: 65536.</pre>
+
+To avoid this, you can
+<a href="http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html">load
+secondary dex files at runtime</a> and use
+<a href="http://developer.android.com/tools/help/proguard.html">ProGuard</a> to strip out unnecessary
+class references (Proguard only works when building in release mode).
+</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ba22550..e5e2f18 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -252,6 +252,7 @@
             throws XmlPullParserException, IOException {
 
         int eventType = parser.getEventType();
+        float pathErrorScale = 1;
         while (eventType != XmlPullParser.END_DOCUMENT) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
@@ -261,9 +262,11 @@
                     int drawableRes = a.getResourceId(
                             R.styleable.AnimatedVectorDrawable_drawable, 0);
                     if (drawableRes != 0) {
-                        mAnimatedVectorState.mVectorDrawable = (VectorDrawable) res.getDrawable(
+                        VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable(
                                 drawableRes, theme).mutate();
-                        mAnimatedVectorState.mVectorDrawable.setAllowCaching(false);
+                        vectorDrawable.setAllowCaching(false);
+                        pathErrorScale = vectorDrawable.getPixelSize();
+                        mAnimatedVectorState.mVectorDrawable = vectorDrawable;
                     }
                     a.recycle();
                 } else if (TARGET.equals(tagName)) {
@@ -275,7 +278,8 @@
                     int id = a.getResourceId(
                             R.styleable.AnimatedVectorDrawableTarget_animation, 0);
                     if (id != 0) {
-                        Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id);
+                        Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id,
+                                pathErrorScale);
                         setupAnimatorsForTarget(target, objectAnimator);
                     }
                     a.recycle();
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 042da5b..a07ccc4 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -368,6 +368,29 @@
         }
     }
 
+    /**
+     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension.
+     * This is used to calculate the path animation accuracy.
+     *
+     * @hide
+     */
+    public float getPixelSize() {
+        if (mVectorState == null && mVectorState.mVPathRenderer == null ||
+                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
+                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
+                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
+                mVectorState.mVPathRenderer.mViewportWidth == 0) {
+            return 1; // fall back to 1:1 pixel mapping.
+        }
+        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
+        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
+        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
+        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
+        float scaleX = viewportWidth / intrinsicWidth;
+        float scaleY = viewportHeight / intrinsicHeight;
+        return Math.min(scaleX, scaleY);
+    }
+
     /** @hide */
     public static VectorDrawable create(Resources resources, int rid) {
         try {
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDevice.java
index e078354..df4d60d 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDevice.java
@@ -20,90 +20,91 @@
 
 /**
  * Class to provide information about the audio devices.
+ * @hide
  */
 public class AudioDevice {
 
     /**
      * A device type associated with an unknown or uninitialized device.
      */
-    public static final int DEVICE_TYPE_UNKNOWN          = 0;
+    public static final int TYPE_UNKNOWN          = 0;
     /**
      * A device type describing the attached earphone speaker.
      */
-    public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1;
+    public static final int TYPE_BUILTIN_EARPIECE = 1;
     /**
      * A device type describing the speaker system (i.e. a mono speaker or stereo speakers) built
      * in a device.
      */
-    public static final int DEVICE_TYPE_BUILTIN_SPEAKER  = 2;
+    public static final int TYPE_BUILTIN_SPEAKER  = 2;
     /**
      * A device type describing a headset, which is the combination of a headphones and microphone.
      */
-    public static final int DEVICE_TYPE_WIRED_HEADSET    = 3;
+    public static final int TYPE_WIRED_HEADSET    = 3;
     /**
      * A device type describing a pair of wired headphones .
      */
-    public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4;
+    public static final int TYPE_WIRED_HEADPHONES = 4;
     /**
      * A device type describing an analog line-level connection.
      */
-    public static final int DEVICE_TYPE_LINE_ANALOG      = 5;
+    public static final int TYPE_LINE_ANALOG      = 5;
     /**
      * A device type describing a digital line connection (e.g. SPDIF).
      */
-    public static final int DEVICE_TYPE_LINE_DIGITAL     = 6;
+    public static final int TYPE_LINE_DIGITAL     = 6;
     /**
      * A device type describing a Bluetooth device typically used for telephony .
      */
-    public static final int DEVICE_TYPE_BLUETOOTH_SCO    = 7;
+    public static final int TYPE_BLUETOOTH_SCO    = 7;
     /**
      * A device type describing a Bluetooth device supporting the A2DP profile.
      */
-    public static final int DEVICE_TYPE_BLUETOOTH_A2DP   = 8;
+    public static final int TYPE_BLUETOOTH_A2DP   = 8;
     /**
      * A device type describing an HDMI connection .
      */
-    public static final int DEVICE_TYPE_HDMI             = 9;
+    public static final int TYPE_HDMI             = 9;
     /**
      * A device type describing the Audio Return Channel of an HDMI connection.
      */
-    public static final int DEVICE_TYPE_HDMI_ARC         = 10;
+    public static final int TYPE_HDMI_ARC         = 10;
     /**
      * A device type describing a USB audio device.
      */
-    public static final int DEVICE_TYPE_USB_DEVICE       = 11;
+    public static final int TYPE_USB_DEVICE       = 11;
     /**
      * A device type describing a USB audio device in accessory mode.
      */
-    public static final int DEVICE_TYPE_USB_ACCESSORY    = 12;
+    public static final int TYPE_USB_ACCESSORY    = 12;
     /**
      * A device type describing the audio device associated with a dock.
      */
-    public static final int DEVICE_TYPE_DOCK             = 13;
+    public static final int TYPE_DOCK             = 13;
     /**
      * A device type associated with the transmission of audio signals over FM.
      */
-    public static final int DEVICE_TYPE_FM               = 14;
+    public static final int TYPE_FM               = 14;
     /**
      * A device type describing the microphone(s) built in a device.
      */
-    public static final int DEVICE_TYPE_BUILTIN_MIC      = 15;
+    public static final int TYPE_BUILTIN_MIC      = 15;
     /**
      * A device type for accessing the audio content transmitted over FM.
      */
-    public static final int DEVICE_TYPE_FM_TUNER         = 16;
+    public static final int TYPE_FM_TUNER         = 16;
     /**
      * A device type for accessing the audio content transmitted over the TV tuner system.
      */
-    public static final int DEVICE_TYPE_TV_TUNER         = 17;
+    public static final int TYPE_TV_TUNER         = 17;
     /**
      * A device type describing the transmission of audio signals over the telephony network.
      */
-    public static final int DEVICE_TYPE_TELEPHONY        = 18;
+    public static final int TYPE_TELEPHONY        = 18;
     /**
      * A device type describing the auxiliary line-level connectors.
      */
-    public static final int DEVICE_TYPE_AUX_LINE         = 19;
+    public static final int TYPE_AUX_LINE         = 19;
 
     AudioDevicePortConfig mConfig;
 
@@ -135,7 +136,7 @@
      * @return
      */
     public int getDeviceType() {
-        return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), DEVICE_TYPE_UNKNOWN);
+        return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), TYPE_UNKNOWN);
     }
 
     /**
@@ -154,7 +155,7 @@
 
     /** @hide */
     public static int convertInternalDeviceToDeviceType(int intDevice) {
-        return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, DEVICE_TYPE_UNKNOWN);
+        return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, TYPE_UNKNOWN);
     }
 
     private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
@@ -163,43 +164,43 @@
 
     static {
         INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, DEVICE_TYPE_BUILTIN_EARPIECE);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, DEVICE_TYPE_BUILTIN_SPEAKER);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, DEVICE_TYPE_WIRED_HEADPHONES);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_SCO);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, DEVICE_TYPE_BLUETOOTH_SCO);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, DEVICE_TYPE_BLUETOOTH_A2DP);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, DEVICE_TYPE_BLUETOOTH_A2DP);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, DEVICE_TYPE_HDMI);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, DEVICE_TYPE_TELEPHONY);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, DEVICE_TYPE_LINE_ANALOG);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, DEVICE_TYPE_HDMI_ARC);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, DEVICE_TYPE_FM);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, DEVICE_TYPE_AUX_LINE);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, TYPE_BUILTIN_EARPIECE);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, TYPE_BUILTIN_SPEAKER);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, TYPE_WIRED_HEADPHONES);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, TYPE_BLUETOOTH_SCO);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, TYPE_BLUETOOTH_SCO);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, TYPE_BLUETOOTH_A2DP);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, TYPE_BLUETOOTH_A2DP);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, TYPE_HDMI);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, TYPE_DOCK);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, TYPE_DOCK);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, TYPE_USB_DEVICE);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, TYPE_TELEPHONY);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, TYPE_LINE_ANALOG);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, TYPE_HDMI_ARC);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, TYPE_LINE_DIGITAL);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, TYPE_FM);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, TYPE_AUX_LINE);
 
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, DEVICE_TYPE_BUILTIN_MIC);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, DEVICE_TYPE_HDMI);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, DEVICE_TYPE_TELEPHONY);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, DEVICE_TYPE_BUILTIN_MIC);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, DEVICE_TYPE_FM_TUNER);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, DEVICE_TYPE_TV_TUNER);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, DEVICE_TYPE_LINE_ANALOG);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
-        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, TYPE_HDMI);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, TYPE_TELEPHONY);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, TYPE_BUILTIN_MIC);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, TYPE_DOCK);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, TYPE_DOCK);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, TYPE_USB_DEVICE);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, TYPE_FM_TUNER);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, TYPE_TV_TUNER);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, TYPE_LINE_ANALOG);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, TYPE_LINE_DIGITAL);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
 
         // not covered here, legacy
         //AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
@@ -207,25 +208,25 @@
 
         // privileges mapping to output device
         EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM, AudioSystem.DEVICE_OUT_FM);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
-        EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM, AudioSystem.DEVICE_OUT_FM);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
     }
 }
 
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 8883d28..5651fc9 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -177,9 +177,15 @@
      */
     public static final int QUALITY_HIGH_SPEED_1080P = 2004;
 
+    /**
+     * High speed ( >= 100fps) quality level corresponding to the 2160p (3840 x 2160)
+     * resolution.
+     */
+    public static final int QUALITY_HIGH_SPEED_2160P = 2005;
+
     // Start and end of high speed quality list
     private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW;
-    private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_1080P;
+    private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P;
 
     /**
      * Default recording duration in seconds before the session is terminated.
@@ -313,6 +319,7 @@
      * @see #QUALITY_HIGH_SPEED_480P
      * @see #QUALITY_HIGH_SPEED_720P
      * @see #QUALITY_HIGH_SPEED_1080P
+     * @see #QUALITY_HIGH_SPEED_2160P
     */
     public static CamcorderProfile get(int cameraId, int quality) {
         if (!((quality >= QUALITY_LIST_START &&
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 81ebb14..1c7c9ea 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -672,6 +672,11 @@
             super(detailMessage);
             mErrorCode = errorCode;
             mActionCode = actionCode;
+
+            // TODO get this from codec
+            final String sign = errorCode < 0 ? "neg_" : "";
+            mDiagnosticInfo =
+                "android.media.MediaCodec.error_" + sign + Math.abs(errorCode);
         }
 
         /**
@@ -696,15 +701,28 @@
          * Retrieve the error code associated with a CodecException.
          * This is opaque diagnostic information and may depend on
          * hardware or API level.
+         *
+         * @hide
          */
         public int getErrorCode() {
             return mErrorCode;
         }
 
+        /**
+         * Retrieve a human readable diagnostic information string
+         * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+         * This string will not be localized or generally comprehensible
+         * to end-users.
+         */
+        public String getDiagnosticInfo() {
+            return mDiagnosticInfo;
+        }
+
         /* Must be in sync with android_media_MediaCodec.cpp */
         private final static int ACTION_TRANSIENT = 1;
         private final static int ACTION_RECOVERABLE = 2;
 
+        private final String mDiagnosticInfo;
         private final int mErrorCode;
         private final int mActionCode;
     }
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index ca707d8..1490732 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -188,18 +188,37 @@
      */
     public static final class MediaDrmStateException extends java.lang.IllegalStateException {
         private final int mErrorCode;
+        private final String mDiagnosticInfo;
 
         public MediaDrmStateException(int errorCode, String detailMessage) {
             super(detailMessage);
             mErrorCode = errorCode;
+
+            // TODO get this from DRM session
+            final String sign = errorCode < 0 ? "neg_" : "";
+            mDiagnosticInfo =
+                "android.media.MediaDrm.error_" + sign + Math.abs(errorCode);
+
         }
 
         /**
          * Retrieve the associated error code
+         *
+         * @hide
          */
         public int getErrorCode() {
             return mErrorCode;
         }
+
+        /**
+         * Retrieve a human readable diagnostic information string
+         * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+         * This string will not be localized or generally comprehensible
+         * to end-users.
+         */
+        public String getDiagnosticInfo() {
+            return mDiagnosticInfo;
+        }
     }
 
     /**
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 9343aa4..afa0b6e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1929,6 +1929,7 @@
         mSubtitleController.setAnchor(anchor);
     }
 
+    private final Object mInbandSubtitleLock = new Object();
     private SubtitleTrack[] mInbandSubtitleTracks;
     private int mSelectedSubtitleTrackIndex = -1;
     private Vector<SubtitleTrack> mOutOfBandSubtitleTracks;
@@ -2036,19 +2037,21 @@
         }
 
         TrackInfo[] tracks = getInbandTrackInfo();
-        SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
-        for (int i=0; i < tracks.length; i++) {
-            if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
-                if (i < mInbandSubtitleTracks.length) {
-                    inbandTracks[i] = mInbandSubtitleTracks[i];
-                } else {
-                    SubtitleTrack track = mSubtitleController.addTrack(
-                            tracks[i].getFormat());
-                    inbandTracks[i] = track;
+        synchronized (mInbandSubtitleLock) {
+            SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
+            for (int i=0; i < tracks.length; i++) {
+                if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+                    if (i < mInbandSubtitleTracks.length) {
+                        inbandTracks[i] = mInbandSubtitleTracks[i];
+                    } else {
+                        SubtitleTrack track = mSubtitleController.addTrack(
+                                tracks[i].getFormat());
+                        inbandTracks[i] = track;
+                    }
                 }
             }
+            mInbandSubtitleTracks = inbandTracks;
         }
-        mInbandSubtitleTracks = inbandTracks;
         mSubtitleController.selectDefaultTrack();
     }
 
@@ -2224,9 +2227,9 @@
                 try {
                     Libcore.os.lseek(fd3, offset2, OsConstants.SEEK_SET);
                     byte[] buffer = new byte[4096];
-                    for (int total = 0; total < length2;) {
-                        int remain = (int)length2 - total;
-                        int bytes = IoBridge.read(fd3, buffer, 0, Math.min(buffer.length, remain));
+                    for (long total = 0; total < length2;) {
+                        int bytesToRead = (int) Math.min(buffer.length, length2 - total);
+                        int bytes = IoBridge.read(fd3, buffer, 0, bytesToRead);
                         if (bytes < 0) {
                             break;
                         } else {
@@ -2358,6 +2361,18 @@
             throws IllegalStateException {
         // handle subtitle track through subtitle controller
         SubtitleTrack track = null;
+        synchronized (mInbandSubtitleLock) {
+            if (mInbandSubtitleTracks.length == 0) {
+                TrackInfo[] tracks = getInbandTrackInfo();
+                mInbandSubtitleTracks = new SubtitleTrack[tracks.length];
+                for (int i=0; i < tracks.length; i++) {
+                    if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+                        mInbandSubtitleTracks[i] = mSubtitleController.addTrack(tracks[i].getFormat());
+                    }
+                }
+            }
+        }
+
         if (index < mInbandSubtitleTracks.length) {
             track = mInbandSubtitleTracks[index];
         } else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) {
@@ -3256,9 +3271,7 @@
                 if (DEBUG) Log.d(TAG, "scheduleUpdate");
                 int i = registerListener(listener);
 
-                if (mStopped) {
-                    scheduleNotification(NOTIFY_STOP, 0 /* delay */);
-                } else {
+                if (!mStopped) {
                     mTimes[i] = 0;
                     scheduleNotification(NOTIFY_TIME, 0 /* delay */);
                 }
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 37adb8c..f82dbe0 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -275,7 +275,7 @@
                      mSelectedTrack.getFormat().getInteger(
                             MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) {
                     show();
-                } else {
+                } else if (mSelectedTrack != null && !mSelectedTrack.isTimedText()) {
                     hide();
                 }
                 mVisibilityIsExplicit = false;
diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
index b314c02..be5adc8 100644
--- a/media/java/android/media/audiofx/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -16,11 +16,14 @@
 
 package android.media.audiofx;
 
+import android.annotation.IntDef;
 import android.media.AudioDevice;
 import android.media.AudioFormat;
 import android.media.audiofx.AudioEffect;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.StringTokenizer;
@@ -248,14 +251,114 @@
     }
 
     /**
-     * Checks if the combination of a channel mask and device type is supported by this virtualizer.
+     * A virtualization mode indicating virtualization processing is not active.
+     * See {@link #getVirtualizationMode()} as one of the possible return value.
+     */
+    public static final int VIRTUALIZATION_MODE_OFF = 0;
+
+    /**
+     * A virtualization mode used to indicate the virtualizer effect must stop forcing the
+     * processing to a particular mode in {@link #forceVirtualizationMode(int)}.
+     */
+    public static final int VIRTUALIZATION_MODE_AUTO = 1;
+    /**
+     * A virtualization mode typically used over headphones.
+     * Binaural virtualization describes an audio processing configuration for virtualization
+     * where the left and right channels are respectively reaching the left and right ear of the
+     * user, without also feeding the opposite ear (as is the case when listening over speakers).
+     * <p>Such a mode is therefore meant to be used when audio is playing over stereo wired
+     * headphones or headsets, but also stereo headphones through a wireless A2DP Bluetooth link.
+     * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+     */
+    public final static int VIRTUALIZATION_MODE_BINAURAL = 2;
+
+    /**
+     * A virtualization mode typically used over speakers.
+     * Transaural virtualization describes an audio processing configuration that differs from
+     * binaural (as described in {@link #VIRTUALIZATION_MODE_BINAURAL} in that cross-talk is
+     * present, i.e. audio played from the left channel also reaches the right ear of the user,
+     * and vice-versa.
+     * <p>When supported, such a mode is therefore meant to be used when audio is playing over the
+     * built-in stereo speakers of a device, if they are featured.
+     * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+     */
+    public final static int VIRTUALIZATION_MODE_TRANSAURAL = 3;
+
+    /** @hide */
+    @IntDef( {
+        VIRTUALIZATION_MODE_BINAURAL,
+        VIRTUALIZATION_MODE_TRANSAURAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface VirtualizationMode {}
+
+    /** @hide */
+    @IntDef( {
+        VIRTUALIZATION_MODE_AUTO,
+        VIRTUALIZATION_MODE_BINAURAL,
+        VIRTUALIZATION_MODE_TRANSAURAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ForceVirtualizationMode {}
+
+    private static int getDeviceForModeQuery(@VirtualizationMode int virtualizationMode)
+            throws IllegalArgumentException {
+        switch (virtualizationMode) {
+            case VIRTUALIZATION_MODE_BINAURAL:
+                return AudioDevice.TYPE_WIRED_HEADPHONES;
+            case VIRTUALIZATION_MODE_TRANSAURAL:
+                return AudioDevice.TYPE_BUILTIN_SPEAKER;
+            default:
+                throw (new IllegalArgumentException(
+                        "Virtualizer: illegal virtualization mode " + virtualizationMode));
+        }
+    }
+
+    private static int getDeviceForModeForce(@ForceVirtualizationMode int virtualizationMode)
+            throws IllegalArgumentException {
+        if (virtualizationMode == VIRTUALIZATION_MODE_AUTO) {
+            return AudioDevice.TYPE_UNKNOWN;
+        } else {
+            return getDeviceForModeQuery(virtualizationMode);
+        }
+    }
+
+    private static int deviceToMode(int deviceType) {
+        switch (deviceType) {
+            case AudioDevice.TYPE_WIRED_HEADSET:
+            case AudioDevice.TYPE_WIRED_HEADPHONES:
+            case AudioDevice.TYPE_BLUETOOTH_SCO:
+            case AudioDevice.TYPE_BUILTIN_EARPIECE:
+                return VIRTUALIZATION_MODE_BINAURAL;
+            case AudioDevice.TYPE_BUILTIN_SPEAKER:
+            case AudioDevice.TYPE_LINE_ANALOG:
+            case AudioDevice.TYPE_LINE_DIGITAL:
+            case AudioDevice.TYPE_BLUETOOTH_A2DP:
+            case AudioDevice.TYPE_HDMI:
+            case AudioDevice.TYPE_HDMI_ARC:
+            case AudioDevice.TYPE_USB_DEVICE:
+            case AudioDevice.TYPE_USB_ACCESSORY:
+            case AudioDevice.TYPE_DOCK:
+            case AudioDevice.TYPE_FM:
+            case AudioDevice.TYPE_AUX_LINE:
+                return VIRTUALIZATION_MODE_TRANSAURAL;
+            case AudioDevice.TYPE_UNKNOWN:
+            default:
+                return VIRTUALIZATION_MODE_OFF;
+        }
+    }
+
+    /**
+     * Checks if the combination of a channel mask and virtualization mode is supported by this
+     * virtualizer.
      * Some virtualizer implementations may only support binaural processing (i.e. only support
-     * headphone output), some may support transaural processing (i.e. for speaker output) for the
+     * headphone output, see {@link #VIRTUALIZATION_MODE_BINAURAL}), some may support transaural
+     * processing (i.e. for speaker output, see {@link #VIRTUALIZATION_MODE_TRANSAURAL}) for the
      * built-in speakers. Use this method to query the virtualizer implementation capabilities.
      * @param inputChannelMask the channel mask of the content to virtualize.
-     * @param deviceType the device type for which virtualization processing is to be performed.
-     *    Valid values are the device types defined in {@link AudioDevice}.
-     * @return true if the combination of channel mask and output device type is supported, false
+     * @param virtualizationMode the mode for which virtualization processing is to be performed,
+     *    one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+     * @return true if the combination of channel mask and virtualization mode is supported, false
      *    otherwise.
      *    <br>An indication that a certain channel mask is not supported doesn't necessarily mean
      *    you cannot play content with that channel mask, it more likely implies the content will
@@ -268,22 +371,22 @@
      * @throws IllegalArgumentException
      * @throws UnsupportedOperationException
      */
-    public boolean canVirtualize(int inputChannelMask, int deviceType)
+    public boolean canVirtualize(int inputChannelMask, @VirtualizationMode int virtualizationMode)
             throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
-        return getAnglesInt(inputChannelMask, deviceType, null);
+        return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), null);
     }
 
     /**
      * Queries the virtual speaker angles (azimuth and elevation) for a combination of a channel
-     * mask and device type.
-     * If the virtualization configuration (mask and device) is supported (see
+     * mask and virtualization mode.
+     * If the virtualization configuration (mask and mode) is supported (see
      * {@link #canVirtualize(int, int)}, the array angles will contain upon return the
      * definition of each virtual speaker and its azimuth and elevation angles relative to the
      * listener.
      * <br>Note that in some virtualizer implementations, the angles may be strength-dependent.
      * @param inputChannelMask the channel mask of the content to virtualize.
-     * @param deviceType the device type for which virtualization processing is to be performed.
-     *    Valid values are the device types defined in {@link AudioDevice}.
+     * @param virtualizationMode the mode for which virtualization processing is to be performed,
+     *    one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
      * @param angles a non-null array whose length is 3 times the number of channels in the channel
      *    mask.
      *    If the method indicates the configuration is supported, the array will contain upon return
@@ -297,37 +400,39 @@
      *      <li>the element at index <code>3*i+2</code> contains its corresponding elevation angle
      *          where +90 is directly above the listener, 0 is the horizontal plane, and -90 is
      *          directly below the listener.</li>
-     * @return true if the combination of channel mask and output device type is supported, false
+     * @return true if the combination of channel mask and virtualization mode is supported, false
      *    otherwise.
      * @throws IllegalStateException
      * @throws IllegalArgumentException
      * @throws UnsupportedOperationException
      */
-    public boolean getSpeakerAngles(int inputChannelMask, int deviceType, int[] angles)
+    public boolean getSpeakerAngles(int inputChannelMask,
+            @VirtualizationMode int virtualizationMode, int[] angles)
             throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
         if (angles == null) {
             throw (new IllegalArgumentException(
                     "Virtualizer: illegal null channel / angle array"));
         }
 
-        return getAnglesInt(inputChannelMask, deviceType, angles);
+        return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), angles);
     }
 
     /**
-     * Forces the virtualizer effect to use the processing mode used for the given device type.
+     * Forces the virtualizer effect to use the given processing mode.
      * The effect must be enabled for the forced mode to be applied.
-     * @param deviceType one of the device types defined in {@link AudioDevice}.
-     *     Use {@link AudioDevice#DEVICE_TYPE_UNKNOWN} to return to the non-forced mode.
-     * @return true if the processing mode for the device type is supported, and it is successfully
-     *     set, or forcing was successfully disabled with {@link AudioDevice#DEVICE_TYPE_UNKNOWN},
-     *     false otherwise.
+     * @param virtualizationMode one of {@link #VIRTUALIZATION_MODE_BINAURAL},
+     *     {@link #VIRTUALIZATION_MODE_TRANSAURAL} to force a particular processing mode, or
+     *     {@value #VIRTUALIZATION_MODE_AUTO} to stop forcing a mode.
+     * @return true if the processing mode is supported, and it is successfully set, or
+     *     forcing was successfully disabled, false otherwise.
      * @throws IllegalStateException
      * @throws IllegalArgumentException
      * @throws UnsupportedOperationException
      */
-    public boolean forceVirtualizationMode(int deviceType)
+    public boolean forceVirtualizationMode(@ForceVirtualizationMode int virtualizationMode)
             throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
         // convert Java device type to internal representation
+        int deviceType = getDeviceForModeForce(virtualizationMode);
         int internalDevice = AudioDevice.convertDeviceTypeToInternalDevice(deviceType);
 
         int status = setParameter(PARAM_FORCE_VIRTUALIZATION_MODE, internalDevice);
@@ -335,8 +440,8 @@
         if (status >= 0) {
             return true;
         } else if (status == AudioEffect.ERROR_BAD_VALUE) {
-            // a BAD_VALUE return from setParameter indicates the mode can't be forced to that
-            // of this device, don't throw an exception, just return false
+            // a BAD_VALUE return from setParameter indicates the mode can't be forced
+            // don't throw an exception, just return false
             return false;
         } else {
             // something wrong may have happened
@@ -349,31 +454,25 @@
     }
 
     /**
-     * Return the device type which reflects the virtualization mode being used, if any.
-     * @return a device type (as defined in {@link AudioDevice}) which reflects the virtualization
-     *     mode being used.
-     *     If virtualization is not active, the device type will be
-     *     {@link AudioDevice#DEVICE_TYPE_UNKNOWN}. Virtualization may not be active either because
-     *     the effect is not enabled or because the current output device is not compatible with
-     *     this virtualization implementation.
-     *     <p>Note that the return value may differ from a device type successfully set with
-     *     {@link #forceVirtualizationMode(int)} as the implementation
-     *     may use a single mode for multiple devices. An example of this is with
-     *     {@link AudioDevice#DEVICE_TYPE_WIRED_HEADSET} that would typically be handled
-     *     like {@link AudioDevice#DEVICE_TYPE_WIRED_HEADPHONES} from a virtualization
-     *     standpoint.
+     * Return the virtualization mode being used, if any.
+     * @return the virtualization mode being used.
+     *     If virtualization is not active, the virtualization mode will be
+     *     {@link #VIRTUALIZATION_MODE_OFF}. Otherwise the value will be
+     *     {@link #VIRTUALIZATION_MODE_BINAURAL} or {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+     *     Virtualization may not be active either because the effect is not enabled or
+     *     because the current output device is not compatible with this virtualization
+     *     implementation.
      * @throws IllegalStateException
-     * @throws IllegalArgumentException
      * @throws UnsupportedOperationException
      */
     public int getVirtualizationMode()
-            throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+            throws IllegalStateException, UnsupportedOperationException {
         int[] value = new int[1];
         int status = getParameter(PARAM_VIRTUALIZATION_MODE, value);
         if (status >= 0) {
-            return AudioDevice.convertInternalDeviceToDeviceType(value[0]);
+            return deviceToMode(AudioDevice.convertInternalDeviceToDeviceType(value[0]));
         } else if (status == AudioEffect.ERROR_BAD_VALUE) {
-            return AudioDevice.DEVICE_TYPE_UNKNOWN;
+            return VIRTUALIZATION_MODE_OFF;
         } else {
             // something wrong may have happened
             checkStatus(status);
@@ -381,7 +480,7 @@
         // unexpected virtualizer behavior
         Log.e(TAG, "unexpected status code " + status
                 + " after getParameter(PARAM_VIRTUALIZATION_MODE)");
-        return AudioDevice.DEVICE_TYPE_UNKNOWN;
+        return VIRTUALIZATION_MODE_OFF;
     }
 
     /**
diff --git a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index cfd5db3..0000000
--- a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index e3cb6db..0000000
--- a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index b9e30e2..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 8c8ec7a..0c85dab 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -36,7 +36,6 @@
 
     <FrameLayout
        android:id="@+id/keyguard_bouncer_frame"
-       android:background="@drawable/kg_bouncer_bg_white"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index 9e886f2..b7d5d30 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -42,7 +42,6 @@
     <!-- Password entry field -->
       <FrameLayout
          android:id="@+id/keyguard_bouncer_frame"
-         android:background="@drawable/kg_bouncer_bg_white"
          android:layout_height="wrap_content"
          android:layout_width="280dp"
          android:layout_gravity="center_horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index a126465..bd585b5 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -49,7 +49,6 @@
 
           <FrameLayout
              android:id="@+id/keyguard_bouncer_frame"
-             android:background="@drawable/kg_bouncer_bg_white"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index d3064ed..5330363 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -48,8 +48,7 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
-            android:background="@drawable/kg_bouncer_bg_white"/>
+            android:layout_marginRight="16dp"/>
 
         <include layout="@layout/keyguard_glow_pad_container" />
 
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index 2d20b02..d539856 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -152,6 +152,11 @@
         mKlondikeText.layout(left, top, left + mKlondikeText.getMeasuredWidth(), bottom);
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     // Cause a VIRTUAL_KEY vibration
     public void doHapticKeyClick() {
         if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index f3ba3a7..6497f46 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -145,6 +145,11 @@
         }
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     private Rect getCharBounds() {
         float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity;
         mDrawPaint.setTextSize(textHeight);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index ce0b9b6..b6c36c7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -442,7 +442,8 @@
                 * mPreviewPageMargin);
 
         final int verticalPadding;
-        if (mPageContentHeight + mFooterHeight + mPreviewListPadding > availableHeight) {
+        if (mPageContentHeight + mFooterHeight + mPreviewListPadding
+                + 2 * mPreviewPageMargin > availableHeight) {
             verticalPadding = Math.max(0,
                     (availableHeight - mPageContentHeight - mFooterHeight) / 2
                             - mPreviewPageMargin);
diff --git a/packages/SystemUI/res/layout/notification_public_default.xml b/packages/SystemUI/res/layout/notification_public_default.xml
new file mode 100644
index 0000000..acfc4bb
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_public_default.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    internal:layout_minHeight="64dp"
+    internal:layout_maxHeight="64dp"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_marginTop="12dp"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
+        android:scaleType="centerInside"
+        />
+    <DateTimeView android:id="@+id/time"
+        android:textAppearance="@android:style/TextAppearance.Material.Notification.Time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dp"
+        android:layout_alignParentEnd="true"
+        android:layout_alignBaseline="@id/title"
+        android:singleLine="true"
+        android:gravity="center"
+        android:paddingStart="8dp"
+        android:visibility="gone"
+        />
+    <TextView android:id="@+id/title"
+        android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_toEndOf="@id/icon"
+        android:layout_toStartOf="@id/time"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        />
+    <ImageView android:id="@+id/profile_badge_line3"
+        android:layout_width="@*android:dimen/notification_badge_size"
+        android:layout_height="@*android:dimen/notification_badge_size"
+        android:layout_below="@id/title"
+        android:layout_marginStart="4dp"
+        android:layout_marginEnd="8dp"
+        android:layout_alignParentEnd="true"
+        android:scaleType="fitCenter"
+        android:visibility="gone"
+        />
+    <TextView android:id="@+id/text"
+        android:textAppearance="@android:style/TextAppearance.Material.Notification"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignStart="@id/title"
+        android:layout_below="@id/title"
+        android:layout_toStartOf="@id/profile_badge_line3"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 5cdf819..2eb99ba 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -40,7 +40,6 @@
                 android:layout_height="wrap_content"
                 android:layout_marginEnd="8dp"
                 android:minWidth="132dp"
-                android:text="@string/quick_settings_more_settings"
                 android:textAppearance="@style/TextAppearance.QS.DetailButton"
                 android:focusable="true" />
 
@@ -50,9 +49,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:minWidth="88dp"
-                android:text="@string/quick_settings_done"
                 android:textAppearance="@style/TextAppearance.QS.DetailButton"
                 android:focusable="true"/>
 
     </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 6b829e5..e9d86d6 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -52,9 +52,10 @@
         android:paddingStart="8dp"
         />
 
-    <include
-        layout="@layout/notification_guts"
-        android:id="@+id/notification_guts"
+    <ViewStub
+        android:layout="@layout/notification_guts"
+        android:id="@+id/notification_guts_stub"
+        android:inflatedId="@+id/notification_guts"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 147efaf..0445fe8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -736,9 +736,6 @@
     <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
     <string name="camera_hint">Swipe left for camera</string>
 
-    <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_forever">Indefinitely</string>
-
     <!-- Interruption level: None. [CHAR LIMIT=20] -->
     <string name="interruption_level_none">None</string>
 
@@ -805,18 +802,6 @@
     <string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
 
 
-    <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
-    <plurals name="zen_mode_duration_minutes">
-        <item quantity="one">For one minute</item>
-        <item quantity="other">For %d minutes</item>
-    </plurals>
-
-    <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
-    <plurals name="zen_mode_duration_hours">
-        <item quantity="one">For one hour</item>
-        <item quantity="other">For %d hours</item>
-    </plurals>
-
     <!-- Battery saver notification title. [CHAR LIMIT=60]-->
     <string name="battery_saver_notification_title">Battery saver is on</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
index b86e67c..a9fdc86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
@@ -23,7 +23,6 @@
 import android.text.TextUtils.TruncateAt;
 import android.view.Gravity;
 import android.view.View;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -41,7 +40,7 @@
  *               truncate.
  *   Second line: ellipsis if necessary
  */
-public class QSDualTileLabel extends FrameLayout {
+public class QSDualTileLabel extends LinearLayout {
 
     private final Context mContext;
     private final TextView mFirstLine;
@@ -54,6 +53,7 @@
     public QSDualTileLabel(Context context) {
         super(context);
         mContext = context;
+        setOrientation(LinearLayout.VERTICAL);
 
         mHorizontalPaddingPx = mContext.getResources()
                 .getDimensionPixelSize(R.dimen.qs_dual_tile_padding_horizontal);
@@ -70,13 +70,13 @@
         mFirstLineCaret.setScaleType(ImageView.ScaleType.MATRIX);
         mFirstLineCaret.setClickable(false);
         firstLineLayout.addView(mFirstLineCaret);
-        addView(firstLineLayout, newFrameLayoutParams());
+        addView(firstLineLayout, newLinearLayoutParams());
 
         mSecondLine = initTextView();
         mSecondLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
         mSecondLine.setEllipsize(TruncateAt.END);
         mSecondLine.setVisibility(GONE);
-        addView(mSecondLine, newFrameLayoutParams());
+        addView(mSecondLine, newLinearLayoutParams());
 
         addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
@@ -89,7 +89,7 @@
         });
     }
 
-    private static LayoutParams newFrameLayoutParams() {
+    private static LayoutParams newLinearLayoutParams() {
         final LayoutParams lp =
                 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         lp.gravity = Gravity.CENTER_HORIZONTAL;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 6bfe0a4..2fafb2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -89,6 +89,7 @@
         mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
         mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
         mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
+        updateDetailText();
         mDetail.setVisibility(GONE);
         mDetail.setClickable(true);
         mBrightnessView = LayoutInflater.from(context).inflate(
@@ -112,6 +113,11 @@
         });
     }
 
+    private void updateDetailText() {
+        mDetailDoneButton.setText(R.string.quick_settings_done);
+        mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
+    }
+
     public void setBrightnessMirror(BrightnessMirrorController c) {
         super.onFinishInflate();
         ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
@@ -150,6 +156,7 @@
         if (mListening) {
             refreshAllTiles();
         }
+        updateDetailText();
     }
 
     @Override
@@ -525,6 +532,12 @@
     };
 
     private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() {
+        public void onAnimationCancel(Animator animation) {
+            // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get
+            // called, this will avoid accidentally turning off the grid when we don't want to.
+            animation.removeListener(this);
+        };
+
         @Override
         public void onAnimationEnd(Animator animation) {
             setGridContentVisibility(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4d85352..907a13f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -69,6 +69,7 @@
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewStub;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
@@ -764,17 +765,95 @@
         }, false /* afterKeyguardGone */);
     }
 
+    private void inflateGuts(ExpandableNotificationRow row) {
+        ViewStub stub = (ViewStub) row.findViewById(R.id.notification_guts_stub);
+        if (stub != null) {
+            stub.inflate();
+        }
+        final StatusBarNotification sbn = row.getStatusBarNotification();
+        PackageManager pmUser = getPackageManagerForUser(
+                sbn.getUser().getIdentifier());
+        row.setTag(sbn.getPackageName());
+        final View guts = row.findViewById(R.id.notification_guts);
+        final String pkg = sbn.getPackageName();
+        String appname = pkg;
+        Drawable pkgicon = null;
+        int appUid = -1;
+        try {
+            final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+                    PackageManager.GET_UNINSTALLED_PACKAGES
+                            | PackageManager.GET_DISABLED_COMPONENTS);
+            if (info != null) {
+                appname = String.valueOf(pmUser.getApplicationLabel(info));
+                pkgicon = pmUser.getApplicationIcon(info);
+                appUid = info.uid;
+            }
+        } catch (NameNotFoundException e) {
+            // app is gone, just show package name and generic icon
+            pkgicon = pmUser.getDefaultActivityIcon();
+        }
+        ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
+        ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(sbn.getPostTime());
+        ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
+        final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
+        final View appSettingsButton
+                = guts.findViewById(R.id.notification_inspect_app_provided_settings);
+        if (appUid >= 0) {
+            final int appUidF = appUid;
+            settingsButton.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    startAppNotificationSettingsActivity(pkg, appUidF);
+                }
+            });
+
+            final Intent appSettingsQueryIntent
+                    = new Intent(Intent.ACTION_MAIN)
+                    .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+                    .setPackage(pkg);
+            List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
+            if (infos.size() > 0) {
+                appSettingsButton.setVisibility(View.VISIBLE);
+                appSettingsButton.setContentDescription(
+                        mContext.getResources().getString(
+                                R.string.status_bar_notification_app_settings_title,
+                                appname
+                        ));
+                final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
+                        .setClassName(pkg, infos.get(0).activityInfo.name);
+                appSettingsButton.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
+                                sbn.getId(),
+                                sbn.getTag(),
+                                appUidF);
+                    }
+                });
+            } else {
+                appSettingsButton.setVisibility(View.GONE);
+            }
+        } else {
+            settingsButton.setVisibility(View.GONE);
+            appSettingsButton.setVisibility(View.GONE);
+        }
+
+    }
+
     protected SwipeHelper.LongPressListener getNotificationLongClicker() {
         return new SwipeHelper.LongPressListener() {
             @Override
             public boolean onLongPress(View v, int x, int y) {
                 dismissPopups();
 
+                if (!(v instanceof ExpandableNotificationRow)) {
+                    return false;
+                }
                 if (v.getWindowToken() == null) {
                     Log.e(TAG, "Trying to show notification guts, but not attached to window");
                     return false;
                 }
 
+                inflateGuts((ExpandableNotificationRow) v);
+
                 // Assume we are a status_bar_notification_row
                 final NotificationGuts guts = (NotificationGuts) v.findViewById(
                         R.id.notification_guts);
@@ -1190,67 +1269,6 @@
             row.setExpansionLogger(this, entry.notification.getKey());
         }
 
-        // the notification inspector (see SwipeHelper.setLongPressListener)
-        row.setTag(sbn.getPackageName());
-        final View guts = row.findViewById(R.id.notification_guts);
-        final String pkg = entry.notification.getPackageName();
-        String appname = pkg;
-        Drawable pkgicon = null;
-        int appUid = -1;
-        try {
-            final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
-                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
-            if (info != null) {
-                appname = String.valueOf(pmUser.getApplicationLabel(info));
-                pkgicon = pmUser.getApplicationIcon(info);
-                appUid = info.uid;
-            }
-        } catch (NameNotFoundException e) {
-            // app is gone, just show package name and generic icon
-            pkgicon = pmUser.getDefaultActivityIcon();
-        }
-        ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
-        ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime());
-        ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
-        final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
-        final View appSettingsButton
-                = guts.findViewById(R.id.notification_inspect_app_provided_settings);
-        if (appUid >= 0) {
-            final int appUidF = appUid;
-            settingsButton.setOnClickListener(new View.OnClickListener() {
-                public void onClick(View v) {
-                    startAppNotificationSettingsActivity(pkg, appUidF);
-                }
-            });
-
-            final Intent appSettingsQueryIntent
-                    = new Intent(Intent.ACTION_MAIN)
-                        .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
-                        .setPackage(pkg);
-            List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
-            if (infos.size() > 0) {
-                appSettingsButton.setVisibility(View.VISIBLE);
-                appSettingsButton.setContentDescription(
-                        mContext.getResources().getString(
-                                R.string.status_bar_notification_app_settings_title,
-                                appname
-                        ));
-                final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
-                        .setClassName(pkg, infos.get(0).activityInfo.name);
-                appSettingsButton.setOnClickListener(new View.OnClickListener() {
-                    public void onClick(View v) {
-                        startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
-                                sbn.getId(),
-                                sbn.getTag(),
-                                appUidF);
-                    }
-                });
-            }
-        } else {
-            settingsButton.setVisibility(View.GONE);
-            appSettingsButton.setVisibility(View.GONE);
-        }
-
         workAroundBadLayerDrawableOpacity(row);
         View vetoButton = updateNotificationVetoButton(row, sbn);
         vetoButton.setContentDescription(mContext.getString(
@@ -1331,12 +1349,12 @@
         if (publicViewLocal == null) {
             // Add a basic notification template
             publicViewLocal = LayoutInflater.from(mContext).inflate(
-                    com.android.internal.R.layout.notification_template_material_base,
+                    R.layout.notification_public_default,
                     expandedPublic, false);
             publicViewLocal.setIsRootNamespace(true);
             expandedPublic.setContractedChild(publicViewLocal);
 
-            final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
+            final TextView title = (TextView) publicViewLocal.findViewById(R.id.title);
             try {
                 title.setText(pmUser.getApplicationLabel(
                         pmUser.getApplicationInfo(entry.notification.getPackageName(), 0)));
@@ -1344,10 +1362,9 @@
                 title.setText(entry.notification.getPackageName());
             }
 
-            final ImageView icon = (ImageView) publicViewLocal.findViewById(
-                    com.android.internal.R.id.icon);
+            final ImageView icon = (ImageView) publicViewLocal.findViewById(R.id.icon);
             final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
-                    com.android.internal.R.id.profile_badge_line3);
+                    R.id.profile_badge_line3);
 
             final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
                     entry.notification.getUser(),
@@ -1383,16 +1400,13 @@
             }
 
             final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time);
+            final DateTimeView time = (DateTimeView) publicViewLocal.findViewById(R.id.time);
             if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) {
-                final View timeStub = publicViewLocal.findViewById(com.android.internal.R.id.time);
-                timeStub.setVisibility(View.VISIBLE);
-                final DateTimeView dateTimeView = (DateTimeView)
-                        publicViewLocal.findViewById(com.android.internal.R.id.time);
-                dateTimeView.setTime(entry.notification.getNotification().when);
+                time.setVisibility(View.VISIBLE);
+                time.setTime(entry.notification.getNotification().when);
             }
 
-            final TextView text = (TextView) publicViewLocal.findViewById(
-                com.android.internal.R.id.text);
+            final TextView text = (TextView) publicViewLocal.findViewById(R.id.text);
             if (text != null) {
                 text.setText(R.string.notification_hidden_text);
                 text.setTextAppearance(mContext,
@@ -1432,7 +1446,7 @@
             row.setUserExpanded(userExpanded);
         }
         row.setUserLocked(userLocked);
-
+        row.setStatusBarNotification(entry.notification);
         return true;
     }
 
@@ -1946,6 +1960,7 @@
         } else {
             entry.row.setOnClickListener(null);
         }
+        entry.row.setStatusBarNotification(notification);
         entry.row.notifyContentUpdated();
         entry.row.resetHeight();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index c13593a..2ad6859 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -20,9 +20,11 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
 
 import android.widget.ImageView;
@@ -67,6 +69,8 @@
     private boolean mWasReset;
     private NotificationGuts mGuts;
 
+    private StatusBarNotification mStatusBarNotification;
+
     public void setIconAnimationRunning(boolean running) {
         setIconAnimationRunning(running, mPublicLayout);
         setIconAnimationRunning(running, mPrivateLayout);
@@ -112,6 +116,14 @@
         }
     }
 
+    public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
+        mStatusBarNotification = statusBarNotification;
+    }
+
+    public StatusBarNotification getStatusBarNotification() {
+        return mStatusBarNotification;
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -155,7 +167,15 @@
         super.onFinishInflate();
         mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
         mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
-        mGuts = (NotificationGuts) findViewById(R.id.notification_guts);
+        ViewStub gutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
+        gutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+            @Override
+            public void onInflate(ViewStub stub, View inflated) {
+                mGuts = (NotificationGuts) inflated;
+                mGuts.setClipTopAmount(getClipTopAmount());
+                mGuts.setActualHeight(getActualHeight());
+            }
+        });
         mVetoButton = findViewById(R.id.veto);
     }
 
@@ -421,7 +441,9 @@
     public void setActualHeight(int height, boolean notifyListeners) {
         mPrivateLayout.setActualHeight(height);
         mPublicLayout.setActualHeight(height);
-        mGuts.setActualHeight(height);
+        if (mGuts != null) {
+            mGuts.setActualHeight(height);
+        }
         invalidate();
         super.setActualHeight(height, notifyListeners);
     }
@@ -443,7 +465,9 @@
         super.setClipTopAmount(clipTopAmount);
         mPrivateLayout.setClipTopAmount(clipTopAmount);
         mPublicLayout.setClipTopAmount(clipTopAmount);
-        mGuts.setClipTopAmount(clipTopAmount);
+        if (mGuts != null) {
+            mGuts.setClipTopAmount(clipTopAmount);
+        }
     }
 
     public void notifyContentUpdated() {
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 9585e17..902123d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -631,9 +631,10 @@
     }
 
     private boolean isInQsArea(float x, float y) {
-        return mStatusBarState != StatusBarState.SHADE
-                || y <= mNotificationStackScroller.getBottomMostNotificationBottom()
-                || y <= mQsContainer.getY() + mQsContainer.getHeight();
+        return mStatusBarState != StatusBarState.SHADE ||
+                (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
+                        (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+                                || y <= mQsContainer.getY() + mQsContainer.getHeight());
     }
 
     private void handleQsDown(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7261ea1..2f21781 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -684,7 +684,7 @@
                 removeCallbacks(mPeekRunnable);
                 mPeekRunnable.run();
             }
-        } else if (!isFullyCollapsed() && !mTracking) {
+        } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
             if (mHeightAnimator != null) {
                 mHeightAnimator.cancel();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 6949ffb..fa43f32 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -431,6 +431,9 @@
 
     public void onConfigurationChanged(Configuration newConfig) {
         updateWidth();
+        if (mZenPanel != null) {
+            mZenPanel.updateLocale();
+        }
     }
 
     private void updateWidth() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index ac7fc25..f829994 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -60,7 +60,7 @@
 
     private static final int[] MINUTE_BUCKETS = DEBUG
             ? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
-            : new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+            : ZenModeConfig.MINUTE_BUCKETS;
     private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
     private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
     private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@@ -68,7 +68,6 @@
     private static final int TIME_CONDITION_INDEX = 1;
     private static final int FIRST_CONDITION_INDEX = 2;
     private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
-    private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
 
     public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
 
@@ -121,10 +120,7 @@
         super.onFinishInflate();
 
         mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
-        mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
-        mZenButtons.addButton(R.string.interruption_level_priority,
-                Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-        mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+        addZenButtons();
         mZenButtons.setCallback(mZenButtonsCallback);
 
         mZenSubhead = findViewById(R.id.zen_subhead);
@@ -174,6 +170,13 @@
         setExpanded(false);
     }
 
+    private void addZenButtons() {
+        mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
+        mZenButtons.addButton(R.string.interruption_level_priority,
+                Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+    }
+
     public void setHidden(boolean hidden) {
         if (mHidden == hidden) return;
         mHidden = hidden;
@@ -213,7 +216,7 @@
                 mBucketIndex = -1;
             } else {
                 mBucketIndex = DEFAULT_BUCKET_INDEX;
-                mTimeCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+                mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
             }
             if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
             mConditions = null; // reset conditions
@@ -234,6 +237,11 @@
         mController.addCallback(mZenCallback);
     }
 
+    public void updateLocale() {
+        mZenButtons.removeAllViews();
+        addZenButtons();
+    }
+
     private void setExitCondition(Condition exitCondition) {
         if (sameConditionId(mExitCondition, exitCondition)) return;
         mExitCondition = exitCondition;
@@ -254,7 +262,7 @@
     }
 
     private void refreshExitConditionText() {
-        final String forever = mContext.getString(R.string.zen_mode_forever);
+        final String forever = mContext.getString(com.android.internal.R.string.zen_mode_forever);
         if (mExitCondition == null) {
             mExitConditionText = forever;
         } else if (ZenModeConfig.isValidCountdownConditionId(mExitCondition.id)) {
@@ -330,24 +338,7 @@
         if (time == 0) return null;
         final long span = time - System.currentTimeMillis();
         if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
-        return timeCondition(time, Math.round(span / (float)MINUTES_MS));
-    }
-
-    private Condition newTimeCondition(int minutesFromNow) {
-        final long now = System.currentTimeMillis();
-        final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
-        return timeCondition(now + millis, minutesFromNow);
-    }
-
-    private Condition timeCondition(long time, int minutes) {
-        final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
-        final int resId = minutes < 60
-                ? R.plurals.zen_mode_duration_minutes
-                : R.plurals.zen_mode_duration_hours;
-        final String caption = mContext.getResources().getQuantityString(resId, num, num);
-        final Uri id = ZenModeConfig.toCountdownConditionId(time);
-        return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
-                Condition.FLAG_RELEVANT_NOW);
+        return ZenModeConfig.toTimeCondition(time, Math.round(span / (float) MINUTES_MS));
     }
 
     private void handleUpdateConditions(Condition[] conditions) {
@@ -401,7 +392,7 @@
         if (favoriteIndex == -1) {
             getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
         } else {
-            mTimeCondition = newTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
+            mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
             mBucketIndex = favoriteIndex;
             bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
             getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
@@ -457,7 +448,7 @@
         });
         final TextView title = (TextView) row.findViewById(android.R.id.title);
         if (condition == null) {
-            title.setText(R.string.zen_mode_forever);
+            title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
         } else {
             title.setText(condition.summary);
         }
@@ -494,7 +485,7 @@
             } else {
                 final long span = time - System.currentTimeMillis();
                 button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
-                final Condition maxCondition = newTimeCondition(MAX_BUCKET_MINUTES);
+                final Condition maxCondition = ZenModeConfig.toTimeCondition(MAX_BUCKET_MINUTES);
                 button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
             }
 
@@ -520,18 +511,18 @@
                 final long bucketTime = now + bucketMinutes * MINUTES_MS;
                 if (up && bucketTime > time || !up && bucketTime < time) {
                     mBucketIndex = j;
-                    newCondition = timeCondition(bucketTime, bucketMinutes);
+                    newCondition = ZenModeConfig.toTimeCondition(bucketTime, bucketMinutes);
                     break;
                 }
             }
             if (newCondition == null) {
                 mBucketIndex = DEFAULT_BUCKET_INDEX;
-                newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+                newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
             }
         } else {
             // on a known index, simply increment or decrement
             mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
-            newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+            newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
         }
         mTimeCondition = newCondition;
         bind(mTimeCondition, row);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3062a92..75090db 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4746,6 +4746,11 @@
 
     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
         if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+        if (score < 0) {
+            loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
+                    ").  Bumping score to min of 0");
+            score = 0;
+        }
 
         nai.currentScore = score;
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index c8718e3e..060c8e3 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -106,6 +106,7 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 import android.widget.ArrayAdapter;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -3455,9 +3456,14 @@
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
                         final boolean isAuxiliary = "1".equals(String.valueOf(
                                 parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
-                        final InputMethodSubtype subtype =
-                                new InputMethodSubtype(label, icon, imeSubtypeLocale,
-                                        imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
+                        final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
+                                .setSubtypeNameResId(label)
+                                .setSubtypeIconResId(icon)
+                                .setSubtypeLocale(imeSubtypeLocale)
+                                .setSubtypeMode(imeSubtypeMode)
+                                .setSubtypeExtraValue(imeSubtypeExtraValue)
+                                .setIsAuxiliary(isAuxiliary)
+                                .build();
                         tempSubtypesArray.add(subtype);
                     }
                 }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index f6beb9a..9292d45 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.content;
 
+import android.Manifest;
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
 import android.accounts.AccountManager;
@@ -478,7 +479,7 @@
             mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
                     UserHandle.ALL,
                     new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
-                    null, null);
+                    Manifest.permission.ACCOUNT_MANAGER, null);
         }
 
         // Pick a random second in a day to seed all periodic syncs
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c8b5b3e..fefbe0a 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -33,6 +33,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
@@ -48,6 +49,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.service.trust.TrustAgentService;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -97,6 +99,7 @@
     private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
+    private final LockPatternUtils mLockPatternUtils;
 
     private UserManager mUserManager;
 
@@ -104,6 +107,7 @@
         super(context);
         mContext = context;
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mLockPatternUtils = new LockPatternUtils(context);
     }
 
     @Override
@@ -116,6 +120,7 @@
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
             mReceiver.register(mContext);
+            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
             refreshAgentList(UserHandle.USER_ALL);
         }
     }
@@ -159,6 +164,11 @@
 
     void refreshAgentList(int userId) {
         if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+            Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+                    + " must be USER_ALL or a specific user.", new Throwable("here"));
+            userId = UserHandle.USER_ALL;
+        }
         PackageManager pm = mContext.getPackageManager();
 
         List<UserInfo> userInfos;
@@ -168,12 +178,13 @@
             userInfos = new ArrayList<>();
             userInfos.add(mUserManager.getUserInfo(userId));
         }
-        LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+        LockPatternUtils lockPatternUtils = mLockPatternUtils;
 
         ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
         obsoleteAgents.addAll(mActiveAgents);
 
         for (UserInfo userInfo : userInfos) {
+            if (!userInfo.supportsSwitchTo()) continue;
             if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
                     == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
             if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
@@ -186,22 +197,11 @@
             if (enabledAgents == null) {
                 continue;
             }
-            List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
-                    PackageManager.GET_META_DATA, userInfo.id);
+            List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
             for (ResolveInfo resolveInfo : resolveInfos) {
-                if (resolveInfo.serviceInfo == null) continue;
-
-                String packageName = resolveInfo.serviceInfo.packageName;
-                if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
-                        != PackageManager.PERMISSION_GRANTED) {
-                    Log.w(TAG, "Skipping agent because package " + packageName
-                            + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
-                    continue;
-                }
-
                 ComponentName name = getComponentName(resolveInfo);
-                if (!enabledAgents.contains(name)) continue;
 
+                if (!enabledAgents.contains(name)) continue;
                 if (disableTrustAgents) {
                     List<String> features =
                             dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
@@ -228,11 +228,13 @@
         boolean trustMayHaveChanged = false;
         for (int i = 0; i < obsoleteAgents.size(); i++) {
             AgentInfo info = obsoleteAgents.valueAt(i);
-            if (info.agent.isManagingTrust()) {
-                trustMayHaveChanged = true;
+            if (userId == UserHandle.USER_ALL || userId == info.userId) {
+                if (info.agent.isManagingTrust()) {
+                    trustMayHaveChanged = true;
+                }
+                info.agent.unbind();
+                mActiveAgents.remove(info);
             }
-            info.agent.unbind();
-            mActiveAgents.remove(info);
         }
 
         if (trustMayHaveChanged) {
@@ -342,6 +344,54 @@
         return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
     }
 
+    private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
+        if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
+            return;
+        }
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
+        ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            ComponentName componentName = getComponentName(resolveInfo);
+            int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
+            if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
+                        + "is not a system package.");
+                continue;
+            }
+            discoveredAgents.add(componentName);
+        }
+
+        List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
+        if (previouslyEnabledAgents != null) {
+            discoveredAgents.addAll(previouslyEnabledAgents);
+        }
+        utils.setEnabledTrustAgents(discoveredAgents, userId);
+        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
+    }
+
+    private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
+        List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+                0 /* flags */, userId);
+        ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            if (resolveInfo.serviceInfo == null) continue;
+            if (resolveInfo.serviceInfo.applicationInfo == null) continue;
+            String packageName = resolveInfo.serviceInfo.packageName;
+            if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+                    != PackageManager.PERMISSION_GRANTED) {
+                ComponentName name = getComponentName(resolveInfo);
+                Log.w(TAG, "Skipping agent " + name + " because package does not have"
+                        + " permission " + PERMISSION_PROVIDE_AGENT + ".");
+                continue;
+            }
+            allowedAgents.add(resolveInfo);
+        }
+        return allowedAgents;
+    }
+
     // Agent dispatch and aggregation
 
     private boolean aggregateIsTrusted(int userId) {
@@ -414,6 +464,7 @@
             }
         }
         mTrustListeners.add(listener);
+        updateTrustAll();
     }
 
     private void removeListener(ITrustListener listener) {
@@ -616,12 +667,19 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
-                    intent.getAction())) {
+            String action = intent.getAction();
+            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
                 refreshAgentList(getSendingUserId());
                 updateDevicePolicyFeatures();
-            } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                 updateUserHasAuthenticated(getSendingUserId());
+            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
+                if (userId > 0) {
+                    maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
+                } else {
+                    Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
+                }
             }
         }
 
@@ -629,6 +687,7 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
             filter.addAction(Intent.ACTION_USER_PRESENT);
+            filter.addAction(Intent.ACTION_USER_ADDED);
             context.registerReceiverAsUser(this,
                     UserHandle.ALL,
                     filter,
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 348c36c..8b8e8eb 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -60,13 +60,14 @@
             if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
                 mPendingConnections.remove(connection);
                 // Unconditionally initialize the connection ...
-                connection.setState(parcel.getState());
                 connection.setCallCapabilities(parcel.getCapabilities());
                 connection.setHandle(
                         parcel.getHandle(), parcel.getHandlePresentation());
                 connection.setCallerDisplayName(
                         parcel.getCallerDisplayName(),
                         parcel.getCallerDisplayNamePresentation());
+                // Set state after handle so that the client can identify the connection.
+                connection.setState(parcel.getState());
                 List<RemoteConnection> conferenceable = new ArrayList<>();
                 for (String confId : parcel.getConferenceableConnectionIds()) {
                     if (mConnectionById.containsKey(confId)) {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 65c00bd..aaa2f98 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -76,6 +76,8 @@
     public static final int REASON_INVALID_LISTENER = -2;
     /** Invalid request */
     public static final int REASON_INVALID_REQUEST = -3;
+    /** Invalid request */
+    public static final int REASON_NOT_AUTHORIZED = -4;
 
     /** @hide */
     public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";