Merge "QS: Repoint Wifi + BT dual tile labels to settings." into lmp-dev
diff --git a/Android.mk b/Android.mk
index 80b860b..6280332 100644
--- a/Android.mk
+++ b/Android.mk
@@ -156,6 +156,7 @@
 	core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl \
+	core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiRecordListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7bc30fd..547ec6c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -222,6 +222,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/inputflinger $(PRODUCT_OUT)/symbols/system/bin/inputflinger)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RsFountainFbo_intermediates)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index de3723c..9c97cc9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1028,6 +1028,8 @@
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
+    field public static final int reparent = 16843965; // 0x10104bd
+    field public static final int reparentWithOverlay = 16843966; // 0x10104be
     field public static final int repeatCount = 16843199; // 0x10101bf
     field public static final int repeatMode = 16843200; // 0x10101c0
     field public static final int reqFiveWayNav = 16843314; // 0x1010232
@@ -1445,6 +1447,7 @@
     field public static final int windowSharedElementExitTransition = 16843834; // 0x101043a
     field public static final int windowSharedElementReenterTransition = 16843954; // 0x10104b2
     field public static final int windowSharedElementReturnTransition = 16843953; // 0x10104b1
+    field public static final int windowSharedElementsUseOverlay = 16843964; // 0x10104bc
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -12978,7 +12981,7 @@
   }
 
   public class CaptureFailure {
-    method public int getFrameNumber();
+    method public long getFrameNumber();
     method public int getReason();
     method public android.hardware.camera2.CaptureRequest getRequest();
     method public int getSequenceId();
@@ -13571,7 +13574,7 @@
     method public void onStartInput(android.view.inputmethod.EditorInfo, boolean);
     method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
     method public void onUnbindInput();
-    method public void onUpdateCursor(android.graphics.Rect);
+    method public deprecated void onUpdateCursor(android.graphics.Rect);
     method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
     method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
@@ -17212,12 +17215,12 @@
   }
 
   public class Network implements android.os.Parcelable {
+    method public void bindSocket(java.net.Socket) throws java.io.IOException;
     method public int describeContents();
     method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
-    method public java.net.URL getBoundURL(java.net.URL) throws java.net.MalformedURLException;
     method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
     method public javax.net.SocketFactory getSocketFactory();
-    method public static void setNetworkBoundURLFactory(android.net.NetworkBoundURLFactory);
+    method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -31802,7 +31805,7 @@
     ctor public ChangeBounds(android.content.Context, android.util.AttributeSet);
     method public void captureEndValues(android.transition.TransitionValues);
     method public void captureStartValues(android.transition.TransitionValues);
-    method public void setReparent(boolean);
+    method public deprecated void setReparent(boolean);
     method public void setResizeClip(boolean);
   }
 
@@ -31825,6 +31828,10 @@
     ctor public ChangeTransform(android.content.Context, android.util.AttributeSet);
     method public void captureEndValues(android.transition.TransitionValues);
     method public void captureStartValues(android.transition.TransitionValues);
+    method public boolean getReparent();
+    method public boolean getReparentWithOverlay();
+    method public void setReparent(boolean);
+    method public void setReparentWithOverlay(boolean);
   }
 
   public class CircularPropagation extends android.transition.VisibilityPropagation {
@@ -35137,6 +35144,7 @@
     method public android.transition.Transition getSharedElementExitTransition();
     method public android.transition.Transition getSharedElementReenterTransition();
     method public android.transition.Transition getSharedElementReturnTransition();
+    method public boolean getSharedElementsUseOverlay();
     method public abstract int getStatusBarColor();
     method public long getTransitionBackgroundFadeDuration();
     method public android.transition.TransitionManager getTransitionManager();
@@ -35198,6 +35206,7 @@
     method public void setSharedElementExitTransition(android.transition.Transition);
     method public void setSharedElementReenterTransition(android.transition.Transition);
     method public void setSharedElementReturnTransition(android.transition.Transition);
+    method public void setSharedElementsUseOverlay(boolean);
     method public void setSoftInputMode(int);
     method public abstract void setStatusBarColor(int);
     method public abstract void setTitle(java.lang.CharSequence);
@@ -36178,7 +36187,7 @@
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public static final void removeComposingSpans(android.text.Spannable);
     method public boolean reportFullscreenMode(boolean);
-    method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+    method public boolean requestUpdateCursorAnchorInfo(int);
     method public boolean sendKeyEvent(android.view.KeyEvent);
     method public boolean setComposingRegion(int, int);
     method public static void setComposingSpans(android.text.Spannable);
@@ -36244,25 +36253,6 @@
     method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
   }
 
-  public final class CursorAnchorInfoRequest implements android.os.Parcelable {
-    ctor public CursorAnchorInfoRequest(int, int);
-    ctor public CursorAnchorInfoRequest(android.os.Parcel);
-    method public int describeContents();
-    method public int getRequestFlags();
-    method public int getRequestType();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; // 0x2
-    field public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; // 0x1
-    field public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; // 0x2
-    field public static final int FLAG_CURSOR_RECT_MONITOR = 1; // 0x1
-    field public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; // 0x4
-    field public static final int RESULT_NOT_HANDLED = 0; // 0x0
-    field public static final int RESULT_SCHEDULED = 1; // 0x1
-    field public static final int TYPE_CURSOR_ANCHOR_INFO = 1; // 0x1
-    field public static final int TYPE_CURSOR_RECT = 2; // 0x2
-  }
-
   public class EditorInfo implements android.text.InputType android.os.Parcelable {
     ctor public EditorInfo();
     method public int describeContents();
@@ -36360,13 +36350,15 @@
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract boolean reportFullscreenMode(boolean);
-    method public abstract int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+    method public abstract boolean requestUpdateCursorAnchorInfo(int);
     method public abstract boolean sendKeyEvent(android.view.KeyEvent);
     method public abstract boolean setComposingRegion(int, int);
     method public abstract boolean setComposingText(java.lang.CharSequence, int);
     method public abstract boolean setSelection(int, int);
     field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
     field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+    field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1; // 0x1
+    field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 2; // 0x2
   }
 
   public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -36388,7 +36380,7 @@
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public boolean reportFullscreenMode(boolean);
-    method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+    method public boolean requestUpdateCursorAnchorInfo(int);
     method public boolean sendKeyEvent(android.view.KeyEvent);
     method public boolean setComposingRegion(int, int);
     method public boolean setComposingText(java.lang.CharSequence, int);
@@ -36454,7 +36446,7 @@
     method public boolean isActive(android.view.View);
     method public boolean isActive();
     method public boolean isFullscreenMode();
-    method public boolean isWatchingCursor(android.view.View);
+    method public deprecated boolean isWatchingCursor(android.view.View);
     method public void restartInput(android.view.View);
     method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
     method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
@@ -36472,7 +36464,7 @@
     method public boolean switchToNextInputMethod(android.os.IBinder, boolean);
     method public void toggleSoftInput(int, int);
     method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
-    method public void updateCursor(android.view.View, int, int, int, int);
+    method public deprecated void updateCursor(android.view.View, int, int, int, int);
     method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo);
     method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(android.view.View, int, int, int, int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f5ac5f7..ffcdcf7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5021,6 +5021,9 @@
                 }
             }
         }
+        if (mActionBar != null) {
+            mActionBar.setTitle(title);
+        }
     }
 
     protected void onChildTitleChanged(Activity childActivity, CharSequence title) {
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 7d2f677..e4f2b88 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -665,6 +665,9 @@
     }
 
     protected void moveSharedElementsToOverlay() {
+        if (!mWindow.getSharedElementsUseOverlay()) {
+            return;
+        }
         int numSharedElements = mSharedElements.size();
         ViewGroup decor = getDecor();
         if (decor != null) {
@@ -700,6 +703,17 @@
     }
 
     protected void moveSharedElementsFromOverlay() {
+        int numListeners = mGhostViewListeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            GhostViewListeners listener = mGhostViewListeners.get(i);
+            ViewGroup parent = (ViewGroup) listener.getView().getParent();
+            parent.getViewTreeObserver().removeOnPreDrawListener(listener);
+        }
+        mGhostViewListeners.clear();
+
+        if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
+            return;
+        }
         ViewGroup decor = getDecor();
         if (decor != null) {
             ViewGroupOverlay overlay = decor.getOverlay();
@@ -709,13 +723,6 @@
                 GhostView.removeGhost(sharedElement);
             }
         }
-        int numListeners = mGhostViewListeners.size();
-        for (int i = 0; i < numListeners; i++) {
-            GhostViewListeners listener = mGhostViewListeners.get(i);
-            ViewGroup parent = (ViewGroup) listener.getView().getParent();
-            parent.getViewTreeObserver().removeOnPreDrawListener(listener);
-        }
-        mGhostViewListeners.clear();
     }
 
     protected void setGhostVisibility(int visibility) {
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 936e205..b7af544 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -434,6 +434,12 @@
          * @return The job object to hand to the JobScheduler. This object is immutable.
          */
         public JobInfo build() {
+            // Allow tasks with no constraints. What am I, a database?
+            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
+                    !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) {
+                throw new IllegalArgumentException("You're trying to build a job with no " +
+                        "constraints, this is not allowed.");
+            }
             mExtras = new PersistableBundle(mExtras);  // Make our own copy.
             // Check that a deadline was not set on a periodic job.
             if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 7fe192c..ca7022d 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -22,7 +22,13 @@
 
 /**
  * Class for scheduling various types of jobs with the scheduling framework on the device.
- *
+ * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
+ * and how to construct them.
+ * The framework will be intelligent about when you receive your callbacks, and attempt to batch
+ * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
+ * can be run at any moment depending on the current state of the JobScheduler's internal queue,
+ * however it might be deferred as long as until the next time the device is connected to a power
+ * source.
  * <p>You do not
  * instantiate this class directly; instead, retrieve it through
  * {@link android.content.Context#getSystemService
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index a83bd4a..d19418b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1470,6 +1470,12 @@
             case 320:
                 parts.add("xhdpi");
                 break;
+            case 480:
+                parts.add("xxhdpi");
+                break;
+            case 640:
+                parts.add("xxxhdpi");
+                break;
             default:
                 parts.add(config.densityDpi + "dpi");
                 break;
@@ -1542,7 +1548,7 @@
                 break;
         }
 
-        parts.add("v" + Build.VERSION.SDK_INT);
+        parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
         return TextUtils.join("-", parts);
     }
 }
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
index 2c505e5..b6d3b08 100644
--- a/core/java/android/hardware/camera2/CaptureFailure.java
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -47,13 +47,13 @@
     private final int mReason;
     private final boolean mDropped;
     private final int mSequenceId;
-    private final int mFrameNumber;
+    private final long mFrameNumber;
 
     /**
      * @hide
      */
     public CaptureFailure(CaptureRequest request, int reason, boolean dropped, int sequenceId,
-            int frameNumber) {
+            long frameNumber) {
         mRequest = request;
         mReason = reason;
         mDropped = dropped;
@@ -95,9 +95,9 @@
      * for every new result or failure; and the scope is the lifetime of the
      * {@link CameraDevice}.</p>
      *
-     * @return int frame number
+     * @return long frame number
      */
-    public int getFrameNumber() {
+    public long getFrameNumber() {
         return mFrameNumber;
     }
 
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index a15028c..621968b 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -68,6 +68,8 @@
 
     /** This session is closed; all further calls will throw ISE */
     private boolean mClosed = false;
+    /** This session failed to be configured successfully */
+    private final boolean mConfigureSuccess;
     /** Do not unconfigure if this is set; another session will overwrite configuration */
     private boolean mSkipUnconfigure = false;
 
@@ -119,10 +121,12 @@
         if (configureSuccess) {
             mStateListener.onConfigured(this);
             if (VERBOSE) Log.v(TAG, "ctor - Created session successfully");
+            mConfigureSuccess = true;
         } else {
             mStateListener.onConfigureFailed(this);
             mClosed = true; // do not fire any other callbacks, do not allow any other work
             Log.e(TAG, "Failed to create capture session; configuration failed");
+            mConfigureSuccess = false;
         }
     }
 
@@ -285,9 +289,9 @@
         // - This session is active, so close() below starts the shutdown drain
         // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
         // - This session is already closed and has executed the idle drain listener, and
-        //   configureOutputs(null) has already been called.
+        //   configureOutputsChecked(null) has already been called.
         //
-        // Do not call configureOutputs(null) going forward, since it would race with the
+        // Do not call configureOutputsChecked(null) going forward, since it would race with the
         // configuration for the new session. If it was already called, then we don't care, since it
         // won't get called again.
         mSkipUnconfigure = true;
@@ -506,7 +510,7 @@
             public void onUnconfigured(CameraDevice camera) {
                 synchronized (session) {
                     // Ignore #onUnconfigured before #close is called
-                    if (mClosed) {
+                    if (mClosed && mConfigureSuccess) {
                         mUnconfigureDrainer.taskFinished();
                     }
                 }
@@ -619,7 +623,7 @@
 
                 try {
                     mUnconfigureDrainer.taskStarted();
-                    mDeviceImpl.configureOutputs(null); // begin transition to unconfigured state
+                    mDeviceImpl.configureOutputsChecked(null); // begin transition to unconfigured
                 } catch (CameraAccessException e) {
                     // OK: do not throw checked exceptions.
                     Log.e(TAG, "Exception while configuring outputs: ", e);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 71eb0e9..79ce9df 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -312,10 +312,33 @@
     }
 
     public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
+        // Leave this here for backwards compatibility with older code using this directly
+        configureOutputsChecked(outputs);
+    }
+
+    /**
+     * Attempt to configure the outputs; the device goes to idle and then configures the
+     * new outputs if possible.
+     *
+     * <p>The configuration may gracefully fail, if there are too many outputs, if the formats
+     * are not supported, or if the sizes for that format is not supported. In this case this
+     * function will return {@code false} and the unconfigured callback will be fired.</p>
+     *
+     * <p>If the configuration succeeds (with 1 or more outputs), then the idle callback is fired.
+     * Unconfiguring the device always fires the idle callback.</p>
+     *
+     * @param outputs a list of one or more surfaces, or {@code null} to unconfigure
+     * @return whether or not the configuration was successful
+     *
+     * @throws CameraAccessException if there were any unexpected problems during configuration
+     */
+    public boolean configureOutputsChecked(List<Surface> outputs) throws CameraAccessException {
         // Treat a null input the same an empty list
         if (outputs == null) {
             outputs = new ArrayList<Surface>();
         }
+        boolean success = false;
+
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
 
@@ -355,7 +378,17 @@
                     mConfiguredOutputs.put(streamId, s);
                 }
 
-                mRemoteDevice.endConfigure();
+                try {
+                    mRemoteDevice.endConfigure();
+                }
+                catch (IllegalArgumentException e) {
+                    // OK. camera service can reject stream config if it's not supported by HAL
+                    // This is only the result of a programmer misusing the camera2 api.
+                    Log.e(TAG, "Stream configuration failed", e);
+                    return false;
+                }
+
+                success = true;
             } catch (CameraRuntimeException e) {
                 if (e.getReason() == CAMERA_IN_USE) {
                     throw new IllegalStateException("The camera is currently busy." +
@@ -365,15 +398,18 @@
                 throw e.asChecked();
             } catch (RemoteException e) {
                 // impossible
-                return;
-            }
-
-            if (outputs.size() > 0) {
-                mDeviceHandler.post(mCallOnIdle);
-            } else {
-                mDeviceHandler.post(mCallOnUnconfigured);
+                return false;
+            } finally {
+                if (success && outputs.size() > 0) {
+                    mDeviceHandler.post(mCallOnIdle);
+                } else {
+                    // Always return to the 'unconfigured' state if we didn't hit a fatal error
+                    mDeviceHandler.post(mCallOnUnconfigured);
+                }
             }
         }
+
+        return success;
     }
 
     @Override
@@ -397,7 +433,7 @@
             boolean configureSuccess = true;
             CameraAccessException pendingException = null;
             try {
-                configureOutputs(outputs); // and then block until IDLE
+                configureSuccess = configureOutputsChecked(outputs); // and then block until IDLE
             } catch (CameraAccessException e) {
                 configureSuccess = false;
                 pendingException = e;
diff --git a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
index b4289db2..1e1c4b1 100644
--- a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
+++ b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
@@ -225,7 +225,18 @@
         }
         if (obj instanceof ColorSpaceTransform) {
             final ColorSpaceTransform other = (ColorSpaceTransform) obj;
-            return Arrays.equals(mElements, other.mElements);
+            for (int i = 0, j = 0; i < COUNT; ++i, j += RATIONAL_SIZE) {
+                int numerator = mElements[j + OFFSET_NUMERATOR];
+                int denominator = mElements[j + OFFSET_DENOMINATOR];
+                int numeratorOther = other.mElements[j + OFFSET_NUMERATOR];
+                int denominatorOther = other.mElements[j + OFFSET_DENOMINATOR];
+                Rational r = new Rational(numerator, denominator);
+                Rational rOther = new Rational(numeratorOther, denominatorOther);
+                if (!r.equals(rOther)) {
+                    return false;
+                }
+            }
+            return true;
         }
         return false;
     }
@@ -238,5 +249,51 @@
         return HashCodeHelpers.hashCode(mElements);
     }
 
+    /**
+     * Return the color space transform as a string representation.
+     *
+     *  <p> Example:
+     * {@code "ColorSpaceTransform([1/1, 0/1, 0/1], [0/1, 1/1, 0/1], [0/1, 0/1, 1/1])"} is an
+     * identity transform. Elements are printed in row major order. </p>
+     *
+     * @return string representation of color space transform
+     */
+    @Override
+    public String toString() {
+        return String.format("ColorSpaceTransform%s", toShortString());
+    }
+
+    /**
+     * Return the color space transform as a compact string representation.
+     *
+     *  <p> Example:
+     * {@code "([1/1, 0/1, 0/1], [0/1, 1/1, 0/1], [0/1, 0/1, 1/1])"} is an identity transform.
+     * Elements are printed in row major order. </p>
+     *
+     * @return compact string representation of color space transform
+     */
+    private String toShortString() {
+        StringBuilder sb = new StringBuilder("(");
+        for (int row = 0, i = 0; row < ROWS; row++) {
+            sb.append("[");
+            for (int col = 0; col < COLUMNS; col++, i += RATIONAL_SIZE) {
+                int numerator = mElements[i + OFFSET_NUMERATOR];
+                int denominator = mElements[i + OFFSET_DENOMINATOR];
+                sb.append(numerator);
+                sb.append("/");
+                sb.append(denominator);
+                if (col < COLUMNS - 1) {
+                    sb.append(", ");
+                }
+            }
+            sb.append("]");
+            if (row < ROWS - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
     private final int[] mElements;
-};
+}
diff --git a/core/java/android/hardware/camera2/params/RggbChannelVector.java b/core/java/android/hardware/camera2/params/RggbChannelVector.java
index cf3e1de..e08ec55d 100644
--- a/core/java/android/hardware/camera2/params/RggbChannelVector.java
+++ b/core/java/android/hardware/camera2/params/RggbChannelVector.java
@@ -190,6 +190,32 @@
                 Float.floatToIntBits(mBlue);
     }
 
+    /**
+     * Return the RggbChannelVector as a string representation.
+     *
+     * <p> {@code "RggbChannelVector{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each
+     * {@code %f} respectively represents one of the the four color channels. </p>
+     *
+     * @return string representation of {@link RggbChannelVector}
+     */
+    @Override
+    public String toString() {
+        return String.format("RggbChannelVector%s", toShortString());
+    }
+
+    /**
+     * Return the RggbChannelVector as a string in compact form.
+     *
+     * <p> {@code "{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each {@code %f}
+     * respectively represents one of the the four color channels. </p>
+     *
+     * @return compact string representation of {@link RggbChannelVector}
+     */
+    private String toShortString() {
+        return String.format("{R:%f, G_even:%f, G_odd:%f, B:%f}",
+                mRed, mGreenEven, mGreenOdd, mBlue);
+    }
+
     private final float mRed;
     private final float mGreenEven;
     private final float mGreenOdd;
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index f95ed0f..aba90e47 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -50,7 +50,7 @@
         try {
             mService.sendKeyEvent(getDeviceType(), keyCode, isPressed);
         } catch (RemoteException e) {
-            Log.e(TAG, "queryDisplayStatus threw exception ", e);
+            Log.e(TAG, "sendKeyEvent threw exception ", e);
         }
     }
 
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 354c05e..c37fb5b 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -35,6 +35,11 @@
 public final class HdmiTvClient extends HdmiClient {
     private static final String TAG = "HdmiTvClient";
 
+    /**
+     * Size of MHL scratchpad register.
+     */
+    public static final int SCRATCHPAD_DATA_SIZE = 16;
+
     HdmiTvClient(IHdmiControlService service) {
         super(service);
     }
@@ -80,6 +85,15 @@
         }
     }
 
+    private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
+        return new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                callback.onComplete(result);
+            }
+        };
+    }
+
     /**
      * Select a HDMI port to be a new route path.
      *
@@ -126,6 +140,15 @@
         }
     }
 
+    private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) {
+        return new IHdmiInputChangeListener.Stub() {
+            @Override
+            public void onChanged(HdmiDeviceInfo info) {
+                listener.onChanged(info);
+            }
+        };
+    }
+
     /**
      * Set system audio volume
      *
@@ -170,6 +193,38 @@
         }
     }
 
+    private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) {
+        return new IHdmiRecordListener.Stub() {
+            @Override
+            public byte[] getOneTouchRecordSource(int recorderAddress) {
+                HdmiRecordSources.RecordSource source =
+                        callback.getOneTouchRecordSource(recorderAddress);
+                if (source == null) {
+                    return EmptyArray.BYTE;
+                }
+                byte[] data = new byte[source.getDataSize(true)];
+                source.toByteArray(true, data, 0);
+                return data;
+            }
+
+            @Override
+            public void onOneTouchRecordResult(int result) {
+                callback.onOneTouchRecordResult(result);
+            }
+
+            @Override
+            public void onTimerRecordingResult(int result) {
+                callback.onTimerRecordingResult(
+                        HdmiRecordListener.TimerStatusData.parseFrom(result));
+            }
+
+            @Override
+            public void onClearTimerRecordingResult(int result) {
+                callback.onClearTimerRecordingResult(result);
+            }
+        };
+    }
+
     /**
      * Start one touch recording with the given recorder address and recorder source.
      * <p>
@@ -276,53 +331,63 @@
         }
     }
 
-    private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
-        return new IHdmiControlCallback.Stub() {
+    /**
+     * Interface used to get incoming MHL scratchpad command.
+     */
+    public interface HdmiMhlScratchpadCommandListener {
+        void onReceived(int portId, int offset, int length, byte[] data);
+    }
+
+    /**
+     * Set {@link HdmiMhlScratchpadCommandListener} to get incoming MHL sSratchpad command.
+     *
+     * @param listener to receive incoming MHL Scratchpad command
+     */
+    public void setHdmiMhlScratchpadCommandListener(HdmiMhlScratchpadCommandListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null.");
+        }
+        try {
+            mService.addHdmiMhlScratchpadCommandListener(getListenerWrapper(listener));
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to set hdmi mhl scratchpad command listener: ", e);
+        }
+    }
+
+    private IHdmiMhlScratchpadCommandListener getListenerWrapper(
+            final HdmiMhlScratchpadCommandListener listener) {
+        return new IHdmiMhlScratchpadCommandListener.Stub() {
             @Override
-            public void onComplete(int result) {
-                callback.onComplete(result);
+            public void onReceived(int portId, int offset, int length, byte[] data) {
+                listener.onReceived(portId, offset, length, data);
             }
         };
     }
 
-    private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) {
-        return new IHdmiInputChangeListener.Stub() {
-            @Override
-            public void onChanged(HdmiDeviceInfo info) {
-                listener.onChanged(info);
-            }
-        };
-    }
+    /**
+     * Send MHL Scratchpad command to the device connected to a port of the given portId.
+     *
+     * @param portId id of port to send MHL Scratchpad command
+     * @param offset offset in the in given data
+     * @param length length of data. offset + length should be bound to length of data.
+     * @param data container for Scratchpad data. It should be 16 bytes.
+     * @throws IllegalArgumentException if the given parameters are invalid
+     */
+    public void sendScratchpadCommand(int portId, int offset, int length, byte[] data) {
+        if (data == null || data.length != SCRATCHPAD_DATA_SIZE) {
+            throw new IllegalArgumentException("Invalid scratchpad data.");
+        }
+        if (offset < 0 || offset >= SCRATCHPAD_DATA_SIZE) {
+            throw new IllegalArgumentException("Invalid offset:" + offset);
+        }
+        if (length < 0 || offset + length > SCRATCHPAD_DATA_SIZE) {
+            throw new IllegalArgumentException("Invalid length:" + length);
+        }
 
-    private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) {
-        return new IHdmiRecordListener.Stub() {
-            @Override
-            public byte[] getOneTouchRecordSource(int recorderAddress) {
-                HdmiRecordSources.RecordSource source =
-                        callback.getOneTouchRecordSource(recorderAddress);
-                if (source == null) {
-                    return EmptyArray.BYTE;
-                }
-                byte[] data = new byte[source.getDataSize(true)];
-                source.toByteArray(true, data, 0);
-                return data;
-            }
-
-            @Override
-            public void onOneTouchRecordResult(int result) {
-                callback.onOneTouchRecordResult(result);
-            }
-
-            @Override
-            public void onTimerRecordingResult(int result) {
-                callback.onTimerRecordingResult(
-                        HdmiRecordListener.TimerStatusData.parseFrom(result));
-            }
-
-            @Override
-            public void onClearTimerRecordingResult(int result) {
-                callback.onClearTimerRecordingResult(result);
-            }
-        };
+        try {
+            mService.sendScratchpadCommand(portId, offset, length, data);
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to send scratchpad command: ", e);
+        }
     }
 }
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 17f290b..3bd45ed 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -22,6 +22,7 @@
 import android.hardware.hdmi.IHdmiDeviceEventListener;
 import android.hardware.hdmi.IHdmiHotplugEventListener;
 import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener;
 import android.hardware.hdmi.IHdmiRecordListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
 import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -66,4 +67,6 @@
     void stopOneTouchRecord(int recorderAddress);
     void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
     void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
+    void sendScratchpadCommand(int portId, int offset, int length, in byte[] data);
+    void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener);
 }
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
similarity index 69%
rename from core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
rename to core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
index 41ef7cc6..4176597 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
@@ -14,6 +14,14 @@
  * limitations under the License.
  */
 
-package android.view.inputmethod;
+package android.hardware.hdmi;
 
-parcelable CursorAnchorInfoRequest;
+ /**
+ * Callback interface definition for MHL client to get the scratchpad
+ * command.
+ *
+ * @hide
+ */
+ oneway interface IHdmiMhlScratchpadCommandListener {
+      void onReceived(int portId, int offset, int length, in byte[] data);
+ }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ba811b7..2eb42a7 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -53,7 +53,6 @@
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CursorAnchorInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -1711,13 +1710,12 @@
     }
 
     /**
-     * Called when the application has reported a new location of its text cursor.  This is only
-     * called if explicitly requested by the input method.  The default implementation does nothing.
-     * @param newCursor The new cursor position, in screen coordinates if the input method calls
-     * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
-     * {@link CursorAnchorInfoRequest#FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. Otherwise,
-     * this is in local coordinates.
+     * Called when the application has reported a new location of its text
+     * cursor.  This is only called if explicitly requested by the input method.
+     * The default implementation does nothing.
+     * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead.
      */
+    @Deprecated
     public void onUpdateCursor(Rect newCursor) {
         // Intentionally empty
     }
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 0de3f26..d2a4728 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -16,10 +16,10 @@
 
 package android.net;
 
-import android.net.NetworkBoundURLFactory;
 import android.net.NetworkUtils;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.system.ErrnoException;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -30,6 +30,7 @@
 import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.net.URL;
+import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.net.SocketFactory;
@@ -54,7 +55,7 @@
     public final int netId;
 
     // Objects used to perform per-network operations such as getSocketFactory
-    // and getBoundURL, and a lock to protect access to them.
+    // and openConnection, and a lock to protect access to them.
     private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
     private volatile OkHttpClient mOkHttpClient = null;
     private Object mLock = new Object();
@@ -157,12 +158,7 @@
         @Override
         public Socket createSocket() throws IOException {
             Socket socket = new Socket();
-            // Query a property of the underlying socket to ensure the underlying
-            // socket exists so a file descriptor is available to bind to a network.
-            socket.getReuseAddress();
-            if (!NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId)) {
-                throw new SocketException("Failed to bind socket to network.");
-            }
+            bindSocket(socket);
             return socket;
         }
     }
@@ -187,73 +183,63 @@
         return mNetworkBoundSocketFactory;
     }
 
-    /** The default NetworkBoundURLFactory, used if setNetworkBoundURLFactory is never called. */
-    private static final NetworkBoundURLFactory DEFAULT_URL_FACTORY = new NetworkBoundURLFactory() {
-        public URL getBoundURL(final Network network, URL url) throws MalformedURLException {
-            if (network.mOkHttpClient == null) {
-                synchronized (network.mLock) {
-                    if (network.mOkHttpClient == null) {
-                        HostResolver hostResolver = new HostResolver() {
-                            @Override
-                            public InetAddress[] getAllByName(String host)
-                                    throws UnknownHostException {
-                                return network.getAllByName(host);
-                            }
-                        };
-                        network.mOkHttpClient = new OkHttpClient()
-                                .setSocketFactory(network.getSocketFactory())
-                                .setHostResolver(hostResolver);
-                    }
+    private void maybeInitHttpClient() {
+        if (mOkHttpClient == null) {
+            synchronized (mLock) {
+                if (mOkHttpClient == null) {
+                    HostResolver hostResolver = new HostResolver() {
+                        @Override
+                        public InetAddress[] getAllByName(String host) throws UnknownHostException {
+                            return Network.this.getAllByName(host);
+                        }
+                    };
+                    mOkHttpClient = new OkHttpClient()
+                            .setSocketFactory(getSocketFactory())
+                            .setHostResolver(hostResolver);
                 }
             }
-
-            String protocol = url.getProtocol();
-            URLStreamHandler handler = network.mOkHttpClient.createURLStreamHandler(protocol);
-            if (handler == null) {
-                // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
-                // passed another protocol.
-                throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
-            }
-            return new URL(url, "", handler);
         }
-    };
-
-    private static AtomicReference<NetworkBoundURLFactory> sNetworkBoundURLFactory =
-            new AtomicReference <NetworkBoundURLFactory>(DEFAULT_URL_FACTORY);
-
-    /**
-     * Returns a {@link URL} based on the given URL but bound to this {@code Network},
-     * such that opening the URL will send all network traffic on this Network.
-     *
-     * Note that if this {@code Network} ever disconnects, any URL object generated by this method
-     * in the past or future will cease to work.
-     *
-     * The returned URL may have a {@link URLStreamHandler} explicitly set, which may not be the
-     * handler generated by the factory set with {@link java.net.URL#setURLStreamHandlerFactory}. To
-     * affect the {@code URLStreamHandler}s of URLs returned by this method, call
-     * {@link #setNetworkBoundURLFactory}.
-     *
-     * Because the returned URLs may have an explicit {@code URLStreamHandler} set, using them as a
-     * context when constructing other URLs and explicitly specifying a {@code URLStreamHandler} may
-     * result in URLs that are no longer bound to the same {@code Network}.
-     *
-     * The default implementation only supports {@code HTTP} and {@code HTTPS} URLs.
-     *
-     * @return a {@link URL} bound to this {@code Network}.
-     */
-    public URL getBoundURL(URL url) throws MalformedURLException {
-        return sNetworkBoundURLFactory.get().getBoundURL(this, url);
     }
 
     /**
-     * Sets the {@link NetworkBoundURLFactory} to be used by future {@link #getBoundURL} calls.
-     * If {@code null}, clears any factory that was previously specified.
+     * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent
+     * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}.
+     *
+     * @return a {@code URLConnection} to the resource referred to by this URL.
+     * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS.
+     * @throws IOException if an error occurs while opening the connection.
+     * @see java.net.URL#openConnection()
      */
-    public static void setNetworkBoundURLFactory(NetworkBoundURLFactory factory) {
-        if (factory == null) {
-            factory = DEFAULT_URL_FACTORY;
+    public URLConnection openConnection(URL url) throws IOException {
+        maybeInitHttpClient();
+        String protocol = url.getProtocol();
+        URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol);
+        if (handler == null) {
+            // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
+            // passed another protocol.
+            throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
         }
-        sNetworkBoundURLFactory.set(factory);
+        return new URL(url, "", handler).openConnection();
+    }
+
+    /**
+     * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket
+     * will be sent on this {@code Network}, irrespective of any process-wide network binding set by
+     * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected.
+     */
+    public void bindSocket(Socket socket) throws IOException {
+        if (socket.isConnected()) {
+            throw new SocketException("Socket is connected");
+        }
+        // Query a property of the underlying socket to ensure the underlying
+        // socket exists so a file descriptor is available to bind to a network.
+        socket.getReuseAddress();
+        int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId);
+        if (err != 0) {
+            // bindSocketToNetwork returns negative errno.
+            throw new ErrnoException("Binding socket to network " + netId, -err)
+                    .rethrowAsSocketException();
+        }
     }
 
     // implement the Parcelable interface
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 54d8676..d2a2997 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -128,8 +128,9 @@
     /**
      * Explicitly binds {@code socketfd} to the network designated by {@code netId}.  This
      * overrides any binding via {@link #bindProcessToNetwork}.
+     * @return 0 on success or negative errno on failure.
      */
-    public native static boolean bindSocketToNetwork(int socketfd, int netId);
+    public native static int bindSocketToNetwork(int socketfd, int netId);
 
     /**
      * Protect {@code socketfd} from VPN connections.  After protecting, data sent through
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 1e1ad9e..afa5885 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -95,6 +95,10 @@
                     int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
                     while (len > 0) {
                         int n = IoBridge.read(mServer, temp, 0, Math.min(temp.length, len));
+                        if (n == -1) {
+                            throw new IOException(
+                                    "Unexpected EOF; still expected " + len + " bytes");
+                        }
                         IoBridge.write(mTarget, temp, 0, n);
                         len -= n;
                     }
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 6246cbe..ebb1a5c 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -107,6 +107,8 @@
      *
      * @param reparent true if the transition should track the parent
      * container of target views and animate parent changes.
+     * @deprecated Use {@link android.transition.ChangeTransform} to handle
+     * transitions between different parents.
      */
     public void setReparent(boolean reparent) {
         mReparent = reparent;
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 4b230eb..d7a9120 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -16,7 +16,6 @@
 package android.transition;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.TypeEvaluator;
 import android.content.Context;
@@ -196,28 +195,6 @@
     private ObjectAnimator createMatrixAnimator(final ImageView imageView, Matrix startMatrix,
             final Matrix endMatrix) {
         return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
-                new MatrixEvaluator(), startMatrix, endMatrix);
+                new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
     }
-
-    private static class MatrixEvaluator implements TypeEvaluator<Matrix> {
-
-        float[] mTempStartValues = new float[9];
-
-        float[] mTempEndValues = new float[9];
-
-        Matrix mTempMatrix = new Matrix();
-
-        @Override
-        public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
-            startValue.getValues(mTempStartValues);
-            endValue.getValues(mTempEndValues);
-            for (int i = 0; i < 9; i++) {
-                float diff = mTempEndValues[i] - mTempStartValues[i];
-                mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
-            }
-            mTempMatrix.setValues(mTempEndValues);
-            return mTempMatrix;
-        }
-    }
-
 }
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index e9be3b9..d579f54 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -16,72 +16,134 @@
 package android.transition;
 
 import android.animation.Animator;
-import android.animation.FloatArrayEvaluator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Matrix;
 import android.util.AttributeSet;
-import android.util.FloatProperty;
 import android.util.Property;
+import android.view.GhostView;
 import android.view.View;
 import android.view.ViewGroup;
+import com.android.internal.R;
 
 /**
  * This Transition captures scale and rotation for Views before and after the
  * scene change and animates those changes during the transition.
  *
- * <p>ChangeTransform does not work when the pivot changes between scenes, so either the
- * pivot must be set to prevent automatic pivot adjustment or the View's size must be unchanged.</p>
+ * A change in parent is handled as well by capturing the transforms from
+ * the parent before and after the scene change and animating those during the
+ * transition.
  */
 public class ChangeTransform extends Transition {
 
     private static final String TAG = "ChangeTransform";
 
-    private static final String PROPNAME_SCALE_X = "android:changeTransform:scaleX";
-    private static final String PROPNAME_SCALE_Y = "android:changeTransform:scaleY";
-    private static final String PROPNAME_ROTATION_X = "android:changeTransform:rotationX";
-    private static final String PROPNAME_ROTATION_Y = "android:changeTransform:rotationY";
-    private static final String PROPNAME_ROTATION_Z = "android:changeTransform:rotationZ";
-    private static final String PROPNAME_PIVOT_X = "android:changeTransform:pivotX";
-    private static final String PROPNAME_PIVOT_Y = "android:changeTransform:pivotY";
+    private static final String PROPNAME_MATRIX = "android:changeTransform:matrix";
+    private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms";
+    private static final String PROPNAME_PARENT = "android:changeTransform:parent";
+    private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix";
 
     private static final String[] sTransitionProperties = {
-            PROPNAME_SCALE_X,
-            PROPNAME_SCALE_Y,
-            PROPNAME_ROTATION_X,
-            PROPNAME_ROTATION_Y,
-            PROPNAME_ROTATION_Z,
+            PROPNAME_MATRIX,
+            PROPNAME_TRANSFORMS,
+            PROPNAME_PARENT_MATRIX,
     };
 
-    private static final FloatProperty<View>[] sChangedProperties = new FloatProperty[] {
-            (FloatProperty) View.SCALE_X,
-            (FloatProperty) View.SCALE_Y,
-            (FloatProperty) View.ROTATION_X,
-            (FloatProperty) View.ROTATION_Y,
-            (FloatProperty) View.ROTATION,
-    };
-
-    private static Property<View, float[]> TRANSFORMS = new Property<View, float[]>(float[].class,
-            "transforms") {
-        @Override
-        public float[] get(View object) {
-            return null;
-        }
-
-        @Override
-        public void set(View view, float[] values) {
-            for (int i = 0; i < values.length; i++) {
-                float value = values[i];
-                if (!Float.isNaN(value)) {
-                    sChangedProperties[i].setValue(view, value);
+    private static final Property<View, Matrix> ANIMATION_MATRIX_PROPERTY =
+            new Property<View, Matrix>(Matrix.class, "animationMatrix") {
+                @Override
+                public Matrix get(View object) {
+                    return null;
                 }
-            }
-        }
-    };
+
+                @Override
+                public void set(View object, Matrix value) {
+                    object.setAnimationMatrix(value);
+                }
+            };
+
+    private boolean mUseOverlay = true;
+    private boolean mReparent = true;
+    private Matrix mTempMatrix = new Matrix();
 
     public ChangeTransform() {}
 
     public ChangeTransform(Context context, AttributeSet attrs) {
         super(context, attrs);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeTransform);
+        mUseOverlay = a.getBoolean(R.styleable.ChangeTransform_reparentWithOverlay, true);
+        mReparent = a.getBoolean(R.styleable.ChangeTransform_reparent, true);
+        a.recycle();
+    }
+
+    /**
+     * Returns whether changes to parent should use an overlay or not. When the parent
+     * change doesn't use an overlay, it affects the transforms of the child. The
+     * default value is <code>true</code>.
+     *
+     * <p>Note: when Overlays are not used when a parent changes, a view can be clipped when
+     * it moves outside the bounds of its parent. Setting
+     * {@link android.view.ViewGroup#setClipChildren(boolean)} and
+     * {@link android.view.ViewGroup#setClipToPadding(boolean)} can help. Also, when
+     * Overlays are not used and the parent is animating its location, the position of the
+     * child view will be relative to its parent's final position, so it may appear to "jump"
+     * at the beginning.</p>
+     *
+     * @return <code>true</code> when a changed parent should execute the transition
+     * inside the scene root's overlay or <code>false</code> if a parent change only
+     * affects the transform of the transitioning view.
+     */
+    public boolean getReparentWithOverlay() {
+        return mUseOverlay;
+    }
+
+    /**
+     * Sets whether changes to parent should use an overlay or not. When the parent
+     * change doesn't use an overlay, it affects the transforms of the child. The
+     * default value is <code>true</code>.
+     *
+     * <p>Note: when Overlays are not used when a parent changes, a view can be clipped when
+     * it moves outside the bounds of its parent. Setting
+     * {@link android.view.ViewGroup#setClipChildren(boolean)} and
+     * {@link android.view.ViewGroup#setClipToPadding(boolean)} can help. Also, when
+     * Overlays are not used and the parent is animating its location, the position of the
+     * child view will be relative to its parent's final position, so it may appear to "jump"
+     * at the beginning.</p>
+     *
+     * @return <code>true</code> when a changed parent should execute the transition
+     * inside the scene root's overlay or <code>false</code> if a parent change only
+     * affects the transform of the transitioning view.
+     */
+    public void setReparentWithOverlay(boolean reparentWithOverlay) {
+        mUseOverlay = reparentWithOverlay;
+    }
+
+    /**
+     * Returns whether parent changes will be tracked by the ChangeTransform. If parent
+     * changes are tracked, then the transform will adjust to the transforms of the
+     * different parents. If they aren't tracked, only the transforms of the transitioning
+     * view will be tracked. Default is true.
+     *
+     * @return whether parent changes will be tracked by the ChangeTransform.
+     */
+    public boolean getReparent() {
+        return mReparent;
+    }
+
+    /**
+     * Sets whether parent changes will be tracked by the ChangeTransform. If parent
+     * changes are tracked, then the transform will adjust to the transforms of the
+     * different parents. If they aren't tracked, only the transforms of the transitioning
+     * view will be tracked. Default is true.
+     *
+     * @param reparent Set to true to track parent changes or false to only track changes
+     *                 of the transitioning view without considering the parent change.
+     */
+    public void setReparent(boolean reparent) {
+        mReparent = reparent;
     }
 
     @Override
@@ -89,19 +151,29 @@
         return sTransitionProperties;
     }
 
-    private void captureValues(TransitionValues values) {
-        View view = values.view;
+    private void captureValues(TransitionValues transitionValues) {
+        View view = transitionValues.view;
         if (view.getVisibility() == View.GONE) {
             return;
         }
-
-        values.values.put(PROPNAME_SCALE_X, view.getScaleX());
-        values.values.put(PROPNAME_SCALE_Y, view.getScaleY());
-        values.values.put(PROPNAME_PIVOT_X, view.getPivotX());
-        values.values.put(PROPNAME_PIVOT_Y, view.getPivotY());
-        values.values.put(PROPNAME_ROTATION_X, view.getRotationX());
-        values.values.put(PROPNAME_ROTATION_Y, view.getRotationY());
-        values.values.put(PROPNAME_ROTATION_Z, view.getRotation());
+        transitionValues.values.put(PROPNAME_PARENT, view.getParent());
+        Transforms transforms = new Transforms(view);
+        transitionValues.values.put(PROPNAME_TRANSFORMS, transforms);
+        Matrix matrix = view.getMatrix();
+        if (matrix == null || matrix.isIdentity()) {
+            matrix = null;
+        } else {
+            matrix = new Matrix(matrix);
+        }
+        transitionValues.values.put(PROPNAME_MATRIX, matrix);
+        if (mReparent) {
+            Matrix parentMatrix = new Matrix();
+            ViewGroup parent = (ViewGroup) view.getParent();
+            parent.transformMatrixToGlobal(parentMatrix);
+            parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
+            transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix);
+        }
+        return;
     }
 
     @Override
@@ -115,57 +187,252 @@
     }
 
     @Override
-    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
+    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
             TransitionValues endValues) {
-        if (startValues == null || endValues == null
-                || !startValues.values.containsKey(PROPNAME_SCALE_X)
-                || !endValues.values.containsKey(PROPNAME_SCALE_X)
-                || !isPivotSame(startValues, endValues)
-                || !isChanged(startValues, endValues)) {
+        if (startValues == null || endValues == null ||
+                !startValues.values.containsKey(PROPNAME_PARENT) ||
+                !endValues.values.containsKey(PROPNAME_PARENT)) {
             return null;
         }
 
-        float[] start = createValues(startValues);
-        float[] end = createValues(endValues);
-        for (int i = 0; i < start.length; i++) {
-            if (start[i] == end[i]) {
-                start[i] = Float.NaN;
-                end[i] = Float.NaN;
-            } else {
-                sChangedProperties[i].setValue(endValues.view, start[i]);
+        ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
+        ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
+        boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent);
+
+        Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform);
+        if (startMatrix != null) {
+            startValues.values.put(PROPNAME_MATRIX, startMatrix);
+        }
+
+        Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix);
+        if (startParentMatrix != null) {
+            startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix);
+        }
+
+        // First handle the parent change:
+        if (handleParentChange) {
+            setMatricesForParent(startValues, endValues);
+        }
+
+        // Next handle the normal matrix transform:
+        ObjectAnimator transformAnimator = createTransformAnimator(startValues, endValues);
+
+        if (handleParentChange && transformAnimator != null && mUseOverlay) {
+            createGhostView(sceneRoot, startValues, endValues);
+        }
+
+        return transformAnimator;
+    }
+
+    private ObjectAnimator createTransformAnimator(TransitionValues startValues,
+            TransitionValues endValues) {
+        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+        Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
+
+        if (startMatrix == null) {
+            startMatrix = Matrix.IDENTITY_MATRIX;
+        }
+
+        if (endMatrix == null) {
+            endMatrix = Matrix.IDENTITY_MATRIX;
+        }
+
+        if (startMatrix.equals(endMatrix)) {
+            return null;
+        }
+
+        final Transforms transforms = (Transforms) endValues.values.get(PROPNAME_TRANSFORMS);
+
+        // clear the transform properties so that we can use the animation matrix instead
+        final View view = endValues.view;
+        setIdentityTransforms(view);
+
+        ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
+                new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
+
+        AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+            private boolean mIsCanceled;
+            private Matrix mTempMatrix;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mIsCanceled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!mIsCanceled) {
+                    view.setTagInternal(R.id.transitionTransform, null);
+                    view.setTagInternal(R.id.parentMatrix, null);
+                }
+                ANIMATION_MATRIX_PROPERTY.set(view, null);
+                transforms.restore(view);
+            }
+
+            @Override
+            public void onAnimationPause(Animator animation) {
+                ValueAnimator animator = (ValueAnimator) animation;
+                Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
+                if (mTempMatrix == null) {
+                    mTempMatrix = new Matrix(currentMatrix);
+                } else {
+                    mTempMatrix.set(currentMatrix);
+                }
+                view.setTagInternal(R.id.transitionTransform, mTempMatrix);
+                transforms.restore(view);
+            }
+
+            @Override
+            public void onAnimationResume(Animator animation) {
+                setIdentityTransforms(view);
+            }
+        };
+
+        animator.addListener(listener);
+        animator.addPauseListener(listener);
+        return animator;
+    }
+
+    private boolean parentsMatch(ViewGroup startParent, ViewGroup endParent) {
+        boolean parentsMatch = false;
+        if (!isValidTarget(startParent) || !isValidTarget(endParent)) {
+            parentsMatch = startParent == endParent;
+        } else {
+            TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+            if (endValues != null) {
+                parentsMatch = endParent == endValues.view;
             }
         }
-        FloatArrayEvaluator evaluator = new FloatArrayEvaluator(new float[start.length]);
-        return ObjectAnimator.ofObject(endValues.view, TRANSFORMS, evaluator, start, end);
+        return parentsMatch;
     }
 
-    private static float[] createValues(TransitionValues transitionValues) {
-        float[] values = new float[sChangedProperties.length];
-        for (int i = 0; i < values.length; i++) {
-            values[i] = (Float) transitionValues.values.get(sTransitionProperties[i]);
+    private void createGhostView(final ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        View view = endValues.view;
+
+        Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_PARENT_MATRIX);
+        Matrix localEndMatrix = new Matrix(endMatrix);
+        sceneRoot.transformMatrixToLocal(localEndMatrix);
+
+        GhostView ghostView = GhostView.addGhost(view, sceneRoot, localEndMatrix);
+
+        Transition outerTransition = this;
+        while (outerTransition.mParent != null) {
+            outerTransition = outerTransition.mParent;
         }
-        return values;
+        GhostListener listener = new GhostListener(view, ghostView, endMatrix);
+        outerTransition.addListener(listener);
+
+        if (startValues.view != endValues.view) {
+            startValues.view.setTransitionAlpha(0);
+        }
+        view.setTransitionAlpha(1);
     }
 
-    private static boolean isPivotSame(TransitionValues startValues, TransitionValues endValues) {
-        float startPivotX = (Float) startValues.values.get(PROPNAME_PIVOT_X);
-        float startPivotY = (Float) startValues.values.get(PROPNAME_PIVOT_Y);
-        float endPivotX = (Float) endValues.values.get(PROPNAME_PIVOT_X);
-        float endPivotY = (Float) endValues.values.get(PROPNAME_PIVOT_Y);
+    private void setMatricesForParent(TransitionValues startValues, TransitionValues endValues) {
+        Matrix endParentMatrix = (Matrix) endValues.values.get(PROPNAME_PARENT_MATRIX);
+        endValues.view.setTagInternal(R.id.parentMatrix, endParentMatrix);
 
-        // We don't support pivot changes, because they could be automatically set
-        // and we can't end the state in an automatic state.
-        return startPivotX == endPivotX && startPivotY == endPivotY;
+        Matrix toLocal = mTempMatrix;
+        toLocal.reset();
+        endParentMatrix.invert(toLocal);
+
+        Matrix startLocal = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+        if (startLocal == null) {
+            startLocal = new Matrix();
+            startValues.values.put(PROPNAME_MATRIX, startLocal);
+        }
+
+        Matrix startParentMatrix = (Matrix) startValues.values.get(PROPNAME_PARENT_MATRIX);
+        startLocal.postConcat(startParentMatrix);
+        startLocal.postConcat(toLocal);
     }
 
-    private static boolean isChanged(TransitionValues startValues, TransitionValues endValues) {
-        for (int i = 0; i < sChangedProperties.length; i++) {
-            Object start = startValues.values.get(sTransitionProperties[i]);
-            Object end = endValues.values.get(sTransitionProperties[i]);
-            if (!start.equals(end)) {
-                return true;
+    private static void setIdentityTransforms(View view) {
+        setTransforms(view, 0, 0, 0, 1, 1, 0, 0, 0);
+    }
+
+    private static void setTransforms(View view, float translationX, float translationY,
+            float translationZ, float scaleX, float scaleY, float rotationX,
+            float rotationY, float rotationZ) {
+        view.setTranslationX(translationX);
+        view.setTranslationY(translationY);
+        view.setTranslationZ(translationZ);
+        view.setScaleX(scaleX);
+        view.setScaleY(scaleY);
+        view.setRotationX(rotationX);
+        view.setRotationY(rotationY);
+        view.setRotation(rotationZ);
+    }
+
+    private static class Transforms {
+        public final float translationX;
+        public final float translationY;
+        public final float translationZ;
+        public final float scaleX;
+        public final float scaleY;
+        public final float rotationX;
+        public final float rotationY;
+        public final float rotationZ;
+
+        public Transforms(View view) {
+            translationX = view.getTranslationX();
+            translationY = view.getTranslationY();
+            translationZ = view.getTranslationZ();
+            scaleX = view.getScaleX();
+            scaleY = view.getScaleY();
+            rotationX = view.getRotationX();
+            rotationY = view.getRotationY();
+            rotationZ = view.getRotation();
+        }
+
+        public void restore(View view) {
+            setTransforms(view, translationX, translationY, translationZ, scaleX, scaleY,
+                    rotationX, rotationY, rotationZ);
+        }
+
+        @Override
+        public boolean equals(Object that) {
+            if (!(that instanceof Transforms)) {
+                return false;
             }
+            Transforms thatTransform = (Transforms) that;
+            return thatTransform.translationX == translationX &&
+                    thatTransform.translationY == translationY &&
+                    thatTransform.translationZ == translationZ &&
+                    thatTransform.scaleX == scaleX &&
+                    thatTransform.scaleY == scaleY &&
+                    thatTransform.rotationX == rotationX &&
+                    thatTransform.rotationY == rotationY &&
+                    thatTransform.rotationZ == rotationZ;
         }
-        return false;
+    }
+
+    private static class GhostListener extends Transition.TransitionListenerAdapter {
+        private View mView;
+        private GhostView mGhostView;
+	private Matrix mEndMatrix;
+
+        public GhostListener(View view, GhostView ghostView, Matrix endMatrix) {
+            mView = view;
+            mGhostView = ghostView;
+            mEndMatrix = endMatrix;
+        }
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            transition.removeListener(this);
+            GhostView.removeGhost(mView);
+        }
+
+        @Override
+        public void onTransitionPause(Transition transition) {
+            mGhostView.setVisibility(View.INVISIBLE);
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+            mGhostView.setVisibility(View.VISIBLE);
+        }
     }
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0d32d40..59ba71f 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -112,8 +112,8 @@
  *
  * Further information on XML resource descriptions for transitions can be found for
  * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
- * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, and
- * {@link android.R.styleable#Slide}.
+ * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade},
+ * {@link android.R.styleable#Slide}, and {@link android.R.styleable#ChangeTransform}.
  *
  */
 public abstract class Transition implements Cloneable {
@@ -1755,24 +1755,40 @@
         // if oldValues null, then transition didn't care to stash values,
         // and won't get canceled
         if (oldValues != null && newValues != null) {
-            for (String key : oldValues.values.keySet()) {
-                Object oldValue = oldValues.values.get(key);
-                Object newValue = newValues.values.get(key);
-                if (oldValue != null && newValue != null &&
-                        !oldValue.equals(newValue)) {
-                    valuesChanged = true;
-                    if (DBG) {
-                        Log.d(LOG_TAG, "Transition.playTransition: " +
-                                "oldValue != newValue for " + key +
-                                ": old, new = " + oldValue + ", " + newValue);
+            String[] properties = getTransitionProperties();
+            if (properties != null) {
+                int count = properties.length;
+                for (int i = 0; i < count; i++) {
+                    if (isValueChanged(oldValues, newValues, properties[i])) {
+                        valuesChanged = true;
+                        break;
                     }
-                    break;
+                }
+            } else {
+                for (String key : oldValues.values.keySet()) {
+                    if (isValueChanged(oldValues, newValues, key)) {
+                        valuesChanged = true;
+                        break;
+                    }
                 }
             }
         }
         return valuesChanged;
     }
 
+    private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues,
+            String key) {
+        Object oldValue = oldValues.values.get(key);
+        Object newValue = newValues.values.get(key);
+        boolean changed = (oldValue != null && newValue != null && !oldValue.equals(newValue));
+        if (DBG && changed) {
+            Log.d(LOG_TAG, "Transition.playTransition: " +
+                    "oldValue != newValue for " + key +
+                    ": old, new = " + oldValue + ", " + newValue);
+        }
+        return changed;
+    }
+
     /**
      * This is a utility method used by subclasses to handle standard parts of
      * setting up and running an Animator: it sets the {@link #getDuration()
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index 931d46a..b0c9e9a 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
+import android.animation.TypeEvaluator;
+import android.graphics.Matrix;
 
 /**
  * Static utility methods for Transitions.
@@ -37,4 +39,25 @@
             return animatorSet;
         }
     }
+
+    public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
+
+        float[] mTempStartValues = new float[9];
+
+        float[] mTempEndValues = new float[9];
+
+        Matrix mTempMatrix = new Matrix();
+
+        @Override
+        public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
+            startValue.getValues(mTempStartValues);
+            endValue.getValues(mTempEndValues);
+            for (int i = 0; i < 9; i++) {
+                float diff = mTempEndValues[i] - mTempStartValues[i];
+                mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
+            }
+            mTempMatrix.setValues(mTempEndValues);
+            return mTempMatrix;
+        }
+    }
 }
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 79dbb49..81c69d1 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -63,8 +63,6 @@
 
     private static final String[] sTransitionProperties = {
             PROPNAME_VISIBILITY,
-            PROPNAME_PARENT,
-            PROPNAME_SCREEN_LOCATION,
     };
 
     private static class VisibilityInfo {
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index a56d448..9433237 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
+import android.animation.Animator.AnimatorListener;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
@@ -202,7 +203,7 @@
             mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
         }
 
-        final ArrayList<AnimatorListener> listeners = getListeners();
+        final ArrayList<AnimatorListener> listeners = cloneListeners();
         final int numListeners = listeners == null ? 0 : listeners.size();
         for (int i = 0; i < numListeners; i++) {
             listeners.get(i).onAnimationStart(this);
@@ -220,7 +221,7 @@
             getHelper().removeDelayedAnimation(this);
             nEnd(mNativePtr.get());
 
-            final ArrayList<AnimatorListener> listeners = getListeners();
+            final ArrayList<AnimatorListener> listeners = cloneListeners();
             final int numListeners = listeners == null ? 0 : listeners.size();
             for (int i = 0; i < numListeners; i++) {
                 listeners.get(i).onAnimationCancel(this);
@@ -329,13 +330,22 @@
     protected void onFinished() {
         mFinished = true;
 
-        final ArrayList<AnimatorListener> listeners = getListeners();
+        final ArrayList<AnimatorListener> listeners = cloneListeners();
         final int numListeners = listeners == null ? 0 : listeners.size();
         for (int i = 0; i < numListeners; i++) {
             listeners.get(i).onAnimationEnd(this);
         }
     }
 
+    @SuppressWarnings("unchecked")
+    private ArrayList<AnimatorListener> cloneListeners() {
+        ArrayList<AnimatorListener> listeners = getListeners();
+        if (listeners != null) {
+            listeners = (ArrayList<AnimatorListener>) listeners.clone();
+        }
+        return listeners;
+    }
+
     long getNativeAnimator() {
         return mNativePtr.get();
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 243d7d7..6f58582 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10793,6 +10793,15 @@
         }
     }
 
+    /** @hide */
+    public void setAnimationMatrix(Matrix matrix) {
+        invalidateViewProperty(true, false);
+        mRenderNode.setAnimationMatrix(matrix);
+        invalidateViewProperty(false, true);
+
+        invalidateParentIfNeededAndWasQuickRejected();
+    }
+
     /**
      * Returns the current StateListAnimator if exists.
      *
@@ -13090,6 +13099,10 @@
         removeSendViewScrolledAccessibilityEventCallback();
         stopNestedScroll();
 
+        // Anything that started animating right before detach should already
+        // be in its final state when re-attached.
+        jumpDrawablesToCurrentState();
+
         destroyDrawingCache();
 
         cleanupDraw();
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index eeff90a..7ced088 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -26,7 +26,7 @@
 public final class ViewAnimationUtils {
     private ViewAnimationUtils() {}
     /**
-     * Returns a ValueAnimator which can animate a clipping circle.
+     * Returns an Animator which can animate a clipping circle.
      *
      * Any shadow cast by the View will respect the circular clip from this animator.
      *
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index e7b3152..2c7ea3e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1662,6 +1662,27 @@
     public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
 
     /**
+     * Returns <code>true</code> when shared elements should use an Overlay during
+     * shared element transitions or <code>false</code> when they should animate as
+     * part of the normal View hierarchy. The default value is true.
+     *
+     * @return <code>true</code> when shared elements should use an Overlay during
+     * shared element transitions or <code>false</code> when they should animate as
+     * part of the normal View hierarchy.
+     */
+    public boolean getSharedElementsUseOverlay() { return true; }
+
+    /**
+     * Sets whether or not shared elements should use an Overlay during shared element transitions.
+     * The default value is true.
+     *
+     * @param sharedElementsUseOverlay <code>true</code> indicates that shared elements should
+     *                                 be transitioned with an Overlay or <code>false</code>
+     *                                 to transition within the normal View hierarchy.
+     */
+    public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) { }
+
+    /**
      * @return the color of the status bar.
      */
     public abstract int getStatusBarColor();
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 8cae27b..4d2f57a 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -429,25 +429,10 @@
     }
 
     /**
-     * The default implementation is responsible for handling
-     * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. In fact, for derived classes, calling
-     * {@code super.requestCursorAnchorInfo(request)} is the only way to handle
-     * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}.
+     * The default implementation does nothing.
      */
-    public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
-        // This implementation supports TYPE_CURSOR_RECT only.
-        if (request == null ||
-                request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_RECT) {
-            return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
-        }
-        if (mIMM == null) {
-            // In this case, TYPE_CURSOR_RECT is not handled.
-            // TODO: Return some notification code for the input method that indicates
-            // Cursor rect information is temporarily unavailable.
-            return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
-        }
-        mIMM.setCursorRectMonitorMode(request.getRequestFlags());
-        return CursorAnchorInfoRequest.RESULT_SCHEDULED;
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        return false;
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
deleted file mode 100644
index e4c94f2..0000000
--- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.
- */
-
-package android.view.inputmethod;
-
-import android.inputmethodservice.InputMethodService;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * Used to enable or disable event notification for
- * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. This class is also used to
- * enable {@link InputMethodService#onUpdateCursor(android.graphics.Rect)} for existing editors
- * that have not supported {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
- */
-public final class CursorAnchorInfoRequest implements Parcelable {
-    private final int mRequestType;
-    private final int mRequestFlags;
-
-    /**
-     * Not handled by the editor.
-     */
-    public static final int RESULT_NOT_HANDLED = 0x00;
-    /**
-     * Request is scheduled in the editor task queue.
-     */
-    public static final int RESULT_SCHEDULED = 0x01;
-
-    /**
-     * The request is for {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
-     * This mechanism is powerful enough to retrieve fine-grained positional information of
-     * characters in the editor.
-     */
-    public static final int TYPE_CURSOR_ANCHOR_INFO = 0x01;
-    /**
-     * The editor is requested to call
-     * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
-     * whenever cursor/anchor position is changed. To disable monitoring, call
-     * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
-     * {@link #TYPE_CURSOR_ANCHOR_INFO} and this flag off.
-     * <p>
-     * This flag can be used together with {@link #FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE}.
-     * </p>
-     */
-    public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 0x01;
-    /**
-     * The editor is requested to call
-     * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
-     * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
-     * used together with {@link #FLAG_CURSOR_ANCHOR_INFO_MONITOR}.
-     */
-    public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 0x02;
-
-    /**
-     * The request is for {@link InputMethodService#onUpdateCursor(android.graphics.Rect)}. This
-     * mechanism has been available since API Level 3 (CUPCAKE) but only the cursor rectangle can
-     * be retrieved with this mechanism.
-     */
-    public static final int TYPE_CURSOR_RECT = 0x02;
-    /**
-     * The editor is requested to call
-     * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)}
-     * whenever the cursor position is changed. To disable monitoring, call
-     * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
-     * {@link #TYPE_CURSOR_RECT} and this flag off.
-     * <p>
-     * This flag can be used together with {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}.
-     * </p>
-     */
-    public static final int FLAG_CURSOR_RECT_MONITOR = 0x01;
-    /**
-     * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
-     * called back in screen coordinates. To receive cursor position in local coordinates, call
-     * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
-     * {@link #TYPE_CURSOR_RECT} and this flag off.
-     */
-    public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 0x02;
-    /**
-     * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
-     * called back in screen coordinates after coordinate conversion with {@link View#getMatrix()}.
-     * To disable coordinate conversion with {@link View#getMatrix()} again, call
-     * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
-     * {@link #TYPE_CURSOR_RECT} and this flag off.
-     *
-     * <p>
-     * The flag is ignored if {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES} is off.
-     * </p>
-     */
-    public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 0x04;
-
-    /**
-     * Constructs the object with request type and type-specific flags.
-     *
-     * @param requestType the type of this request. Currently {@link #TYPE_CURSOR_ANCHOR_INFO} or
-     * {@link #TYPE_CURSOR_RECT} is supported.
-     * @param requestFlags the flags for the given request type.
-     */
-    public CursorAnchorInfoRequest(int requestType, int requestFlags) {
-        mRequestType = requestType;
-        mRequestFlags = requestFlags;
-    }
-
-    /**
-     * Used to make this class parcelable.
-     *
-     * @param source the parcel from which the object is unmarshalled.
-     */
-    public CursorAnchorInfoRequest(Parcel source) {
-        mRequestType = source.readInt();
-        mRequestFlags = source.readInt();
-    }
-
-    /**
-     * @return the type of this request.
-     */
-    public int getRequestType() {
-        return mRequestType;
-    }
-
-    /**
-     * @return the flags that are specific to the type of this request.
-     */
-    public int getRequestFlags() {
-        return mRequestFlags;
-    }
-
-    /**
-     * Used to package this object into a {@link Parcel}.
-     *
-     * @param dest The {@link Parcel} to be written.
-     * @param flags The flags used for parceling.
-     */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRequestType);
-        dest.writeInt(mRequestFlags);
-    }
-
-    @Override
-    public int hashCode(){
-        return mRequestType * 31 + mRequestFlags;
-    }
-
-    @Override
-    public boolean equals(Object obj){
-        if (obj == null) {
-            return false;
-        }
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof CursorAnchorInfoRequest)) {
-            return false;
-        }
-        final CursorAnchorInfoRequest that = (CursorAnchorInfoRequest) obj;
-        if (hashCode() != that.hashCode()) {
-            return false;
-        }
-        return mRequestType != that.mRequestType && mRequestFlags == that.mRequestFlags;
-    }
-
-    @Override
-    public String toString() {
-        return "CursorAnchorInfoRequest{mRequestType=" + mRequestType
-                + " mRequestFlags=" + mRequestFlags
-                + "}";
-    }
-
-    /**
-     * Used to make this class parcelable.
-     */
-    public static final Parcelable.Creator<CursorAnchorInfoRequest> CREATOR =
-            new Parcelable.Creator<CursorAnchorInfoRequest>() {
-        @Override
-        public CursorAnchorInfoRequest createFromParcel(Parcel source) {
-            return new CursorAnchorInfoRequest(source);
-        }
-
-        @Override
-        public CursorAnchorInfoRequest[] newArray(int size) {
-            return new CursorAnchorInfoRequest[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index dff91dc..ca094c1 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -725,13 +725,34 @@
     public boolean performPrivateCommand(String action, Bundle data);
 
     /**
-     * Called by the IME to ask the editor for calling back
+     * The editor is requested to call
+     * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
+     * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
+     * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}.
+     */
+    public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0;
+
+    /**
+     * The editor is requested to call
+     * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
+     * whenever cursor/anchor position is changed. To disable monitoring, call
+     * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off.
+     * <p>
+     * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}.
+     * </p>
+     */
+    public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+
+    /**
+     * Called by the input method to ask the editor for calling back
      * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
      * notify cursor/anchor locations.
      *
-     * @param request the details of the request.
-     * @return a result code that depends on {@link CursorAnchorInfoRequest#getRequestType()}. See
-     * {@link CursorAnchorInfoRequest} for details.
+     * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or
+     * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}
+     * @return {@code true} if the request is scheduled. {@code false} to indicate that when the
+     * application will not call
+     * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
      */
-    public int requestCursorAnchorInfo(CursorAnchorInfoRequest request);
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode);
 }
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index c831d7c..d95df25 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -126,7 +126,7 @@
         return mTarget.performPrivateCommand(action, data);
     }
 
-    public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
-        return mTarget.requestCursorAnchorInfo(request);
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode);
     }
  }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index eec3570..0a472c7 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -313,9 +313,8 @@
     CompletionInfo[] mCompletions;
     
     // Cursor position on the screen.
-    Rect mNextCursorRect = new Rect();
+    Rect mTmpCursorRect = new Rect();
     Rect mCursorRect = new Rect();
-    RectF mTempRectF = new RectF();
     int mCursorSelStart;
     int mCursorSelEnd;
     int mCursorCandStart;
@@ -372,28 +371,12 @@
     InputChannel mCurChannel;
     ImeInputEventSender mCurSender;
 
-    private static final int CURSOR_RECT_MONITOR_MODE_NONE = 0x0;
-
-    private static final int CURSOR_RECT_MONITOR_FLAG_MASK =
-            CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR |
-            CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES |
-            CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX;
-
-    private static final int CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE = 0x0;
-
-    private static final int CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK =
-            CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR |
-            CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
-
-    /**
-     * The monitor mode for {@link #updateCursor(View, int, int, int, int)}.
-     */
-    private int mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+    private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
 
     /**
      * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
      */
-    private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
+    private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
 
     final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
@@ -446,8 +429,8 @@
                             return;
                         }
 
-                        mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
-                        mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+                        mRequestUpdateCursorAnchorInfoMonitorMode =
+                                REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
 
                         setInputChannelLocked(res.channel);
                         mCurMethod = res.method;
@@ -1540,59 +1523,49 @@
     }
 
     /**
-     * Returns true if the current input method wants to watch the location
+     * Return true if the current input method wants to watch the location
      * of the input editor's cursor in its window.
-     */
-    public boolean isWatchingCursor(View view) {
-        if (!isActive(view)) {
-            return false;
-        }
-        synchronized (mH) {
-            return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0;
-        }
-    }
-
-    /**
-     * Updates the result of {@link #isWatchingCursor(View)}.
      *
-     * @hide
+     * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead.
      */
-    public void setCursorRectMonitorMode(int flags) {
-        synchronized (mH) {
-            mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags);
-        }
+    @Deprecated
+    public boolean isWatchingCursor(View view) {
+        return false;
     }
 
     /**
-     * Returns true if the current input method wants to be notified when cursor/anchor location
+     * Return true if the current input method wants to be notified when cursor/anchor location
      * is changed.
      *
      * @hide
      */
     public boolean isCursorAnchorInfoEnabled() {
         synchronized (mH) {
-            final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
-                    CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
-            final boolean isMonitoring = (mCursorAnchorInfoMonitorMode &
-                    CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR) != 0;
+            final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
+                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+            final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
+                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0;
             return isImmediate || isMonitoring;
         }
     }
 
     /**
-     * Updates the result of {@link #isWatchingCursor(View)}.
+     * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
      *
      * @hide
      */
-    public void setCursorAnchorInfoMonitorMode(int flags) {
+    public void setUpdateCursorAnchorInfoMode(int flags) {
         synchronized (mH) {
-            mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags);
+            mRequestUpdateCursorAnchorInfoMonitorMode = flags;
         }
     }
 
     /**
      * Report the current cursor location in its window.
+     *
+     * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
      */
+    @Deprecated
     public void updateCursor(View view, int left, int top, int right, int bottom) {
         checkFocus();
         synchronized (mH) {
@@ -1601,33 +1574,15 @@
                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
                 return;
             }
-            if (DEBUG) Log.d(TAG, "updateCursor");
-            final boolean usesScreenCoordinates = (mCursorRectMonitorMode &
-                    CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES) != 0;
-            if (usesScreenCoordinates) {
-                view.getLocationOnScreen(mViewTopLeft);
-                final Matrix viewMatrix = view.getMatrix();
-                final boolean usesViewMatrix = (viewMatrix != null) && ((mCursorRectMonitorMode &
-                        CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX) != 0);
-                if (usesViewMatrix) {
-                    mTempRectF.set(left, top, right, bottom);
-                    mViewToScreenMatrix.set(viewMatrix);
-                    mViewToScreenMatrix.postTranslate(mViewTopLeft[0], mViewTopLeft[1]);
-                    mViewToScreenMatrix.mapRect(mTempRectF);
-                    mNextCursorRect.set((int)mTempRectF.left, (int)mTempRectF.top,
-                            (int)mTempRectF.right, (int)mTempRectF.bottom);
-                } else {
-                    mNextCursorRect.set(left + mViewTopLeft[0], top + mViewTopLeft[1],
-                            right + mViewTopLeft[0], bottom + mViewTopLeft[1]);
-                }
-            } else {
-                mNextCursorRect.set(left, top, right, bottom);
-            }
-            if (!Objects.equals(mCursorRect, mNextCursorRect)) {
-                if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mNextCursorRect);
+
+            mTmpCursorRect.set(left, top, right, bottom);
+            if (!mCursorRect.equals(mTmpCursorRect)) {
+                if (DEBUG) Log.d(TAG, "updateCursor");
+
                 try {
-                    mCurMethod.updateCursor(mNextCursorRect);
-                    mCursorRect.set(mNextCursorRect);
+                    if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
+                    mCurMethod.updateCursor(mTmpCursorRect);
+                    mCursorRect.set(mTmpCursorRect);
                 } catch (RemoteException e) {
                     Log.w(TAG, "IME died: " + mCurId, e);
                 }
@@ -1652,8 +1607,8 @@
             }
             // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
             // not been changed from the previous call.
-            final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
-                    CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+            final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
+                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
             if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
                 // TODO: Consider always emitting this message once we have addressed redundant
                 // calls of this method from android.widget.Editor.
@@ -1668,8 +1623,8 @@
                 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
                 mCursorAnchorInfo = cursorAnchorInfo;
                 // Clear immediate bit (if any).
-                mCursorAnchorInfoMonitorMode &=
-                        ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
+                mRequestUpdateCursorAnchorInfoMonitorMode &=
+                        ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE;
             } catch (RemoteException e) {
                 Log.w(TAG, "IME died: " + mCurId, e);
             }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 60ef693..eb93745 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -65,7 +65,6 @@
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -5718,8 +5717,8 @@
         }
 
         @Override
-        public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
-            return getTarget().requestCursorAnchorInfo(request);
+        public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+            return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode);
         }
     }
 
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f4a478a..49d47fe 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -386,7 +386,9 @@
         mCurrentDate.set(Calendar.YEAR, year);
         mCurrentDate.set(Calendar.MONTH, month);
         mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-        mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+        if (mDateChangedListener != null) {
+            mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+        }
         updateDisplay(false);
     }
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3f5f045..29c8298 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1298,25 +1298,6 @@
                         reported = reportExtractedText();
                     }
                 }
-
-                if (imm.isWatchingCursor(mTextView) && highlight != null) {
-                    highlight.computeBounds(ims.mTmpRectF, true);
-                    ims.mTmpOffset[0] = ims.mTmpOffset[1] = 0;
-
-                    canvas.getMatrix().mapPoints(ims.mTmpOffset);
-                    ims.mTmpRectF.offset(ims.mTmpOffset[0], ims.mTmpOffset[1]);
-
-                    ims.mTmpRectF.offset(0, cursorOffsetVertical);
-
-                    ims.mCursorRectInWindow.set((int)(ims.mTmpRectF.left + 0.5),
-                            (int)(ims.mTmpRectF.top + 0.5),
-                            (int)(ims.mTmpRectF.right + 0.5),
-                            (int)(ims.mTmpRectF.bottom + 0.5));
-
-                    imm.updateCursor(mTextView,
-                            ims.mCursorRectInWindow.left, ims.mCursorRectInWindow.top,
-                            ims.mCursorRectInWindow.right, ims.mCursorRectInWindow.bottom);
-                }
             }
         }
 
@@ -4136,7 +4117,6 @@
 
     static class InputMethodState {
         Rect mCursorRectInWindow = new Rect();
-        RectF mTmpRectF = new RectF();
         float[] mTmpOffset = new float[2];
         ExtractedTextRequest mExtractedTextRequest;
         final ExtractedText mExtractedText = new ExtractedText();
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 376e5b4..1b89179 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -73,16 +73,6 @@
     private boolean mHourWithTwoDigit;
     private char mHourFormat;
 
-    /**
-     * A no-op callback used in the constructor to avoid null checks later in
-     * the code.
-     */
-    private static final TimePicker.OnTimeChangedListener NO_OP_CHANGE_LISTENER =
-            new TimePicker.OnTimeChangedListener() {
-                public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
-                }
-            };
-
     public TimePickerClockDelegate(TimePicker delegator, Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(delegator, context);
@@ -216,8 +206,6 @@
         updateMinuteControl();
         updateAmPmControl();
 
-        setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
-
         // set to current time
         setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
         setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 897381d..b1f5d90 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -25,7 +25,6 @@
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 
@@ -55,7 +54,7 @@
     private static final int DO_REPORT_FULLSCREEN_MODE = 100;
     private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
     private static final int DO_CLEAR_META_KEY_STATES = 130;
-    private static final int DO_REQUEST_CURSOR_ANCHOR_INFO = 140;
+    private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
 
     private WeakReference<InputConnection> mInputConnection;
 
@@ -177,9 +176,10 @@
         dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
     }
 
-    public void requestCursorAnchorInfo(CursorAnchorInfoRequest request, int seq,
+    public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
             IInputContextCallback callback) {
-        dispatchMessage(obtainMessageOSC(DO_REQUEST_CURSOR_ANCHOR_INFO, request, seq, callback));
+        dispatchMessage(obtainMessageISC(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode,
+                seq, callback));
     }
 
     void dispatchMessage(Message msg) {
@@ -427,18 +427,17 @@
                         (Bundle)args.arg2);
                 return;
             }
-            case DO_REQUEST_CURSOR_ANCHOR_INFO: {
+            case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
                 SomeArgs args = (SomeArgs)msg.obj;
                 try {
                     InputConnection ic = mInputConnection.get();
                     if (ic == null || !isActive()) {
                         Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
-                        args.callback.setRequestCursorAnchorInfoResult(0, args.seq);
+                        args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
                         return;
                     }
-                    args.callback.setRequestCursorAnchorInfoResult(
-                            ic.requestCursorAnchorInfo((CursorAnchorInfoRequest)args.arg1),
-                            args.seq);
+                    args.callback.setRequestUpdateCursorAnchorInfoResult(
+                            ic.requestUpdateCursorAnchorInfo(msg.arg1), args.seq);
                 } catch (RemoteException e) {
                     Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
                 }
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index c06596a..fd2b513 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -20,7 +20,6 @@
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.ExtractedTextRequest;
 
 import com.android.internal.view.IInputContextCallback;
@@ -74,6 +73,6 @@
 
     void getSelectedText(int flags, int seq, IInputContextCallback callback);
 
-    void requestCursorAnchorInfo(in CursorAnchorInfoRequest request, int seq,
+    void requestUpdateCursorAnchorInfo(in int cursorUpdateMode, int seq,
             IInputContextCallback callback);
 }
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
index ab2fbdc..54ea306 100644
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ b/core/java/com/android/internal/view/IInputContextCallback.aidl
@@ -27,5 +27,5 @@
     void setCursorCapsMode(int capsMode, int seq);
     void setExtractedText(in ExtractedText extractedText, int seq);
     void setSelectedText(CharSequence selectedText, int seq);
-    void setRequestCursorAnchorInfoResult(int result, int seq);
+    void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq);
 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 8535a98..a8526c8 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -23,7 +23,6 @@
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
@@ -41,7 +40,7 @@
         public CharSequence mSelectedText;
         public ExtractedText mExtractedText;
         public int mCursorCapsMode;
-        public int mCursorAnchorInfoRequestResult;
+        public boolean mRequestUpdateCursorAnchorInfoResult;
         
         // A 'pool' of one InputContextCallback.  Each ICW request will attempt to gain
         // exclusive access to this object.
@@ -155,10 +154,10 @@
             }
         }
 
-        public void setRequestCursorAnchorInfoResult(int result, int seq) {
+        public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
             synchronized (this) {
                 if (seq == mSeq) {
-                    mCursorAnchorInfoRequestResult = result;
+                    mRequestUpdateCursorAnchorInfoResult = result;
                     mHaveValue = true;
                     notifyAll();
                 } else {
@@ -429,21 +428,21 @@
         }
     }
 
-    public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
-        int value = CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        boolean result = false;
         try {
             InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.requestCursorAnchorInfo(request, callback.mSeq, callback);
+            mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
             synchronized (callback) {
                 callback.waitForResultLocked();
                 if (callback.mHaveValue) {
-                    value = callback.mCursorAnchorInfoRequestResult;
+                    result = callback.mRequestUpdateCursorAnchorInfoResult;
                 }
             }
             callback.dispose();
         } catch (RemoteException e) {
-            return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+            return false;
         }
-        return value;
+        return result;
     }
 }
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index bfe0090..2967938 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -25,9 +25,9 @@
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputConnection;
 import android.widget.TextView;
 
 public class EditableInputConnection extends BaseInputConnection {
@@ -188,24 +188,17 @@
     }
 
     @Override
-    public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
-        if (DEBUG) Log.v(TAG, "requestCursorAnchorInfo " + request);
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);
 
-        // This implementation supports TYPE_CURSOR_ANCHOR_INFO only. Other events will be
-        // delegated to the super class.
-        if (request == null ||
-                request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_ANCHOR_INFO) {
-            return super.requestCursorAnchorInfo(request);
-        }
         if (mIMM == null) {
             // In this case, TYPE_CURSOR_ANCHOR_INFO is not handled.
-            // TODO: Return some notification code for the input method that indicates
+            // TODO: Return some notification code rather than false to indicate method that
             // CursorAnchorInfo is temporarily unavailable.
-            return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+            return false;
         }
-        final int flags = request.getRequestFlags();
-        mIMM.setCursorAnchorInfoMonitorMode(flags);
-        if ((flags & CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
+        mIMM.setUpdateCursorAnchorInfoMode(cursorUpdateMode);
+        if ((cursorUpdateMode & InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
             if (mTextView == null) {
                 // In this case, FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE is silently ignored.
                 // TODO: Return some notification code for the input method that indicates
@@ -220,6 +213,6 @@
                 mTextView.requestLayout();
             }
         }
-        return CursorAnchorInfoRequest.RESULT_SCHEDULED;
+        return true;
     }
 }
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 5bd38f3..8b9f574 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -236,10 +236,10 @@
     return (jboolean) !setNetworkForResolv(netId);
 }
 
-static jboolean android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket,
+static jint android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket,
         jint netId)
 {
-    return (jboolean) !setNetworkForSocket(netId, socket);
+    return setNetworkForSocket(netId, socket);
 }
 
 static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint socket)
@@ -263,7 +263,7 @@
     { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
     { "getNetworkBoundToProcess", "()I", (void*) android_net_utils_getNetworkBoundToProcess },
     { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
-    { "bindSocketToNetwork", "(II)Z", (void*) android_net_utils_bindSocketToNetwork },
+    { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
 };
 
diff --git a/core/res/res/color/switch_thumb_material_dark.xml b/core/res/res/color/switch_thumb_material_dark.xml
new file mode 100644
index 0000000..8fede70
--- /dev/null
+++ b/core/res/res/color/switch_thumb_material_dark.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/switch_thumb_disabled_material_dark"/>
+    <item android:color="@color/switch_thumb_normal_material_dark"/>
+</selector>
diff --git a/core/res/res/color/switch_thumb_material_light.xml b/core/res/res/color/switch_thumb_material_light.xml
new file mode 100644
index 0000000..1a34b74
--- /dev/null
+++ b/core/res/res/color/switch_thumb_material_light.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/switch_thumb_disabled_material_light"/>
+    <item android:color="@color/switch_thumb_normal_material_light"/>
+</selector>
diff --git a/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 8af9ceb4..5e67395 100644
--- a/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
index 81c78c6..9c2ee13 100644
--- a/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
index 7bcebcd..ce577e5 100644
--- a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
index eb1d945..7c305ab 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 22992c0..cb8f78a 100644
--- a/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
index f44a2c2..64d4c81 100644
--- a/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
index ef4ebc0..d7faacf 100644
--- a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
index 9ddbcf5..0a36039 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 2d79d59..8e7862f 100644
--- a/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 36f9753..95cb83f 100644
--- a/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
index 1a2546f..33c1035 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
index 500ec33..0226f84 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 9c0b19e..eb495c6 100644
--- a/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 0edb4b8..c2268af 100644
--- a/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
index cd5b00f..b6efff3 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
index 5ee867c..2b253fb 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 78c5ebd..fbcd7d4 100644
--- a/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 36974b7..ebc9bf7 100644
--- a/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_borderless_material.xml b/core/res/res/drawable/btn_borderless_material.xml
index 47cc455..016f0ff 100644
--- a/core/res/res/drawable/btn_borderless_material.xml
+++ b/core/res/res/drawable/btn_borderless_material.xml
@@ -15,10 +15,7 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:insetLeft="@dimen/control_inset_material"
-       android:insetTop="@dimen/control_inset_material"
-       android:insetBottom="@dimen/control_inset_material"
-       android:insetRight="@dimen/control_inset_material">
+       android:inset="@dimen/control_inset_material">
     <ripple android:color="?attr/colorControlHighlight">
         <item android:id="@id/mask"
               android:drawable="@drawable/btn_default_mtrl_shape" />
diff --git a/core/res/res/drawable/btn_default_material.xml b/core/res/res/drawable/btn_default_material.xml
index b04d4fb..d00a348 100644
--- a/core/res/res/drawable/btn_default_material.xml
+++ b/core/res/res/drawable/btn_default_material.xml
@@ -15,10 +15,7 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:insetLeft="@dimen/control_inset_material"
-       android:insetTop="@dimen/control_inset_material"
-       android:insetBottom="@dimen/control_inset_material"
-       android:insetRight="@dimen/control_inset_material">
+       android:inset="@dimen/control_inset_material">
     <ripple android:color="?attr/colorControlHighlight">
         <item android:drawable="@drawable/btn_default_mtrl_shape" />
     </ripple>
diff --git a/core/res/res/drawable/btn_toggle_material.xml b/core/res/res/drawable/btn_toggle_material.xml
index a9951e7..9726782 100644
--- a/core/res/res/drawable/btn_toggle_material.xml
+++ b/core/res/res/drawable/btn_toggle_material.xml
@@ -15,10 +15,7 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:insetLeft="@dimen/control_inset_material"
-       android:insetTop="@dimen/control_inset_material"
-       android:insetBottom="@dimen/control_inset_material"
-       android:insetRight="@dimen/control_inset_material">
+       android:inset="@dimen/control_inset_material">
     <layer-list android:paddingMode="stack">
         <item>
             <ripple android:color="?attr/colorControlHighlight">
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index eaf5e45..bbc7301 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -15,10 +15,7 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:insetLeft="@dimen/control_inset_material"
-    android:insetTop="@dimen/control_inset_material"
-    android:insetBottom="@dimen/control_inset_material"
-    android:insetRight="@dimen/control_inset_material">
+        android:inset="@dimen/control_inset_material">
     <ripple android:color="?attr/colorControlActivated">
         <item>
             <selector>
diff --git a/core/res/res/drawable/spinner_textfield_background_material.xml b/core/res/res/drawable/spinner_textfield_background_material.xml
index f818baf..5bdff4a 100644
--- a/core/res/res/drawable/spinner_textfield_background_material.xml
+++ b/core/res/res/drawable/spinner_textfield_background_material.xml
@@ -14,18 +14,20 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:autoMirrored="true">
-    <item android:state_checked="true">
-        <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
-    <item android:state_pressed="true">
-        <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
-    <item>
-        <nine-patch android:src="@drawable/spinner_textfield_default_mtrl_alpha"
-            android:tint="?attr/colorControlNormal" />
-    </item>
-</selector>
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:inset="@dimen/control_inset_material">
+    <selector android:autoMirrored="true">
+        <item android:state_checked="true">
+            <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
+                android:tint="?attr/colorControlActivated" />
+        </item>
+        <item android:state_pressed="true">
+            <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
+                android:tint="?attr/colorControlActivated" />
+        </item>
+        <item>
+            <nine-patch android:src="@drawable/spinner_textfield_default_mtrl_alpha"
+                android:tint="?attr/colorControlNormal" />
+        </item>
+    </selector>
+</inset>
diff --git a/core/res/res/drawable/switch_thumb_material_anim.xml b/core/res/res/drawable/switch_thumb_material_anim.xml
index 30bc8882..0d4d78e 100644
--- a/core/res/res/drawable/switch_thumb_material_anim.xml
+++ b/core/res/res/drawable/switch_thumb_material_anim.xml
@@ -16,22 +16,12 @@
 
 <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
     android:constantSize="true">
-    <item
-        android:state_enabled="false"
-        android:state_checked="true">
-        <nine-patch
-            android:src="@drawable/btn_switch_to_on_mtrl_00012"
-            android:gravity="center"
-            android:tintMode="multiply"
-            android:tint="?attr/colorControlActivated"
-            android:alpha="?attr/disabledAlpha" />
-    </item>
-    <item android:state_enabled="false">
+    <item android:state_enabled="false" android:id="@+id/off">
         <nine-patch
             android:src="@drawable/btn_switch_to_on_mtrl_00001"
             android:gravity="center"
             android:tintMode="multiply"
-            android:tint="?attr/colorButtonNormal" />
+            android:tint="?attr/colorSwitchThumbNormal" />
     </item>
     <item
         android:state_checked="true"
@@ -47,29 +37,29 @@
             android:src="@drawable/btn_switch_to_on_mtrl_00001"
             android:gravity="center"
             android:tintMode="multiply"
-            android:tint="?attr/colorButtonNormal" />
+            android:tint="?attr/colorSwitchThumbNormal" />
     </item>
     <transition
         android:fromId="@+id/off"
         android:toId="@+id/on">
         <animation-list>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
                 <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
@@ -112,22 +102,22 @@
                 <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
             <item android:duration="15">
-                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+                <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
             </item>
         </animation-list>
     </transition>
diff --git a/core/res/res/drawable/switch_track_material.xml b/core/res/res/drawable/switch_track_material.xml
index 0728055..1ec2f88 100644
--- a/core/res/res/drawable/switch_track_material.xml
+++ b/core/res/res/drawable/switch_track_material.xml
@@ -15,10 +15,10 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:state_checked="true">
+    <item android:state_enabled="false">
         <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
-            android:tint="?attr/colorControlActivated"
-            android:alpha="0.2" />
+            android:tint="?attr/colorForeground"
+            android:alpha="0.1" />
     </item>
     <item android:state_checked="true">
         <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
@@ -27,7 +27,7 @@
     </item>
     <item>
         <nine-patch android:src="@drawable/switch_track_mtrl_alpha"
-            android:tint="?attr/colorButtonNormal"
+            android:tint="?attr/colorForeground"
             android:alpha="0.3" />
     </item>
 </selector>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 4aac79d..423e250 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -33,4 +33,5 @@
         <item>83</item>
     </string-array>
 
+    <bool name="config_auto_attach_data_on_creation">false</bool>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 1c83644..e5af60b 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -43,4 +43,5 @@
          provisioning, availability etc -->
     <bool name="config_mobile_allow_volte_vt">false</bool>
 
+    <bool name="config_auto_attach_data_on_creation">false</bool>
 </resources>
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index 21235ec..2317d1f 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -35,9 +35,9 @@
     <item type="dimen" name="dialog_fixed_height_minor">90%</item>
 
     <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">640dp</dimen>
+    <dimen name="thumbnail_width">420dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">640dp</dimen>
+    <dimen name="thumbnail_height">420dp</dimen>
 
     <!-- Preference activity, vertical padding for the header list -->
     <dimen name="preference_screen_header_vertical_padding">32dp</dimen>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index a501fac..377982a 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -20,6 +20,8 @@
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Leanback.Settings.Dialog.Alert" />
     <style name="Theme.Material.Dialog" parent="Theme.Leanback.Dialog" />
     <style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Light.Dialog" />
+    <style name="Theme.Material.Settings.Dialog" parent="Theme.Leanback.Settings.Dialog" />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 327782d..f843d1f 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -506,12 +506,24 @@
 
     <!-- Used in LocalePicker -->
     <string-array translatable="false" name="special_locale_codes">
+        <!-- http://b/17150708 - ensure that the list of languages says "Arabic"
+             rather than "Arabic (Egypt)". If you're an OEM supporting multiple
+             Arabic locales, you should remove this entry so that ar_EG is shown
+             as "Arabic (Egypt)" in Settings. -->
+        <item>ar_EG</item>
+
         <item>zh_CN</item>
         <item>zh_TW</item>
     </string-array>
 
     <!-- Used in LocalePicker -->
     <string-array translatable="false" name="special_locale_names">
+        <!-- http://b/17150708 - ensure that the list of languages says "Arabic"
+             rather than "Arabic (Egypt)". If you're an OEM supporting multiple
+             Arabic locales, you should remove this entry so that ar_EG is shown
+             as "Arabic (Egypt)" in Settings. -->
+        <item>العربية</item>
+
         <item>中文 (简体)</item>
         <item>中文 (繁體)</item>
     </string-array>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b00d7e8..3524636 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -517,6 +517,10 @@
              {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
         <attr name="windowAllowExitTransitionOverlap" format="boolean"/>
 
+        <!-- Indicates whether or not shared elements should use an overlay
+             during transitions. The default value is true. -->
+        <attr name="windowSharedElementsUseOverlay" format="boolean"/>
+
         <!-- Internal layout used internally for window decor -->
         <attr name="windowActionBarFullscreenDecorLayout" format="reference" />
 
@@ -1005,6 +1009,9 @@
         <!-- The color applied to framework buttons in their normal state. -->
         <attr name="colorButtonNormal" format="color" />
 
+        <!-- The color applied to framework switch thumbs in their normal state. -->
+        <attr name="colorSwitchThumbNormal" format="color" />
+
         <!-- ================== -->
         <!-- Hardware rendering -->
         <!-- ================== -->
@@ -1836,6 +1843,10 @@
              {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
         <attr name="windowAllowExitTransitionOverlap"/>
 
+        <!-- Indicates whether or not shared elements should use an overlay
+             during transitions. The default value is true. -->
+        <attr name="windowSharedElementsUseOverlay"/>
+
         <!-- Flag indicating whether this Window is responsible for drawing the background for the
              system bars. If true and the window is not floating, the system bars are drawn with a
              transparent background and the corresponding areas in this window are filled with the
@@ -5597,6 +5608,19 @@
         </attr>
     </declare-styleable>
 
+    <!-- Use <code>changeTransform</code> as the root tag of the XML resource that
+         describes a {@link android.transition.ChangeTransform} transition. -->
+    <declare-styleable name="ChangeTransform">
+        <!-- A parent change should use an overlay or affect the transform of the
+             transitionining View. Default is true. Corresponds to
+             {@link android.transition.ChangeTransform#setReparentWithOverlay(boolean)}. -->
+        <attr name="reparentWithOverlay" format="boolean"/>
+
+        <!-- Tells ChangeTransform to track parent changes. Default is true. Corresponds to
+             {@link android.transition.ChangeTransform#setReparent(boolean)}. -->
+        <attr name="reparent" format="boolean"/>
+    </declare-styleable>
+
     <!-- Use <code>transitionManager</code> as the root tag of the XML resource that
          describes a {@link android.transition.TransitionManager
          TransitionManager}. -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index ccbb8bc..2348951 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -25,6 +25,11 @@
     <color name="button_material_dark">#ff5a595b</color>
     <color name="button_material_light">#ffd6d7d7</color>
 
+    <color name="switch_thumb_normal_material_dark">#ffbdbdbd</color>
+    <color name="switch_thumb_normal_material_light">#fff1f1f1</color>
+    <color name="switch_thumb_disabled_material_dark">#ff616161</color>
+    <color name="switch_thumb_disabled_material_light">#ffbdbdbd</color>
+
     <color name="bright_foreground_material_dark">@color/white</color>
     <color name="bright_foreground_material_light">@color/black</color>
     <!-- White 50% -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cf9a415..df7268f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1675,4 +1675,6 @@
          Examples: <item>311480;prefix</item> <item>310260;suffix</item>
     -->
     <string-array translatable="false" name="no_ems_support_sim_operators" />
+
+    <bool name="config_auto_attach_data_on_creation">true</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6022bdc..6fd2bb1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -19,9 +19,9 @@
 -->
 <resources>
     <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">256dp</dimen>
+    <dimen name="thumbnail_width">192dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">256dp</dimen>
+    <dimen name="thumbnail_height">192dp</dimen>
     <!-- The standard size (both width and height) of an application icon that
          will be displayed in the app launcher and elsewhere. -->
     <dimen name="app_icon_size">48dip</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index c64e910..4c59f73 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -85,4 +85,6 @@
   <item type="id" name="scene_layoutid_cache" />
   <item type="id" name="mask" />
   <item type="id" name="transitionPosition" />
+  <item type="id" name="transitionTransform" />
+  <item type="id" name="parentMatrix" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4f0c5eb..f2466f7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2275,6 +2275,9 @@
   <public type="attr" name="outlineProvider" />
   <public type="attr" name="ageHint" />
   <public type="attr" name="country" />
+  <public type="attr" name="windowSharedElementsUseOverlay" />
+  <public type="attr" name="reparent" />
+  <public type="attr" name="reparentWithOverlay" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index af73c02..b32cd1e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1990,4 +1990,7 @@
   <java-symbol type="color" name="battery_saver_mode_color" />
   <java-symbol type="color" name="system_notification_accent_color" />
   <java-symbol type="dimen" name="text_handle_min_size" />
+  <java-symbol type="id" name="transitionTransform" />
+  <java-symbol type="id" name="parentMatrix" />
+  <java-symbol type="bool" name="config_auto_attach_data_on_creation" />
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b36cdb9..5445816 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -116,12 +116,12 @@
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.Button</item>
-
         <item name="buttonStyleSmall">@style/Widget.Button.Small</item>
         <item name="buttonStyleInset">@style/Widget.Button.Inset</item>
-
         <item name="buttonStyleToggle">@style/Widget.Button.Toggle</item>
 
+        <item name="switchStyle">@style/Widget.CompoundButton.Switch</item>
+
         <item name="selectableItemBackground">@drawable/item_background</item>
         <item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
         <item name="borderlessButtonStyle">?attr/buttonStyle</item>
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index 2b3b8d5..720733f 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -34,6 +34,16 @@
       <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
     </style>
 
+    <style name="Theme.Leanback.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog">
+        <item name="colorBackground">@color/background_leanback_dark</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+        <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+        <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+        <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+        <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+    </style>
+
     <style name="Theme.Leanback.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert">
       <item name="colorBackground">@color/background_leanback_dark</item>
       <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
@@ -54,6 +64,16 @@
       <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
     </style>
 
+    <style name="Theme.Leanback.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert">
+        <item name="colorBackground">@color/background_leanback_light</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_light</item>
+        <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
+        <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+        <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+        <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+        <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+    </style>
+
     <style name="Theme.Leanback.Dialog.AppError" parent="Theme.Leanback.Dialog">
         <item name="windowContentTransitions">false</item>
         <item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 18170ac..23faba8 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -357,10 +357,10 @@
         <item name="timePickerDialogTheme">?attr/dialogTheme</item>
 
         <!-- DatePicker style -->
-        <item name="datePickerStyle">?attr/dialogTheme</item>
+        <item name="datePickerStyle">@style/Widget.Material.DatePicker</item>
 
         <!-- DatePicker dialog theme -->
-        <item name="datePickerDialogTheme">@style/Theme.Material.Dialog.Alert</item>
+        <item name="datePickerDialogTheme">?attr/dialogTheme</item>
 
         <!-- TODO: This belongs in a FastScroll style -->
         <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
@@ -379,6 +379,7 @@
 
         <item name="colorControlHighlight">@color/ripple_material_dark</item>
         <item name="colorButtonNormal">@color/btn_default_material_dark</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
     </style>
 
     <!-- Material theme (light version). -->
@@ -721,6 +722,7 @@
 
         <item name="colorControlHighlight">@color/ripple_material_light</item>
         <item name="colorButtonNormal">@color/btn_default_material_light</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
     </style>
 
     <!-- Variant of the material (light) theme that has a solid (opaque) action bar
@@ -774,6 +776,7 @@
         <item name="colorControlNormal">?attr/textColorSecondary</item>
         <item name="colorControlHighlight">@color/ripple_material_light</item>
         <item name="colorButtonNormal">@color/btn_default_material_light</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
     </style>
 
     <!-- Theme overlay that replaces colors with their dark versions but preserves
@@ -811,6 +814,7 @@
         <item name="colorControlNormal">?attr/textColorSecondary</item>
         <item name="colorControlHighlight">@color/ripple_material_dark</item>
         <item name="colorButtonNormal">@color/btn_default_material_dark</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
     </style>
 
     <!-- Theme overlay that replaces the normal control color, which by default is the same as the
@@ -1192,7 +1196,7 @@
     <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert"/>
 
     <!-- Theme for a presentation window on a secondary display. -->
-    <style name="Theme.Material.Light.Dialog.Presentation" parent="@style/Theme.Material.Light.NoActionBar.Fullscreen" />
+    <style name="Theme.Material.Light.Dialog.Presentation" parent="Theme.Material.Light.NoActionBar.Fullscreen" />
 
     <!-- Default material (dark) for windows that want to have the user's selected
          wallpaper appear behind them.  -->
@@ -1209,7 +1213,47 @@
     </style>
 
     <!-- Default theme for Settings and activities launched from Settings. -->
-    <style name="Theme.Material.Settings" parent="@style/Theme.Material.Light.DarkActionBar">
+    <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
+        <item name="colorPrimary">@color/material_blue_grey_900</item>
+        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorAccent">@color/material_deep_teal_A500</item>
+
+        <item name="dialogTheme">@style/Theme.Material.Settings.Dialog</item>
+        <item name="alertDialogTheme">@style/Theme.Material.Settings.Dialog.Alert</item>
+        <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
+        <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
+        <item name="panelMenuListTheme">@style/Theme.Material.Settings.CompactMenu</item>
+    </style>
+
+    <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
+        <item name="colorPrimary">@color/material_blue_grey_900</item>
+        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorAccent">@color/material_deep_teal_A500</item>
+    </style>
+
+    <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
+
+    <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
+        <item name="colorPrimary">@color/material_blue_grey_900</item>
+        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorAccent">@color/material_deep_teal_A500</item>
+    </style>
+
+    <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
+
+    <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+        <item name="colorPrimary">@color/material_blue_grey_900</item>
+        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorAccent">@color/material_deep_teal_A500</item>
+    </style>
+
+    <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
+        <item name="colorPrimary">@color/material_blue_grey_900</item>
+        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorAccent">@color/material_deep_teal_A500</item>
+    </style>
+
+    <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_A500</item>
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index be2241b..063ac09 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -211,7 +211,7 @@
         final boolean canUseHardware = c.isHardwareAccelerated();
         if (mCanUseHardware != canUseHardware && mCanUseHardware) {
             // We've switched from hardware to non-hardware mode. Panic.
-            cancelHardwareAnimations();
+            cancelHardwareAnimations(true);
         }
         mCanUseHardware = canUseHardware;
 
@@ -231,7 +231,7 @@
         final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
         final int N = pendingAnimations.size();
         if (N > 0) {
-            cancelHardwareAnimations();
+            cancelHardwareAnimations(false);
 
             for (int i = 0; i < N; i++) {
                 pendingAnimations.get(i).setTarget(c);
@@ -399,6 +399,45 @@
         invalidateSelf();
     }
 
+    public void jump() {
+        endSoftwareAnimations();
+        endHardwareAnimations();
+    }
+
+    private void endSoftwareAnimations() {
+        if (mAnimRadius != null) {
+            mAnimRadius.end();
+        }
+
+        if (mAnimOpacity != null) {
+            mAnimOpacity.end();
+        }
+
+        if (mAnimX != null) {
+            mAnimX.end();
+        }
+
+        if (mAnimY != null) {
+            mAnimY.end();
+        }
+    }
+
+    private void endHardwareAnimations() {
+        final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
+        final int N = runningAnimations.size();
+        for (int i = 0; i < N; i++) {
+            runningAnimations.get(i).end();
+        }
+        runningAnimations.clear();
+
+        // Abort any pending animations. Since we always have a completion
+        // listener on a pending animation, we also need to remove ourselves.
+        if (!mPendingAnimations.isEmpty()) {
+            mPendingAnimations.clear();
+            removeSelf();
+        }
+    }
+
     private Paint getTempPaint() {
         if (mTempPaint == null) {
             mTempPaint = new Paint();
@@ -444,7 +483,7 @@
      */
     public void cancel() {
         cancelSoftwareAnimations();
-        cancelHardwareAnimations();
+        cancelHardwareAnimations(true);
     }
 
     private void cancelSoftwareAnimations() {
@@ -468,14 +507,18 @@
     /**
      * Cancels any running hardware animations.
      */
-    private void cancelHardwareAnimations() {
+    private void cancelHardwareAnimations(boolean cancelPending) {
         final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
         final int N = runningAnimations.size();
         for (int i = 0; i < N; i++) {
             runningAnimations.get(i).cancel();
         }
-
         runningAnimations.clear();
+
+        if (cancelPending && !mPendingAnimations.isEmpty()) {
+            mPendingAnimations.clear();
+            removeSelf();
+        }
     }
 
     private void removeSelf() {
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 93df648..49862bc 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -203,7 +203,7 @@
         final boolean canUseHardware = c.isHardwareAccelerated();
         if (mCanUseHardware != canUseHardware && mCanUseHardware) {
             // We've switched from hardware to non-hardware mode. Panic.
-            cancelHardwareAnimations();
+            cancelHardwareAnimations(true);
         }
         mCanUseHardware = canUseHardware;
 
@@ -223,7 +223,7 @@
         final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
         final int N = pendingAnimations.size();
         if (N > 0) {
-            cancelHardwareAnimations();
+            cancelHardwareAnimations(false);
 
             for (int i = 0; i < N; i++) {
                 pendingAnimations.get(i).setTarget(c);
@@ -403,6 +403,41 @@
         invalidateSelf();
     }
 
+    public void jump() {
+        endSoftwareAnimations();
+        endHardwareAnimations();
+    }
+
+    private void endSoftwareAnimations() {
+        if (mAnimOuterOpacity != null) {
+            mAnimOuterOpacity.end();
+        }
+
+        if (mAnimX != null) {
+            mAnimX.end();
+        }
+
+        if (mAnimY != null) {
+            mAnimY.end();
+        }
+    }
+
+    private void endHardwareAnimations() {
+        final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
+        final int N = runningAnimations.size();
+        for (int i = 0; i < N; i++) {
+            runningAnimations.get(i).end();
+        }
+        runningAnimations.clear();
+
+        // Abort any pending animations. Since we always have a completion
+        // listener on a pending animation, we also need to remove ourselves.
+        if (!mPendingAnimations.isEmpty()) {
+            mPendingAnimations.clear();
+            removeSelf();
+        }
+    }
+
     private Paint getTempPaint() {
         if (mTempPaint == null) {
             mTempPaint = new Paint();
@@ -477,7 +512,7 @@
      */
     public void cancel() {
         cancelSoftwareAnimations();
-        cancelHardwareAnimations();
+        cancelHardwareAnimations(true);
     }
 
     private void cancelSoftwareAnimations() {
@@ -497,7 +532,7 @@
     /**
      * Cancels any running hardware animations.
      */
-    private void cancelHardwareAnimations() {
+    private void cancelHardwareAnimations(boolean cancelPending) {
         final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
         final int N = runningAnimations.size();
         for (int i = 0; i < N; i++) {
@@ -505,6 +540,11 @@
         }
 
         runningAnimations.clear();
+
+        if (cancelPending && !mPendingAnimations.isEmpty()) {
+            mPendingAnimations.clear();
+            removeSelf();
+        }
     }
 
     private void removeSelf() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 0447e17..ca32751f 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -199,6 +199,29 @@
     }
 
     @Override
+    public void jumpToCurrentState() {
+        super.jumpToCurrentState();
+
+        if (mRipple != null) {
+            mRipple.jump();
+        }
+
+        if (mBackground != null) {
+            mBackground.jump();
+        }
+
+        mClearingHotspots = true;
+        final int count = mAnimatingRipplesCount;
+        final Ripple[] ripples = mAnimatingRipples;
+        for (int i = 0; i < count; i++) {
+            ripples[i].jump();
+            ripples[i] = null;
+        }
+        mAnimatingRipplesCount = 0;
+        mClearingHotspots = false;
+    }
+
+    @Override
     public void setAlpha(int alpha) {
         super.setAlpha(alpha);
 
@@ -534,18 +557,6 @@
     }
 
     private void clearHotspots() {
-        mClearingHotspots = true;
-
-        final int count = mAnimatingRipplesCount;
-        final Ripple[] ripples = mAnimatingRipples;
-        for (int i = 0; i < count; i++) {
-            // Calling cancel may remove the ripple from the animating ripple
-            // array, so cache the reference before nulling it out.
-            final Ripple ripple = ripples[i];
-            ripples[i] = null;
-            ripple.cancel();
-        }
-
         if (mRipple != null) {
             mRipple.cancel();
             mRipple = null;
@@ -556,8 +567,16 @@
             mBackground = null;
         }
 
-        mClearingHotspots = false;
+        mClearingHotspots = true;
+        final int count = mAnimatingRipplesCount;
+        final Ripple[] ripples = mAnimatingRipples;
+        for (int i = 0; i < count; i++) {
+            ripples[i].cancel();
+            ripples[i] = null;
+        }
         mAnimatingRipplesCount = 0;
+        mClearingHotspots = false;
+
         invalidateSelf();
     }
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index dca7520..977744f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -215,7 +215,10 @@
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingPropertiesChanges(info);
     }
-    uint32_t animatorDirtyMask = mAnimatorManager.animate(info);
+    uint32_t animatorDirtyMask = 0;
+    if (CC_LIKELY(info.runAnimations)) {
+        animatorDirtyMask = mAnimatorManager.animate(info);
+    }
     prepareLayer(info, animatorDirtyMask);
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingDisplayListChanges(info);
@@ -230,7 +233,9 @@
     // Push the animators first so that setupStartValueIfNecessary() is called
     // before properties() is trampled by stagingProperties(), as they are
     // required by some animators.
-    mAnimatorManager.pushStaging(info);
+    if (CC_LIKELY(info.runAnimations)) {
+        mAnimatorManager.pushStaging(info);
+    }
     if (mDirtyPropertyFields) {
         mDirtyPropertyFields = 0;
         damageSelf(info);
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index 06c5ab4..bdac47b 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -196,12 +196,14 @@
     float radius;
     if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
 
-    if (!MathUtils::isPositive(radius)) {
+    bool outlineIsRounded = MathUtils::isPositive(radius);
+    if (!outlineIsRounded || currentTransform()->isSimple()) {
         // TODO: consider storing this rect separately, so that this can't be replaced with clip ops
         clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
-        return;
     }
-    setClippingRoundRect(allocator, bounds, radius);
+    if (outlineIsRounded) {
+        setClippingRoundRect(allocator, bounds, radius);
+    }
 }
 
 void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 331f157..74d52a3 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -65,6 +65,7 @@
         , frameTimeMs(0)
         , animationHook(NULL)
         , prepareTextures(mode == MODE_FULL)
+        , runAnimations(true)
         , damageAccumulator(NULL)
         , renderState(renderState)
         , renderer(NULL)
@@ -76,6 +77,7 @@
         , frameTimeMs(clone.frameTimeMs)
         , animationHook(clone.animationHook)
         , prepareTextures(mode == MODE_FULL)
+        , runAnimations(clone.runAnimations)
         , damageAccumulator(clone.damageAccumulator)
         , renderState(clone.renderState)
         , renderer(clone.renderer)
@@ -88,6 +90,12 @@
     // TODO: Remove this? Currently this is used to signal to stop preparing
     // textures if we run out of cache space.
     bool prepareTextures;
+    // TODO: buildLayer uses this to suppress running any animations, but this
+    // should probably be refactored somehow. The reason this is done is
+    // because buildLayer is not setup for injecting the animationHook, as well
+    // as this being otherwise wasted work as all the animators will be
+    // re-evaluated when the frame is actually drawn
+    bool runAnimations;
 
     // Must not be null during actual usage
     DamageAccumulator* damageAccumulator;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5922135..4bf5a8a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -257,6 +257,7 @@
     info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
     info.damageAccumulator = &mDamageAccumulator;
     info.renderer = mCanvas;
+    info.runAnimations = false;
     node->prepareTree(info);
     SkRect ignore;
     mDamageAccumulator.finish(&ignore);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7bf9e98..96e6ab9 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -94,9 +94,17 @@
  * and {@link #dequeueOutputBuffer} then transfer ownership from the codec
  * to the client.<p>
  * The client is not required to resubmit/release buffers immediately
- * to the codec, the sample code above simply does this for simplicity's sake.<p>
+ * to the codec, the sample code above simply does this for simplicity's sake.
+ * Nonetheless, it is possible that a codec may hold off on generating
+ * output buffers until all outstanding buffers have been
+ * released/resubmitted.
+ * <p>
  * Once the client has an input buffer available it can fill it with data
- * and submit it it to the codec via a call to {@link #queueInputBuffer}.<p>
+ * and submit it it to the codec via a call to {@link #queueInputBuffer}.
+ * Do not submit multiple input buffers with the same timestamp (unless
+ * it is codec-specific data marked as such using the flag
+ * {@link #BUFFER_FLAG_CODEC_CONFIG}).
+ * <p>
  * The codec in turn will return an output buffer to the client in response
  * to {@link #dequeueOutputBuffer}. After the output buffer has been processed
  * a call to {@link #releaseOutputBuffer} will return it to the codec.
@@ -128,18 +136,64 @@
  * {@link #queueInputBuffer}. The codec will continue to return output buffers
  * until it eventually signals the end of the output stream by specifying
  * the same flag ({@link #BUFFER_FLAG_END_OF_STREAM}) on the BufferInfo returned in
- * {@link #dequeueOutputBuffer}.
+ * {@link #dequeueOutputBuffer}.  Do not submit additional input buffers after
+ * signaling the end of the input stream, unless the codec has been flushed,
+ * or stopped and restarted.
  * <p>
+ * <h3>Seeking &amp; Adaptive Playback Support</h3>
+ *
+ * You can check if a decoder supports adaptive playback via {@link
+ * MediaCodecInfo.CodecCapabilities#isFeatureSupported}.  Adaptive playback
+ * is only supported if you configure the codec to decode onto a {@link
+ * android.view.Surface}.
+ *
+ * <h4>For decoders that do not support adaptive playback (including
+ * when not decoding onto a Surface)</h4>
+ *
  * In order to start decoding data that's not adjacent to previously submitted
- * data (i.e. after a seek) it is necessary to {@link #flush} the decoder.
+ * data (i.e. after a seek) <em>one must</em> {@link #flush} the decoder.
  * Any input or output buffers the client may own at the point of the flush are
  * immediately revoked, i.e. after a call to {@link #flush} the client does not
  * own any buffers anymore.
+ * <p>
+ * It is important that the input data after a flush starts at a suitable
+ * stream boundary.  The first frame must be able to be decoded completely on
+ * its own (for most codecs this means an I-frame), and that no frames should
+ * refer to frames before that first new frame.
  * Note that the format of the data submitted after a flush must not change,
  * flush does not support format discontinuities,
- * for this a full {@link #stop}, {@link #configure}, {@link #start}
+ * for this a full {@link #stop}, {@link #configure configure()}, {@link #start}
  * cycle is necessary.
  *
+ * <h4>For decoders that support adaptive playback</h4>
+ *
+ * In order to start decoding data that's not adjacent to previously submitted
+ * data (i.e. after a seek) it is <em>not necessary</em> to {@link #flush} the
+ * decoder.
+ * <p>
+ * It is still important that the input data after the discontinuity starts
+ * at a suitable stream boundary (e.g. I-frame), and that no new frames refer
+ * to frames before the first frame of the new input data segment.
+ * <p>
+ * For some video formats it is also possible to change the picture size
+ * mid-stream.  To do this for H.264, the new Sequence Parameter Set (SPS) and
+ * Picture Parameter Set (PPS) values must be packaged together with an
+ * Instantaneous Decoder Refresh (IDR) frame in a single buffer, which then
+ * can be enqueued as a regular input buffer.
+ * The client will receive an {@link #INFO_OUTPUT_FORMAT_CHANGED} return
+ * value from {@link #dequeueOutputBuffer dequeueOutputBuffer()} or
+ * {@link Callback#onOutputBufferAvailable onOutputBufferAvailable()}
+ * just after the picture-size change takes place and before any
+ * frames with the new size have been returned.
+ * <p>
+ * Be careful when calling {@link #flush} shortly after you have changed
+ * the picture size.  If you have not received confirmation of the picture
+ * size change, you will need to repeat the request for the new picture size.
+ * E.g. for H.264 you will need to prepend the PPS/SPS to the new IDR
+ * frame to ensure that the codec receives the picture size change request.
+ *
+ * <h3>States and error handling</h3>
+ *
  * <p> During its life, a codec conceptually exists in one of the following states:
  * Initialized, Configured, Executing, Error, Uninitialized, (omitting transitory states
  * between them). When created by one of the factory methods,
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index d3b1520..05acf90 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -47,6 +47,7 @@
     private InputStream mInputStream = null;
 
     private boolean mAllowCrossDomainRedirect = true;
+    private boolean mAllowCrossProtocolRedirect = true;
 
     // from com.squareup.okhttp.internal.http
     private final static int HTTP_TEMP_REDIRECT = 307;
@@ -91,6 +92,8 @@
     private boolean filterOutInternalHeaders(String key, String val) {
         if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
             mAllowCrossDomainRedirect = parseBoolean(val);
+            // cross-protocol redirects are also controlled by this flag
+            mAllowCrossProtocolRedirect = mAllowCrossDomainRedirect;
         } else {
             return false;
         }
@@ -190,8 +193,12 @@
                         !url.getProtocol().equals("http")) {
                     throw new NoRouteToHostException("Unsupported protocol redirect");
                 }
+                boolean sameProtocol = mURL.getProtocol().equals(url.getProtocol());
+                if (!mAllowCrossProtocolRedirect && !sameProtocol) {
+                    throw new NoRouteToHostException("Cross-protocol redirects are disallowed");
+                }
                 boolean sameHost = mURL.getHost().equals(url.getHost());
-                if (!sameHost) {
+                if (!mAllowCrossDomainRedirect && !sameHost) {
                     throw new NoRouteToHostException("Cross-domain redirects are disallowed");
                 }
 
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 006b1ee..0d7e6c9 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -27,8 +27,7 @@
     android:layout_height="wrap_content"
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
-    android:gravity="center_horizontal|top"
-    android:contentDescription="@string/keyguard_accessibility_status">
+    android:gravity="center_horizontal|top">
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 55d8d81..a136acf 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -115,8 +115,6 @@
     <string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> widget.</string>
     <!-- Accessibility description of the lock screen user selector widget. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_user_selector">User selector</string>
-    <!-- Accessibility description of the lock screen status widget. [CHAR_LIMIT=none] -->
-    <string name="keyguard_accessibility_status">Status</string>
     <!-- Accessibility description of the camera widget. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_camera">Camera</string>
     <!-- Accessibility description of the lock media control widget. [CHAR_LIMIT=none] -->
@@ -176,6 +174,9 @@
     <!-- Accessibility description announced when user drags widget away from delete drop target [CHAR LIMIT=NONE] -->
     <string name="keyguard_accessibility_delete_widget_end"><xliff:g id="widget_index">%1$s</xliff:g> will not be deleted.</string>
 
+    <!-- Accessibility description for the text view that indicates when the next alarm is set (not shown on screen). [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_next_alarm">Next alarm set for <xliff:g id="alarm" example="Fri 8:30 AM">%1$s</xliff:g></string>
+
     <!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
     <!-- Label for "switch to symbols" key.  Must be short to fit on key! -->
     <string name="password_keyboard_label_symbol_key">\?123</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 51a276e..a0fab42 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -143,7 +143,10 @@
 
     void refreshAlarmStatus(AlarmManager.AlarmClockInfo nextAlarm) {
         if (nextAlarm != null) {
-            mAlarmStatusView.setText(formatNextAlarm(mContext, nextAlarm));
+            String alarm = formatNextAlarm(mContext, nextAlarm);
+            mAlarmStatusView.setText(alarm);
+            mAlarmStatusView.setContentDescription(
+                    getResources().getString(R.string.keyguard_accessibility_next_alarm, alarm));
             mAlarmStatusView.setVisibility(View.VISIBLE);
         } else {
             mAlarmStatusView.setVisibility(View.GONE);
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index ca07c87..ef0c9bb 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -67,6 +67,6 @@
         android:src="@drawable/ic_lock_24dp"
         android:scaleType="center"
         android:tint="#ffffffff"
-        android:contentDescription="@string/accessibility_unlock_button" />
+        android:contentDescription="@string/accessibility_unlock_button_not_secured" />
 
 </com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 40870bf..dea14e9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -105,4 +105,5 @@
     <color name="search_panel_card_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
+    <color name="doze_small_icon_background_color">#ff434343</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 42d9734..52dc000 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -189,6 +189,9 @@
     <!-- Doze: interval between pulses when following the notification light -->
     <integer name="doze_notification_pulse_interval">30000</integer>
 
+    <!-- Doze: alpha to apply to small icons when dozing -->
+    <integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
+
     <!-- Volume: time to delay dismissing the volume panel after a click is performed -->
     <integer name="volume_panel_dismiss_delay">200</integer>
 
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 6418930..4e93cd8 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -34,5 +34,6 @@
     <item type="id" name="alpha_animator_start_value_tag"/>
     <item type="id" name="top_inset_animator_start_value_tag"/>
     <item type="id" name="height_animator_start_value_tag"/>
+    <item type="id" name="doze_saved_filter_tag"/>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8f05f7b..9ff67bb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,8 +213,6 @@
     <string name="accessibility_camera_button">Camera</string>
     <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_phone_button">Phone</string>
-    <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button">Unlock</string>
     <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
     <string name="unlock_label">unlock</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
@@ -222,6 +220,17 @@
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
     <string name="camera_label">open camera</string>
 
+    <!-- Content description of the lock icon when device is secured (lock closed) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button_secured">Device secured.</string>
+    <!-- Content description of the lock icon when device is not secured (lock open) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button_not_secured">Device not secured.</string>
+    <!-- Content description of the lock icon when device is secured (lock closed) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button_secured_trust_managed">Device secured, trust agent active.</string>
+    <!-- Content description of the lock icon when device is not secured (lock open) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button_not_secured_trust_managed">Device not secured, trust agent active.</string>
+    <!-- Content description of the lock icon when face unlock is running (face icon) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button_face_unlock_running">Face detection running, trust agent active.</string>
+
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button">Switch input method button.</string>
     <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 74c0328..fe1e5db 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -76,6 +76,7 @@
     private PendingIntent mNotificationPulseIntent;
     private int mMultipulseCount;
     private int mNotificationPulseInterval;
+    private boolean mPowerSaveActive;
 
     public DozeService() {
         if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -94,6 +95,7 @@
         pw.print("  mNotificationLightOn: "); pw.println(mNotificationLightOn);
         pw.print("  mMultipulseCount: "); pw.println(mMultipulseCount);
         pw.print("  mNotificationPulseInterval: "); pw.println(mNotificationPulseInterval);
+        pw.print("  mPowerSaveActive: "); pw.println(mPowerSaveActive);
     }
 
     @Override
@@ -141,7 +143,13 @@
     @Override
     public void onDreamingStarted() {
         super.onDreamingStarted();
-        if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze());
+        mPowerSaveActive = mHost != null && mHost.isPowerSaveActive();
+        if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive="
+                + mPowerSaveActive);
+        if (mPowerSaveActive) {
+            finishToSavePower();
+            return;
+        }
         mDreaming = true;
         listenForPulseSignals(true);
         requestDoze();
@@ -232,6 +240,11 @@
         }
     }
 
+    private void finishToSavePower() {
+        Log.w(mTag, "Exiting ambient mode due to low power battery saver");
+        finish();
+    }
+
     private void listenForPulseSignals(boolean listen) {
         if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
         mSigMotionSensor.setListening(listen);
@@ -329,6 +342,14 @@
             mNotificationLightOn = on;
             rescheduleNotificationPulse();
         }
+
+        @Override
+        public void onPowerSaveChanged(boolean active) {
+            mPowerSaveActive = active;
+            if (mPowerSaveActive && mDreaming) {
+                finishToSavePower();
+            }
+        }
     };
 
     public interface Host {
@@ -337,11 +358,13 @@
         void requestDoze(DozeService dozeService);
         void requestPulse(int pulses, boolean delayed, DozeService dozeService);
         void dozingStopped(DozeService dozeService);
+        boolean isPowerSaveActive();
 
         public interface Callback {
             void onNewNotifications();
             void onBuzzBeepBlinked();
             void onNotificationLight(boolean on);
+            void onPowerSaveChanged(boolean active);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index c7198fe..d39f64e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -143,7 +143,7 @@
         mBackgroundColor = new ColorDrawable(0);
         // Copy the ripple drawable since we are going to be manipulating it
         mBackground = (RippleDrawable)
-                getResources().getDrawable(R.drawable.recents_task_view_header_bg);
+                getContext().getDrawable(R.drawable.recents_task_view_header_bg);
         mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
         mBackground.setColor(ColorStateList.valueOf(0));
         mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9ac20a6..7d64325 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -120,6 +120,15 @@
         return false;
     }
 
+    @Override
+    public void setDark(boolean dark, boolean fade) {
+        super.setDark(dark, fade);
+        final NotificationContentView showing = getShowingLayout();
+        if (showing != null) {
+            showing.setDark(dark, fade);
+        }
+    }
+
     public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
         mRowMinHeight = rowMinHeight;
         mRowMaxHeight = rowMaxHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index a030f61..548e7d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -17,15 +17,20 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 
 import com.android.systemui.R;
 
@@ -37,6 +42,8 @@
 public class NotificationContentView extends FrameLayout {
 
     private static final long ANIMATION_DURATION_LENGTH = 170;
+    private static final Paint INVERT_PAINT = createInvertPaint();
+    private static final ColorFilter NO_COLOR_FILTER = new ColorFilter();
 
     private final Rect mClipBounds = new Rect();
 
@@ -50,6 +57,7 @@
     private final Interpolator mLinearInterpolator = new LinearInterpolator();
 
     private boolean mContractedVisible = true;
+    private boolean mDark;
 
     private final Paint mFadePaint = new Paint();
 
@@ -192,4 +200,49 @@
     public boolean isContentExpandable() {
         return mExpandedChild != null;
     }
+
+    public void setDark(boolean dark, boolean fade) {
+        if (mDark == dark) return;
+        mDark = dark;
+        setImageViewDark(dark, fade, com.android.internal.R.id.right_icon);
+        setImageViewDark(dark, fade, com.android.internal.R.id.icon);
+    }
+
+    private void setImageViewDark(boolean dark, boolean fade, int imageViewId) {
+        // TODO: implement fade
+        final ImageView v = (ImageView) mContractedChild.findViewById(imageViewId);
+        final Drawable d = v.getBackground();
+        if (dark) {
+            v.setLayerType(LAYER_TYPE_HARDWARE, INVERT_PAINT);
+            if (d != null) {
+                v.setTag(R.id.doze_saved_filter_tag, d.getColorFilter() != null ? d.getColorFilter()
+                        : NO_COLOR_FILTER);
+                d.setColorFilter(getResources().getColor(R.color.doze_small_icon_background_color),
+                        PorterDuff.Mode.SRC_ATOP);
+                v.setImageAlpha(getResources().getInteger(R.integer.doze_small_icon_alpha));
+            }
+        } else {
+            v.setLayerType(LAYER_TYPE_NONE, null);
+            if (d != null)  {
+                final ColorFilter filter = (ColorFilter) v.getTag(R.id.doze_saved_filter_tag);
+                if (filter != null) {
+                    d.setColorFilter(filter == NO_COLOR_FILTER ? null : filter);
+                    v.setTag(R.id.doze_saved_filter_tag, null);
+                }
+                v.setImageAlpha(0xff);
+            }
+        }
+    }
+
+    private static Paint createInvertPaint() {
+        final Paint p = new Paint();
+        final float[] invert = {
+            -1f,  0f,  0f, 1f, 1f,
+             0f, -1f,  0f, 1f, 1f,
+             0f,  0f, -1f, 1f, 1f,
+             0f,  0f,  0f, 1f, 0f
+        };
+        p.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(invert)));
+        return p;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 44d8d23..cb2d40a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -377,11 +377,20 @@
         boolean trustManaged = mUnlockMethodCache.isTrustManaged();
         mTrustDrawable.setTrustManaged(trustManaged);
 
-        // TODO: Update content description depending on state
         updateLockIconClickability();
+        updateLockIconContentDescription(mUnlockMethodCache.isFaceUnlockRunning(),
+                mUnlockMethodCache.isMethodInsecure(), trustManaged);
     }
 
-
+    private void updateLockIconContentDescription(boolean faceUnlockRunning, boolean insecure,
+            boolean trustManaged) {
+        mLockIcon.setContentDescription(getResources().getString(
+                faceUnlockRunning ? R.string.accessibility_unlock_button_face_unlock_running
+                : insecure && !trustManaged ? R.string.accessibility_unlock_button_not_secured
+                : insecure ? R.string.accessibility_unlock_button_not_secured_trust_managed
+                : !trustManaged ? R.string.accessibility_unlock_button_secured
+                : R.string.accessibility_unlock_button_secured_trust_managed));
+    }
 
     public KeyguardAffordanceView getPhoneView() {
         return mPhoneImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b3042b9..80c7c56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -752,6 +752,9 @@
             @Override
             public void onPowerSaveChanged() {
                 mHandler.post(mCheckBarModes);
+                if (mDozeServiceHost != null) {
+                    mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
+                }
             }
             @Override
             public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
@@ -3920,6 +3923,12 @@
 
         private DozeService mCurrentDozeService;
 
+        public void firePowerSaveChanged(boolean active) {
+            for (Callback callback : mCallbacks) {
+                callback.onPowerSaveChanged(active);
+            }
+        }
+
         public void fireBuzzBeepBlinked() {
             for (Callback callback : mCallbacks) {
                 callback.onBuzzBeepBlinked();
@@ -3970,6 +3979,11 @@
             mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget();
         }
 
+        @Override
+        public boolean isPowerSaveActive() {
+            return mBatteryController != null && mBatteryController.isPowerSave();
+        }
+
         private void handleRequestDoze(DozeService dozeService) {
             mCurrentDozeService = dozeService;
             if (!mDozing) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 73358c8..9652ebd 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -267,6 +267,7 @@
     private Boolean mAllowExitTransitionOverlap;
     private Boolean mAllowEnterTransitionOverlap;
     private long mBackgroundFadeDurationMillis = -1;
+    private Boolean mSharedElementsUseOverlay;
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -3546,6 +3547,10 @@
                             R.styleable.Window_windowTransitionBackgroundFadeDuration,
                             DEFAULT_BACKGROUND_FADE_DURATION_MS);
                 }
+                if (mSharedElementsUseOverlay == null) {
+                    mSharedElementsUseOverlay = getWindowStyle().getBoolean(
+                            R.styleable.Window_windowSharedElementsUseOverlay, true);
+                }
             }
         }
     }
@@ -4024,6 +4029,16 @@
         mBackgroundFadeDurationMillis = fadeDurationMillis;
     }
 
+    @Override
+    public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) {
+        mSharedElementsUseOverlay = sharedElementsUseOverlay;
+    }
+
+    @Override
+    public boolean getSharedElementsUseOverlay() {
+        return (mSharedElementsUseOverlay == null) ? true : mSharedElementsUseOverlay;
+    }
+
     private static final class DrawableFeatureState {
         DrawableFeatureState(int _featureId) {
             featureId = _featureId;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 54afe99..1005bd7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4761,7 +4761,9 @@
             result.setType(networkType);
             return result;
         } else {
-           return new NetworkInfo(networkType, 0, "Unknown", "");
+            NetworkInfo result = new NetworkInfo(networkType);
+            result.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+            return result;
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 24b7cb3..fcbe71e 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -773,8 +773,8 @@
         if (newThumbnail != null) {
             if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
                     "Setting thumbnail of " + this + " to " + newThumbnail);
-            task.setLastThumbnail(newThumbnail);
-            if (isPersistable()) {
+            boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail);
+            if (thumbnailUpdated && isPersistable()) {
                 mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
             }
         }
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 0ba62c5..098b0b6 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -94,6 +94,9 @@
             }
             mResult.set(msg.what);
 
+            // Make sure we don't have time timeout still hanging around.
+            removeMessages(FORCE_QUIT);
+
             // If this is a timeout we won't be automatically closed, so go
             // ahead and explicitly dismiss ourselves just in case.
             dismiss();
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 2a8c6fb..d35e09f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -386,15 +386,23 @@
         setNextAffiliate(null);
     }
 
-    void setLastThumbnail(Bitmap thumbnail) {
-        mLastThumbnail = thumbnail;
-        if (thumbnail == null) {
-            if (mLastThumbnailFile != null) {
-                mLastThumbnailFile.delete();
+    /**
+     * Sets the last thumbnail.
+     * @return whether the thumbnail was set
+     */
+    boolean setLastThumbnail(Bitmap thumbnail) {
+        if (mLastThumbnail != thumbnail) {
+            mLastThumbnail = thumbnail;
+            if (thumbnail == null) {
+                if (mLastThumbnailFile != null) {
+                    mLastThumbnailFile.delete();
+                }
+            } else {
+                mService.mTaskPersister.saveImage(thumbnail, mFilename);
             }
-        } else {
-            mService.mTaskPersister.saveImage(thumbnail, mFilename);
+            return true;
         }
+        return false;
     }
 
     void getLastThumbnail(TaskThumbnail thumbs) {
@@ -403,7 +411,8 @@
         if (mLastThumbnail == null) {
             thumbs.mainThumbnail = mService.mTaskPersister.getThumbnail(mFilename);
         }
-        if (mLastThumbnailFile.exists()) {
+        // Only load the thumbnail file if we don't have a thumbnail
+        if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
             try {
                 thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
                         ParcelFileDescriptor.MODE_READ_ONLY);
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ddd0865..9f4ed89 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -639,8 +639,7 @@
                 log("Checking " + url.toString() + " on " +
                         mNetworkAgentInfo.networkInfo.getExtraInfo());
             }
-            url = mNetworkAgentInfo.network.getBoundURL(url);
-            urlConnection = (HttpURLConnection) url.openConnection();
+            urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
             urlConnection.setInstanceFollowRedirects(false);
             urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
             urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index a231945..4e8c46f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -112,6 +112,10 @@
 
     private final HdmiCecStandbyModeHandler mStandbyHandler;
 
+    // If true, do not do routing control/send active source for internal source.
+    // Set to true when the device was woken up by <Text/Image View On>.
+    private boolean mSkipRoutingControl;
+
     // Set of physical addresses of CEC switches on the CEC bus. Managed independently from
     // other CEC devices since they might not have logical address.
     private final ArraySet<Integer> mCecSwitches = new ArraySet<Integer>();
@@ -134,6 +138,7 @@
         mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                 mAddress, mService.getVendorId()));
         mCecSwitches.add(mService.getPhysicalAddress());  // TV is a CEC switch too.
+        mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
         launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
                 reason != HdmiControlService.INITIATED_BY_BOOT_UP);
         launchDeviceDiscovery();
@@ -207,7 +212,10 @@
         // Seq #18
         if (mService.isControlEnabled() && mActiveSource.logicalAddress != mAddress) {
             updateActiveSource(mAddress, mService.getPhysicalAddress());
-            // TODO: Check if this comes from <Text/Image View On> - if true, do nothing.
+            if (mSkipRoutingControl) {
+                mSkipRoutingControl = false;
+                return;
+            }
             HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(
                     mAddress, mService.getPhysicalAddress());
             mService.sendCecCommand(activeSource);
@@ -304,11 +312,13 @@
             invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
             return;
         }
-        // TODO: Return immediately if the operation is triggered by <Text/Image View On>
-        // and this is the first notification about the active input after power-on
-        // (switch to HDMI didn't happen so far but is expected to happen soon).
         int oldPath = getActivePortId() != Constants.INVALID_PORT_ID
                 ? mService.portIdToPath(getActivePortId()) : getDeviceInfo().getPhysicalAddress();
+        setActivePath(oldPath);
+        if (mSkipRoutingControl) {
+            mSkipRoutingControl = false;
+            return;
+        }
         int newPath = mService.portIdToPath(portId);
         HdmiCecMessage routingChange =
                 HdmiCecMessageBuilder.buildRoutingChange(mAddress, oldPath, newPath);
@@ -566,8 +576,6 @@
         if (mService.isPowerStandbyOrTransient() && mAutoWakeup) {
             mService.wakeUp();
         }
-        // TODO: Connect to Hardware input manager to invoke TV App with the appropriate channel
-        //       that represents the source device.
         return true;
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 4c88ce0..8b345cf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -17,7 +17,6 @@
 package com.android.server.hdmi;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
-import android.util.Slog;
 import android.util.SparseArray;
 
 /**
@@ -52,6 +51,7 @@
     }
 
     final SparseArray<ValidationInfo> mValidationInfo = new SparseArray<>();
+    private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
 
     public HdmiCecMessageValidator(HdmiControlService service) {
         mService = service;
@@ -183,32 +183,32 @@
         int opcode = message.getOpcode();
         ValidationInfo info = mValidationInfo.get(opcode);
         if (info == null) {
-            Slog.w(TAG, "No validation information for the message: " + message);
+            mSpamSafeLogger.warning("No validation information for the message: " + message);
             return true;
         }
 
         // Check the source field.
         if (message.getSource() == Constants.ADDR_UNREGISTERED &&
                 (info.addressType & SRC_UNREGISTERED) == 0) {
-            Slog.w(TAG, "Unexpected source: " + message);
+            mSpamSafeLogger.warning("Unexpected source: " + message);
             return false;
         }
         // Check the destination field.
         if (message.getDestination() == Constants.ADDR_BROADCAST) {
             if ((info.addressType & DEST_BROADCAST) == 0) {
-                Slog.w(TAG, "Unexpected broadcast message: " + message);
+                mSpamSafeLogger.warning("Unexpected broadcast message: " + message);
                 return false;
             }
         } else {  // Direct addressing.
             if ((info.addressType & DEST_DIRECT) == 0) {
-                Slog.w(TAG, "Unexpected direct message: " + message);
+                mSpamSafeLogger.warning("Unexpected direct message: " + message);
                 return false;
             }
         }
 
         // Check the parameter type.
         if (!info.parameterValidator.isValid(message.getParams())) {
-            Slog.w(TAG, "Unexpected parameters: " + message);
+            mSpamSafeLogger.warning("Unexpected parameters: " + message);
             return false;
         }
         return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 888ceec3..3dabc11 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -43,6 +43,7 @@
 import android.hardware.hdmi.IHdmiDeviceEventListener;
 import android.hardware.hdmi.IHdmiHotplugEventListener;
 import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener;
 import android.hardware.hdmi.IHdmiRecordListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
 import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -159,41 +160,32 @@
     // Type of logical devices hosted in the system. Stored in the unmodifiable list.
     private final List<Integer> mLocalDevices;
 
-    // List of listeners registered by callers that want to get notified of
-    // hotplug events.
-    @GuardedBy("mLock")
-    private final ArrayList<IHdmiHotplugEventListener> mHotplugEventListeners = new ArrayList<>();
+    private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
 
     // List of records for hotplug event listener to handle the the caller killed in action.
     @GuardedBy("mLock")
     private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords =
             new ArrayList<>();
 
-    // List of listeners registered by callers that want to get notified of
-    // device status events.
-    @GuardedBy("mLock")
-    private final ArrayList<IHdmiDeviceEventListener> mDeviceEventListeners = new ArrayList<>();
-
-    // List of records for device event listener to handle the the caller killed in action.
+    // List of records for device event listener to handle the caller killed in action.
     @GuardedBy("mLock")
     private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords =
             new ArrayList<>();
 
-    // List of records for vendor command listener to handle the the caller killed in action.
+    // List of records for vendor command listener to handle the caller killed in action.
     @GuardedBy("mLock")
     private final ArrayList<VendorCommandListenerRecord> mVendorCommandListenerRecords =
             new ArrayList<>();
 
+    // List of records for MHL Scratchpad command listener to handle the caller killed in action.
     @GuardedBy("mLock")
-    private IHdmiInputChangeListener mInputChangeListener;
+    private final ArrayList<HdmiMhlScratchpadCommandListenerRecord>
+            mScratchpadCommandListenerRecords = new ArrayList<>();
 
     @GuardedBy("mLock")
     private InputChangeListenerRecord mInputChangeListenerRecord;
 
     @GuardedBy("mLock")
-    private IHdmiRecordListener mRecordListener;
-
-    @GuardedBy("mLock")
     private HdmiRecordListenerRecord mRecordListenerRecord;
 
     // Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol
@@ -214,10 +206,6 @@
     @GuardedBy("mLock")
     private List<HdmiDeviceInfo> mMhlDevices;
 
-    // List of listeners registered by callers that want to get notified of
-    // system audio mode changes.
-    private final ArrayList<IHdmiSystemAudioModeChangeListener>
-            mSystemAudioModeChangeListeners = new ArrayList<>();
     // List of records for system audio mode change to handle the the caller killed in action.
     private final ArrayList<SystemAudioModeChangeListenerRecord>
             mSystemAudioModeChangeListenerRecords = new ArrayList<>();
@@ -227,6 +215,9 @@
 
     private final SettingsObserver mSettingsObserver;
 
+    private final HdmiControlBroadcastReceiver
+            mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
+
     @Nullable
     private HdmiCecController mCecController;
 
@@ -248,9 +239,6 @@
 
     private HdmiCecMessageValidator mMessageValidator;
 
-    private final HdmiControlBroadcastReceiver
-            mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
-
     @ServiceThreadOnly
     private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
 
@@ -648,7 +636,7 @@
         if (mMessageValidator.isValid(command)) {
             mCecController.sendCommand(command, callback);
         } else {
-            Slog.e(TAG, "Invalid message type:" + command);
+            mSpamSafeLogger.error("Invalid message type:" + command);
             if (callback != null) {
                 callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
             }
@@ -709,7 +697,7 @@
         }
 
         if (message.getDestination() != Constants.ADDR_BROADCAST) {
-            Slog.w(TAG, "Unhandled cec command:" + message);
+            mSpamSafeLogger.warning("Unhandled cec command:" + message);
         }
         return false;
     }
@@ -788,8 +776,11 @@
     }
 
     void announceSystemAudioModeChange(boolean enabled) {
-        for (IHdmiSystemAudioModeChangeListener listener : mSystemAudioModeChangeListeners) {
-            invokeSystemAudioModeChange(listener, enabled);
+        synchronized (mLock) {
+            for (SystemAudioModeChangeListenerRecord record :
+                    mSystemAudioModeChangeListenerRecords) {
+                invokeSystemAudioModeChangeLocked(record.mListener, enabled);
+            }
         }
     }
 
@@ -914,7 +905,6 @@
         public void binderDied() {
             synchronized (mLock) {
                 mHotplugEventListenerRecords.remove(this);
-                mHotplugEventListeners.remove(mListener);
             }
         }
     }
@@ -930,7 +920,6 @@
         public void binderDied() {
             synchronized (mLock) {
                 mDeviceEventListenerRecords.remove(this);
-                mDeviceEventListeners.remove(mListener);
             }
         }
     }
@@ -946,7 +935,6 @@
         public void binderDied() {
             synchronized (mLock) {
                 mSystemAudioModeChangeListenerRecords.remove(this);
-                mSystemAudioModeChangeListeners.remove(mListener);
             }
         }
     }
@@ -969,14 +957,33 @@
     }
 
     private class HdmiRecordListenerRecord implements IBinder.DeathRecipient {
+        private final IHdmiRecordListener mListener;
+
+        public HdmiRecordListenerRecord(IHdmiRecordListener listener) {
+            mListener = listener;
+        }
+
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                mRecordListener = null;
+                mRecordListenerRecord = null;
             }
         }
     }
 
+    private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient {
+        private final IHdmiMhlScratchpadCommandListener mListener;
+
+        public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) {
+            mListener = listener;
+        }
+
+        @Override
+        public void binderDied() {
+            mScratchpadCommandListenerRecords.remove(this);
+        }
+    }
+
     private void enforceAccessPermission() {
         getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);
     }
@@ -1120,34 +1127,19 @@
         @Override
         public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
             enforceAccessPermission();
-            runOnServiceThread(new Runnable() {
-                @Override
-                public void run() {
-                    HdmiControlService.this.addHotplugEventListener(listener);
-                }
-            });
+            HdmiControlService.this.addHotplugEventListener(listener);
         }
 
         @Override
         public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
             enforceAccessPermission();
-            runOnServiceThread(new Runnable() {
-                @Override
-                public void run() {
-                    HdmiControlService.this.removeHotplugEventListener(listener);
-                }
-            });
+            HdmiControlService.this.removeHotplugEventListener(listener);
         }
 
         @Override
         public void addDeviceEventListener(final IHdmiDeviceEventListener listener) {
             enforceAccessPermission();
-            runOnServiceThread(new Runnable() {
-                @Override
-                public void run() {
-                    HdmiControlService.this.addDeviceEventListener(listener);
-                }
-            });
+            HdmiControlService.this.addDeviceEventListener(listener);
         }
 
         @Override
@@ -1288,12 +1280,7 @@
         public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
                 final int deviceType) {
             enforceAccessPermission();
-            runOnServiceThread(new Runnable() {
-                @Override
-                public void run() {
-                    HdmiControlService.this.addVendorCommandListener(listener, deviceType);
-                }
-            });
+            HdmiControlService.this.addVendorCommandListener(listener, deviceType);
         }
 
         @Override
@@ -1382,6 +1369,38 @@
                 }
             });
         }
+
+        @Override
+        public void sendScratchpadCommand(final int portId, final int offset, final int length,
+                final byte[] data) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (mMhlController == null) {
+                        Slog.w(TAG, "No Mhl controller available.");
+                        return;
+                    }
+                    if (!isControlEnabled()) {
+                        Slog.w(TAG, "Hdmi control is disabled.");
+                        return ;
+                    }
+                    HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
+                    if (device == null) {
+                        Slog.w(TAG, "Invalid port id:" + portId);
+                        return;
+                    }
+                    mMhlController.sendScratchpadCommand(portId, offset, length, data);
+                }
+            });
+        }
+
+        @Override
+        public void addHdmiMhlScratchpadCommandListener(
+                IHdmiMhlScratchpadCommandListener listener) {
+            enforceAccessPermission();
+            HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener);
+        }
     }
 
     @ServiceThreadOnly
@@ -1418,7 +1437,6 @@
         }
         synchronized (mLock) {
             mHotplugEventListenerRecords.add(record);
-            mHotplugEventListeners.add(listener);
         }
     }
 
@@ -1431,7 +1449,6 @@
                     break;
                 }
             }
-            mHotplugEventListeners.remove(listener);
         }
     }
 
@@ -1444,16 +1461,15 @@
             return;
         }
         synchronized (mLock) {
-            mDeviceEventListeners.add(listener);
             mDeviceEventListenerRecords.add(record);
         }
     }
 
     void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
         synchronized (mLock) {
-            for (IHdmiDeviceEventListener listener : mDeviceEventListeners) {
+            for (DeviceEventListenerRecord record : mDeviceEventListenerRecords) {
                 try {
-                    listener.onStatusChanged(device, status);
+                    record.mListener.onStatusChanged(device, status);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Failed to report device event:" + e);
                 }
@@ -1471,7 +1487,6 @@
             return;
         }
         synchronized (mLock) {
-            mSystemAudioModeChangeListeners.add(listener);
             mSystemAudioModeChangeListenerRecords.add(record);
         }
     }
@@ -1486,37 +1501,41 @@
                     break;
                 }
             }
-            mSystemAudioModeChangeListeners.remove(listener);
         }
     }
 
     private final class InputChangeListenerRecord implements IBinder.DeathRecipient {
+        private final IHdmiInputChangeListener mListener;
+
+        public InputChangeListenerRecord(IHdmiInputChangeListener listener) {
+            mListener = listener;
+        }
+
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                mInputChangeListener = null;
+                mInputChangeListenerRecord = null;
             }
         }
     }
 
     private void setInputChangeListener(IHdmiInputChangeListener listener) {
         synchronized (mLock) {
-            mInputChangeListenerRecord = new InputChangeListenerRecord();
+            mInputChangeListenerRecord = new InputChangeListenerRecord(listener);
             try {
                 listener.asBinder().linkToDeath(mInputChangeListenerRecord, 0);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Listener already died");
                 return;
             }
-            mInputChangeListener = listener;
         }
     }
 
     void invokeInputChangeListener(HdmiDeviceInfo info) {
         synchronized (mLock) {
-            if (mInputChangeListener != null) {
+            if (mInputChangeListenerRecord != null) {
                 try {
-                    mInputChangeListener.onChanged(info);
+                    mInputChangeListenerRecord.mListener.onChanged(info);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e);
                 }
@@ -1526,21 +1545,20 @@
 
     private void setHdmiRecordListener(IHdmiRecordListener listener) {
         synchronized (mLock) {
-            mRecordListenerRecord = new HdmiRecordListenerRecord();
+            mRecordListenerRecord = new HdmiRecordListenerRecord(listener);
             try {
                 listener.asBinder().linkToDeath(mRecordListenerRecord, 0);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Listener already died.", e);
             }
-            mRecordListener = listener;
         }
     }
 
     byte[] invokeRecordRequestListener(int recorderAddress) {
         synchronized (mLock) {
-            if (mRecordListener != null) {
+            if (mRecordListenerRecord != null) {
                 try {
-                    return mRecordListener.getOneTouchRecordSource(recorderAddress);
+                    return mRecordListenerRecord.mListener.getOneTouchRecordSource(recorderAddress);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to start record.", e);
                 }
@@ -1551,9 +1569,9 @@
 
     void invokeOneTouchRecordResult(int result) {
         synchronized (mLock) {
-            if (mRecordListener != null) {
+            if (mRecordListenerRecord != null) {
                 try {
-                    mRecordListener.onOneTouchRecordResult(result);
+                    mRecordListenerRecord.mListener.onOneTouchRecordResult(result);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e);
                 }
@@ -1563,9 +1581,9 @@
 
     void invokeTimerRecordingResult(int result) {
         synchronized (mLock) {
-            if (mRecordListener != null) {
+            if (mRecordListenerRecord != null) {
                 try {
-                    mRecordListener.onTimerRecordingResult(result);
+                    mRecordListenerRecord.mListener.onTimerRecordingResult(result);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onTimerRecordingResult.", e);
                 }
@@ -1575,9 +1593,9 @@
 
     void invokeClearTimerRecordingResult(int result) {
         synchronized (mLock) {
-            if (mRecordListener != null) {
+            if (mRecordListenerRecord != null) {
                 try {
-                    mRecordListener.onClearTimerRecordingResult(result);
+                    mRecordListenerRecord.mListener.onClearTimerRecordingResult(result);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onClearTimerRecordingResult.", e);
                 }
@@ -1593,7 +1611,7 @@
         }
     }
 
-    private void invokeSystemAudioModeChange(IHdmiSystemAudioModeChangeListener listener,
+    private void invokeSystemAudioModeChangeLocked(IHdmiSystemAudioModeChangeListener listener,
             boolean enabled) {
         try {
             listener.onStatusChanged(enabled);
@@ -1605,8 +1623,8 @@
     private void announceHotplugEvent(int portId, boolean connected) {
         HdmiHotplugEvent event = new HdmiHotplugEvent(portId, connected);
         synchronized (mLock) {
-            for (IHdmiHotplugEventListener listener : mHotplugEventListeners) {
-                invokeHotplugEventListenerLocked(listener, event);
+            for (HotplugEventListenerRecord record : mHotplugEventListenerRecords) {
+                invokeHotplugEventListenerLocked(record.mListener, event);
             }
         }
     }
@@ -1805,6 +1823,34 @@
         }
     }
 
+    private void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener) {
+        HdmiMhlScratchpadCommandListenerRecord record =
+                new HdmiMhlScratchpadCommandListenerRecord(listener);
+        try {
+            listener.asBinder().linkToDeath(record, 0);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Listener already died.");
+            return;
+        }
+
+        synchronized (mLock) {
+            mScratchpadCommandListenerRecords.add(record);
+        }
+    }
+
+    void invokeScratchpadCommandListeners(int portId, int offest, int length, byte[] data) {
+        synchronized (mLock) {
+            for (HdmiMhlScratchpadCommandListenerRecord record :
+                    mScratchpadCommandListenerRecords) {
+                try {
+                    record.mListener.onReceived(portId, offest, length, data);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to notify scratchpad command", e);
+                }
+            }
+        }
+    }
+
     boolean isProhibitMode() {
         synchronized (mLock) {
             return mProhibitMode;
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
new file mode 100644
index 0000000..36159cb
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+package com.android.server.hdmi;
+
+import android.os.SystemClock;
+import android.util.Pair;
+import android.util.Slog;
+
+import java.util.HashMap;
+
+/**
+ * A logger that prevents spammy log. For the same log message, it logs once every 20seconds.
+ * This class is not thread-safe.
+ */
+final class HdmiLogger {
+    // Logging duration for same error message.
+    private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000;  // 20s
+
+    // Key (String): log message.
+    // Value (Pair(Long, Integer)): a pair of last log time millis and the number of logMessage.
+    // Cache for warning.
+    private final HashMap<String, Pair<Long, Integer>> mWarningTimingCache = new HashMap<>();
+    // Cache for error.
+    private final HashMap<String, Pair<Long, Integer>> mErrorTimingCache = new HashMap<>();
+
+    private final String mTag;
+
+    HdmiLogger(String tag) {
+        mTag = tag;
+    }
+
+    void warning(String logMessage) {
+        long curTime = SystemClock.uptimeMillis();
+        Pair<Long, Integer> timing = mWarningTimingCache.get(logMessage);
+        if (shouldLogNow(timing, curTime)) {
+            Slog.w(mTag, buildMessage(logMessage, timing));
+            mWarningTimingCache.put(logMessage, new Pair<>(curTime, 1));
+        } else {
+            increaseLogCount(mWarningTimingCache, logMessage);
+        }
+    }
+
+    void error(String logMessage) {
+        long curTime = SystemClock.uptimeMillis();
+        Pair<Long, Integer> timing = mErrorTimingCache.get(logMessage);
+        if (shouldLogNow(timing, curTime)) {
+            Slog.e(mTag, buildMessage(logMessage, timing));
+            mErrorTimingCache.put(logMessage, new Pair<>(curTime, 1));
+        } else {
+            increaseLogCount(mErrorTimingCache, logMessage);
+        }
+    }
+
+    private String buildMessage(String message, Pair<Long, Integer> timing) {
+        return new StringBuilder()
+            .append("[").append(timing.second).append("]:").append(message)
+            .toString();
+    }
+
+    private void increaseLogCount(HashMap<String, Pair<Long, Integer>> cache, String message) {
+        Pair<Long, Integer> timing = cache.get(message);
+        if (timing != null) {
+            cache.put(message, new Pair<>(timing.first, timing.second + 1));
+        }
+    }
+
+    private boolean shouldLogNow(Pair<Long, Integer> timing, long curTime) {
+        return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS;
+    }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 14457ec..6771cce 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -162,6 +162,7 @@
         JobStatus jobStatus = new JobStatus(job, uId);
         cancelJob(uId, job.getId());
         startTrackingJob(jobStatus);
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
         return JobScheduler.RESULT_SUCCESS;
     }
 
@@ -507,7 +508,9 @@
                 case MSG_JOB_EXPIRED:
                     synchronized (mJobs) {
                         JobStatus runNow = (JobStatus) message.obj;
-                        if (!mPendingJobs.contains(runNow)) {
+                        // runNow can be null, which is a controller's way of indicating that its
+                        // state is such that all ready jobs should be run immediately.
+                        if (runNow != null && !mPendingJobs.contains(runNow)) {
                             mPendingJobs.add(runNow);
                         }
                     }
diff --git a/services/core/java/com/android/server/job/StateChangedListener.java b/services/core/java/com/android/server/job/StateChangedListener.java
index 90c203a..97dfad3 100644
--- a/services/core/java/com/android/server/job/StateChangedListener.java
+++ b/services/core/java/com/android/server/job/StateChangedListener.java
@@ -33,7 +33,8 @@
     /**
      * Called by the controller to notify the JobManager that regardless of the state of the task,
      * it must be run immediately.
-     * @param jobStatus The state of the task which is to be run immediately.
+     * @param jobStatus The state of the task which is to be run immediately. <strong>null
+     *                  indicates to the scheduler that any ready jobs should be flushed.</strong>
      */
     public void onRunJobNow(JobStatus jobStatus);
 }
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index 538a252..309e034 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -84,15 +84,15 @@
 
     @Override
     public void maybeStartTrackingJob(JobStatus taskStatus) {
+        final boolean isOnStablePower = mChargeTracker.isOnStablePower();
         if (taskStatus.hasChargingConstraint()) {
-            final boolean isOnStablePower = mChargeTracker.isOnStablePower();
             synchronized (mTrackedTasks) {
                 mTrackedTasks.add(taskStatus);
                 taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
             }
-            if (isOnStablePower) {
-                mStateChangedListener.onControllerStateChanged();
-            }
+        }
+        if (isOnStablePower) {
+            mChargeTracker.setStableChargingAlarm();
         }
     }
 
@@ -119,9 +119,15 @@
                 }
             }
         }
+        // Let the scheduler know that state has changed. This may or may not result in an
+        // execution.
         if (reportChange) {
             mStateChangedListener.onControllerStateChanged();
         }
+        // Also tell the scheduler that any ready jobs should be flushed.
+        if (stablePower) {
+            mStateChangedListener.onRunJobNow(null);
+        }
     }
 
     public class ChargingTracker extends BroadcastReceiver {
@@ -196,9 +202,7 @@
                 }
                 // Set up an alarm for ACTION_CHARGING_STABLE - we don't want to kick off tasks
                 // here if the user unplugs the phone immediately.
-                mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                        SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS,
-                        mStableChargingTriggerIntent);
+                setStableChargingAlarm();
                 mCharging = true;
             } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
                 if (DEBUG) {
@@ -211,7 +215,7 @@
             }else if (ACTION_CHARGING_STABLE.equals(action)) {
                 // Here's where we actually do the notify for a task being ready.
                 if (DEBUG) {
-                    Slog.d(TAG, "Battery connected fired @ " + SystemClock.elapsedRealtime()
+                    Slog.d(TAG, "Stable charging fired @ " + SystemClock.elapsedRealtime()
                             + " charging: " + mCharging);
                 }
                 if (mCharging) {  // Should never receive this intent if mCharging is false.
@@ -219,6 +223,17 @@
                 }
             }
         }
+
+        void setStableChargingAlarm() {
+            final long alarmTriggerElapsed =
+                    SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS;
+            if (DEBUG) {
+                Slog.d(TAG, "Setting stable alarm to go off in " +
+                        (STABLE_CHARGING_THRESHOLD_MILLIS / 1000) + "s");
+            }
+            mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTriggerElapsed,
+                    mStableChargingTriggerIntent);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b57a090..32f3707 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5801,6 +5801,29 @@
         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
     }
 
+    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
+        if (rot == Surface.ROTATION_90) {
+            final int tmp = crop.top;
+            crop.top = dw - crop.right;
+            crop.right = crop.bottom;
+            crop.bottom = dw - crop.left;
+            crop.left = tmp;
+        } else if (rot == Surface.ROTATION_180) {
+            int tmp = crop.top;
+            crop.top = dh - crop.bottom;
+            crop.bottom = dh - tmp;
+            tmp = crop.right;
+            crop.right = dw - crop.left;
+            crop.left = dw - tmp;
+        } else if (rot == Surface.ROTATION_270) {
+            final int tmp = crop.top;
+            crop.top = crop.left;
+            crop.left = dh - crop.bottom;
+            crop.bottom = crop.right;
+            crop.right = dh - tmp;
+        }
+    }
+
     /**
      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -5962,21 +5985,31 @@
 
                 // Constrain frame to the screen size.
                 frame.intersect(0, 0, dw, dh);
-                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
-                // of thumbnail is the same as the screen (in landscape) or square.
-                scale = Math.max(width / (float) frame.width(), height / (float) frame.height());
-                dw = (int)(dw * scale);
-                dh = (int)(dh * scale);
+
+                // Tell surface flinger what part of the image to crop. Take the top
+                // right part of the application, and crop the larger dimension to fit.
+                Rect crop = new Rect(frame);
+                if (width / (float) frame.width() < height / (float) frame.height()) {
+                    int cropWidth = (int)((float)width / (float)height * frame.height());
+                    crop.right = crop.left + cropWidth;
+                } else {
+                    int cropHeight = (int)((float)height / (float)width * frame.width());
+                    crop.bottom = crop.top + cropHeight;
+                }
 
                 // The screenshot API does not apply the current screen rotation.
                 rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
                 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-                    final int tmp = dw;
-                    dw = dh;
-                    dh = tmp;
+                    final int tmp = width;
+                    width = height;
+                    height = tmp;
                     rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
                 }
 
+                // Surfaceflinger is not aware of orientation, so convert our logical
+                // crop to surfaceflinger's portrait orientation.
+                convertCropForSurfaceFlinger(crop, rot, dw, dh);
+
                 if (DEBUG_SCREENSHOT) {
                     Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
                             + maxLayer + " appToken=" + appToken);
@@ -5995,7 +6028,7 @@
                 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
                         "Taking screenshot while rotating");
 
-                rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer,
+                rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                         inRotation);
                 if (rawss == null) {
                     Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
@@ -6012,11 +6045,8 @@
         if (DEBUG_SCREENSHOT) {
             bm.eraseColor(0xFF000000);
         }
-        frame.scale(scale);
         Matrix matrix = new Matrix();
-        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
-        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
-        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
+        ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
         Canvas canvas = new Canvas(bm);
         canvas.drawBitmap(rawss, matrix, null);
         canvas.setBitmap(null);
@@ -6042,6 +6072,7 @@
         }
 
         rawss.recycle();
+
         return bm;
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 4b60c9f..5938819 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -267,6 +267,9 @@
             if (mDeviceOwner != null) {
                 out.startTag(null, TAG_DEVICE_OWNER);
                 out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
+                if (mDeviceOwner.name != null) {
+                    out.attribute(null, ATTR_NAME, mDeviceOwner.name);
+                }
                 out.endTag(null, TAG_DEVICE_OWNER);
             }
 
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 4ff3899..f25fc62 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -8,11 +8,13 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+    services.core \
+    services.devicepolicy \
     easymocklib \
     guava \
     mockito-target
 
-LOCAL_JAVA_LIBRARIES := android.test.runner services
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := FrameworksServicesTests
 
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 34b9dae..44accb7 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -163,6 +163,7 @@
      * @return True if the connection was successfully removed.
      */
     public void removeConnection(Connection connection) {
+        Log.d(this, "removing %s from %s", connection, mChildConnections);
         if (connection != null && mChildConnections.remove(connection)) {
             connection.resetConference();
             for (Listener l : mListeners) {
@@ -177,7 +178,7 @@
     public void destroy() {
         Log.d(this, "destroying conference : %s", this);
         // Tear down the children.
-        for (Connection connection : new ArrayList<>(mChildConnections)) {
+        for (Connection connection : mChildConnections) {
             Log.d(this, "removing connection %s", connection);
             removeConnection(connection);
         }
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index c307a25..3aa4baf 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -914,10 +914,11 @@
      */
     public final boolean setConference(Conference conference) {
         // We check to see if it is already part of another conference.
-        if (mConference == null && mConnectionService != null &&
-                mConnectionService.containsConference(conference)) {
+        if (mConference == null) {
             mConference = conference;
-            fireConferenceChanged();
+            if (mConnectionService != null && mConnectionService.containsConference(conference)) {
+                fireConferenceChanged();
+            }
             return true;
         }
         return false;
@@ -929,6 +930,7 @@
      */
     public final void resetConference() {
         if (mConference != null) {
+            Log.d(this, "Conference reset");
             mConference = null;
             fireConferenceChanged();
         }
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index c805978..b77bb18 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -84,6 +84,7 @@
     private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
 
     private boolean mAreAccountsInitialized = false;
+    private Conference sNullConference;
 
     private final IBinder mBinder = new IConnectionService.Stub() {
         @Override
@@ -561,17 +562,29 @@
 
     private void disconnect(String callId) {
         Log.d(this, "disconnect %s", callId);
-        findConnectionForAction(callId, "disconnect").onDisconnect();
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "disconnect").onDisconnect();
+        } else {
+            findConferenceForAction(callId, "disconnect").onDisconnect();
+        }
     }
 
     private void hold(String callId) {
         Log.d(this, "hold %s", callId);
-        findConnectionForAction(callId, "hold").onHold();
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "hold").onHold();
+        } else {
+            findConferenceForAction(callId, "hold").onHold();
+        }
     }
 
     private void unhold(String callId) {
         Log.d(this, "unhold %s", callId);
-        findConnectionForAction(callId, "unhold").onUnhold();
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "unhold").onUnhold();
+        } else {
+            findConferenceForAction(callId, "unhold").onUnhold();
+        }
     }
 
     private void onAudioStateChanged(String callId, AudioState audioState) {
@@ -616,7 +629,10 @@
             return;
         }
 
-        // TODO: Find existing conference call and invoke split(connection).
+        Conference conference = connection.getConference();
+        if (conference != null) {
+            conference.onSeparate(connection);
+        }
     }
 
     private void onPostDialContinue(String callId, boolean proceed) {
@@ -885,4 +901,19 @@
         }
         return sNullConnection;
     }
+
+    private Conference findConferenceForAction(String conferenceId, String action) {
+        if (mConferenceById.containsKey(conferenceId)) {
+            return mConferenceById.get(conferenceId);
+        }
+        Log.w(this, "%s - Cannot find conference %s", action, conferenceId);
+        return getNullConference();
+    }
+
+    private Conference getNullConference() {
+        if (sNullConference == null) {
+            sNullConference = new Conference(null) {};
+        }
+        return sNullConference;
+    }
 }
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index 41c6360..cb63646 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -197,6 +197,7 @@
     void setIsConferenced(String callId, String conferenceCallId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
+                Log.d(this, "sending connection %s with conference %s", callId, conferenceCallId);
                 adapter.setIsConferenced(callId, conferenceCallId);
             } catch (RemoteException ignored) {
             }
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index dcd0b79..767ecf9 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -21,6 +21,8 @@
 import android.os.Parcelable;
 import android.telecomm.VideoProfile;
 
+import com.android.internal.telephony.PhoneConstants;
+
 /**
  * Parcelable object to handle IMS call profile.
  * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
@@ -337,6 +339,38 @@
     }
 
     /**
+     * Translate presentation value to OIR value
+     * @param presentation
+     * @return OIR valuse
+     */
+    public static int presentationToOIR(int presentation) {
+        switch (presentation) {
+            case PhoneConstants.PRESENTATION_RESTRICTED:
+                return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
+            case PhoneConstants.PRESENTATION_ALLOWED:
+                return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
+            default:
+                return ImsCallProfile.OIR_DEFAULT;
+        }
+    }
+
+    /**
+     * Translate OIR value to presentation value
+     * @param oir value
+     * @return presentation value
+     */
+    public static int OIRToPresentation(int oir) {
+        switch(oir) {
+            case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
+                return PhoneConstants.PRESENTATION_RESTRICTED;
+            case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
+                return PhoneConstants.PRESENTATION_ALLOWED;
+            default:
+                return PhoneConstants.PRESENTATION_UNKNOWN;
+        }
+    }
+
+    /**
      * Determines if a video state is set in a video state bit-mask.
      *
      * @param videoState The video state bit mask.
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
index 08d7667..d402699 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
@@ -54,7 +54,7 @@
         for (int i = 0; i < rowIndices.length; i++)
             rowIndices[i] = i * REGION_SIZE;
 
-        mScript = new ScriptC_errorCalculator(mRS, resources, R.raw.errorcalculator);
+        mScript = new ScriptC_errorCalculator(mRS);
         mScript.set_HEIGHT(height);
         mScript.set_WIDTH(width);
         mScript.set_REGION_SIZE(REGION_SIZE);
diff --git a/tests/RenderScriptTests/FountainFbo/Android.mk b/tests/RenderScriptTests/FountainFbo/Android.mk
index 4535eb1..c0f3323 100644
--- a/tests/RenderScriptTests/FountainFbo/Android.mk
+++ b/tests/RenderScriptTests/FountainFbo/Android.mk
@@ -25,5 +25,6 @@
 # LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := RsFountainFbo
+LOCAL_SDK_VERSION := 14
 
 include $(BUILD_PACKAGE)
diff --git a/tests/Split/AndroidManifest.xml b/tests/Split/AndroidManifest.xml
index d5552de..0de8344 100644
--- a/tests/Split/AndroidManifest.xml
+++ b/tests/Split/AndroidManifest.xml
@@ -16,9 +16,9 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.example.split">
-    <application android:label="@string/app_title">
-        <activity android:name="ActivityMain"
+    <application android:label="@string/app_title"
             android:icon="@mipmap/ic_app">
+        <activity android:name="ActivityMain">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index eead68c..b44e2d1 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -561,15 +561,17 @@
         return NO_ERROR;
     }
 
-#if 0
-    printf("Error adding file %s: group %s already exists in leaf=%s path=%s\n",
-            file->getSourceFile().string(),
-            file->getGroupEntry().toDirName(String8()).string(),
-            mLeaf.string(), mPath.string());
-#endif
+    // Check if the version is automatically applied. This is a common source of
+    // error.
+    ConfigDescription withoutVersion = file->getGroupEntry().toParams();
+    withoutVersion.version = 0;
+    AaptConfig::applyVersionForCompatibility(&withoutVersion);
 
-    SourcePos(file->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
-                                               getPrintableSource().string());
+    const sp<AaptFile>& originalFile = mFiles.valueAt(index);
+    SourcePos(file->getSourceFile(), -1)
+            .error("Duplicate file.\n%s: Original is here. %s",
+                   originalFile->getPrintableSource().string(),
+                   (withoutVersion.version != 0) ? "The version qualifier may be implied." : "");
     return UNKNOWN_ERROR;
 }
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 869a6fc..1d93b89 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1399,7 +1399,8 @@
             sp<ApkSplit>& split = splits.editItemAt(i);
             sp<AaptFile> flattenedTable = new AaptFile(String8("resources.arsc"),
                     AaptGroupEntry(), String8());
-            err = table.flatten(bundle, split->getResourceFilter(), flattenedTable);
+            err = table.flatten(bundle, split->getResourceFilter(),
+                    flattenedTable, split->isBase());
             if (err != NO_ERROR) {
                 fprintf(stderr, "Failed to generate resource table for split '%s'\n",
                         split->getPrintableName().string());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 49d8699..b3c364b 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2074,10 +2074,11 @@
     return mNumLocal > 0;
 }
 
-sp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter)
+sp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+        const bool isBase)
 {
     sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
-    status_t err = flatten(bundle, filter, data);
+    status_t err = flatten(bundle, filter, data, isBase);
     return err == NO_ERROR ? data : NULL;
 }
 
@@ -2699,7 +2700,9 @@
     return err;
 }
 
-status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const sp<AaptFile>& dest)
+status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+        const sp<AaptFile>& dest,
+        const bool isBase)
 {
     const ConfigDescription nullConfig;
 
@@ -2768,6 +2771,13 @@
                 configTypeName = "2value";
             }
 
+            // mipmaps don't get filtered, so they will
+            // allways end up in the base. Make sure they
+            // don't end up in a split.
+            if (typeName == mipmap16 && !isBase) {
+                continue;
+            }
+
             const bool filterable = (typeName != mipmap16);
 
             const size_t N = t->getOrderedConfigs().size();
@@ -2871,10 +2881,12 @@
             return amt;
         }
 
-        status_t err = flattenLibraryTable(data, libraryPackages);
-        if (err != NO_ERROR) {
-            fprintf(stderr, "ERROR: failed to write library table\n");
-            return err;
+        if (isBase) {
+            status_t err = flattenLibraryTable(data, libraryPackages);
+            if (err != NO_ERROR) {
+                fprintf(stderr, "ERROR: failed to write library table\n");
+                return err;
+            }
         }
 
         // Build the type chunks inside of this package.
@@ -2890,6 +2902,7 @@
                 continue;
             }
             const bool filterable = (typeName != mipmap16);
+            const bool skipEntireType = (typeName == mipmap16 && !isBase);
 
             const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
 
@@ -2927,6 +2940,11 @@
                     if (cl->getPublic()) {
                         typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
                     }
+
+                    if (skipEntireType) {
+                        continue;
+                    }
+
                     const size_t CN = cl->getEntries().size();
                     for (size_t ci=0; ci<CN; ci++) {
                         if (filterable && !filter->match(cl->getEntries().keyAt(ci))) {
@@ -2943,6 +2961,10 @@
                 }
             }
             
+            if (skipEntireType) {
+                continue;
+            }
+
             // We need to write one type chunk for each configuration for
             // which we have entries in this type.
             const size_t NC = t->getUniqueConfigs().size();
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index d4f47ef..3721de4 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -165,7 +165,8 @@
     size_t numLocalResources() const;
     bool hasResources() const;
 
-    sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter);
+    sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+            const bool isBase);
 
     static inline uint32_t makeResId(uint32_t packageId,
                                      uint32_t typeId,
@@ -206,7 +207,8 @@
     void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
     status_t validateLocalizations(void);
 
-    status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const sp<AaptFile>& dest);
+    status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+            const sp<AaptFile>& dest, const bool isBase);
     status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs);
 
     void writePublicDefinitions(const String16& package, FILE* fp);
diff --git a/tools/aapt/tests/ResourceFilter_test.cpp b/tools/aapt/tests/ResourceFilter_test.cpp
index 30697bb..b55379e 100644
--- a/tools/aapt/tests/ResourceFilter_test.cpp
+++ b/tools/aapt/tests/ResourceFilter_test.cpp
@@ -126,3 +126,38 @@
     EXPECT_TRUE(filter.match(config));
 }
 
+TEST(StrongResourceFilterTest, MatchesDensities) {
+    ConfigDescription config;
+    config.density = 160;
+    config.version = 4;
+    std::set<ConfigDescription> configs;
+    configs.insert(config);
+
+    StrongResourceFilter filter(configs);
+
+    ConfigDescription expectedConfig;
+    expectedConfig.density = 160;
+    expectedConfig.version = 4;
+    ASSERT_TRUE(filter.match(expectedConfig));
+}
+
+TEST(StrongResourceFilterTest, MatchOnlyMdpiAndExcludeAllOthers) {
+    std::set<ConfigDescription> configsToMatch;
+    ConfigDescription config;
+    config.density = 160;
+    config.version = 4;
+    configsToMatch.insert(config);
+
+    std::set<ConfigDescription> configsToNotMatch;
+    config.density = 480;
+    configsToNotMatch.insert(config);
+
+    AndResourceFilter filter;
+    filter.addFilter(new InverseResourceFilter(new StrongResourceFilter(configsToNotMatch)));
+    filter.addFilter(new StrongResourceFilter(configsToMatch));
+
+    ConfigDescription expectedConfig;
+    expectedConfig.density = 160;
+    expectedConfig.version = 4;
+    ASSERT_TRUE(filter.match(expectedConfig));
+}