Merge "Editor: Make the Insertion handle start/finish the selection action mode on tap."
diff --git a/api/current.txt b/api/current.txt
index 9f54b85..1ec2930 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8673,6 +8673,7 @@
     field public int descriptionRes;
     field public boolean enabled;
     field public int flags;
+    field public boolean hardwareAccelerated;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
     field public java.lang.String nativeLibraryDir;
@@ -30801,6 +30802,7 @@
     method public int getSpanStart(java.lang.Object);
     method public T[] getSpans(int, int, java.lang.Class<T>);
     method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
+    method public int getTextWatcherDepth();
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence);
     method public int length();
diff --git a/api/system-current.txt b/api/system-current.txt
index 845c4ff..f568ac8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8888,6 +8888,7 @@
     field public int descriptionRes;
     field public boolean enabled;
     field public int flags;
+    field public boolean hardwareAccelerated;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
     field public java.lang.String nativeLibraryDir;
@@ -33157,6 +33158,7 @@
     method public int getSpanStart(java.lang.Object);
     method public T[] getSpans(int, int, java.lang.Class<T>);
     method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
+    method public int getTextWatcherDepth();
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
     method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence);
     method public int length();
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index 1d5ed8a..46c2c6e 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -119,15 +119,13 @@
     }
 
     /**
-     * Flatten the current undo state into a Parcelable object, which can later be restored
-     * with {@link #restoreInstanceState(android.os.Parcelable)}.
+     * Flatten the current undo state into a Parcel object, which can later be restored
+     * with {@link #restoreInstanceState(android.os.Parcel, java.lang.ClassLoader)}.
      */
-    public Parcelable saveInstanceState() {
+    public void saveInstanceState(Parcel p) {
         if (mUpdateCount > 0) {
             throw new IllegalStateException("Can't save state while updating");
         }
-        ParcelableParcel pp = new ParcelableParcel(getClass().getClassLoader());
-        Parcel p = pp.getParcel();
         mStateSeq++;
         if (mStateSeq <= 0) {
             mStateSeq = 0;
@@ -151,7 +149,6 @@
             mRedos.get(i).writeToParcel(p);
         }
         p.writeInt(0);
-        return pp;
     }
 
     void saveOwner(UndoOwner owner, Parcel out) {
@@ -168,26 +165,24 @@
     }
 
     /**
-     * Restore an undo state previously created with {@link #saveInstanceState()}.  This will
-     * restore the UndoManager's state to almost exactly what it was at the point it had
+     * Restore an undo state previously created with {@link #saveInstanceState(Parcel)}.  This
+     * will restore the UndoManager's state to almost exactly what it was at the point it had
      * been previously saved; the only information not restored is the data object
      * associated with each {@link UndoOwner}, which requires separate calls to
      * {@link #getOwner(String, Object)} to re-associate the owner with its data.
      */
-    public void restoreInstanceState(Parcelable state) {
+    public void restoreInstanceState(Parcel p, ClassLoader loader) {
         if (mUpdateCount > 0) {
             throw new IllegalStateException("Can't save state while updating");
         }
         forgetUndos(null, -1);
         forgetRedos(null, -1);
-        ParcelableParcel pp = (ParcelableParcel)state;
-        Parcel p = pp.getParcel();
         mHistorySize = p.readInt();
         mStateOwners = new UndoOwner[p.readInt()];
 
         int stype;
         while ((stype=p.readInt()) != 0) {
-            UndoState ustate = new UndoState(this, p, pp.getClassLoader());
+            UndoState ustate = new UndoState(this, p, loader);
             if (stype == 1) {
                 mUndos.add(0, ustate);
             } else {
@@ -311,12 +306,15 @@
         }
 
         int removed = 0;
-        for (int i=0; i<mUndos.size() && removed < count; i++) {
+        int i = 0;
+        while (i < mUndos.size() && removed < count) {
             UndoState state = mUndos.get(i);
             if (count > 0 && matchOwners(state, owners)) {
                 state.destroy();
                 mUndos.remove(i);
                 removed++;
+            } else {
+                i++;
             }
         }
 
@@ -329,12 +327,15 @@
         }
 
         int removed = 0;
-        for (int i=0; i<mRedos.size() && removed < count; i++) {
+        int i = 0;
+        while (i < mRedos.size() && removed < count) {
             UndoState state = mRedos.get(i);
             if (count > 0 && matchOwners(state, owners)) {
                 state.destroy();
                 mRedos.remove(i);
                 removed++;
+            } else {
+                i++;
             }
         }
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e1a2aa9..5b7896a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -598,6 +598,11 @@
      */
     public int installLocation = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
 
+    /**
+     * True when the application's rendering should be hardware accelerated.
+     */
+    public boolean hardwareAccelerated;
+
     public void dump(Printer pw, String prefix) {
         super.dumpFront(pw, prefix);
         if (className != null) {
@@ -637,6 +642,7 @@
         }
         pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion
                 + " versionCode=" + versionCode);
+        pw.println(prefix + "hardwareAccelerated=" + hardwareAccelerated);
         if (manageSpaceActivityName != null) {
             pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
         }
@@ -722,6 +728,7 @@
         descriptionRes = orig.descriptionRes;
         uiOptions = orig.uiOptions;
         backupAgentName = orig.backupAgentName;
+        hardwareAccelerated = orig.hardwareAccelerated;
     }
 
 
@@ -773,6 +780,7 @@
         dest.writeString(backupAgentName);
         dest.writeInt(descriptionRes);
         dest.writeInt(uiOptions);
+        dest.writeInt(hardwareAccelerated ? 1 : 0);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -823,6 +831,7 @@
         backupAgentName = source.readString();
         descriptionRes = source.readInt();
         uiOptions = source.readInt();
+        hardwareAccelerated = source.readInt() != 0;
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1140756..a245ba5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2519,6 +2519,7 @@
         owner.baseHardwareAccelerated = sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
                 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
+        ai.hardwareAccelerated = owner.baseHardwareAccelerated;
 
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 7ce44e1..992dc4d 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1006,28 +1006,43 @@
         return new String(buf);
     }
 
+    /**
+     * Returns the depth of TextWatcher callbacks. Returns 0 when the object is not handling
+     * TextWatchers. A return value greater than 1 implies that a TextWatcher caused a change that
+     * recursively triggered a TextWatcher.
+     */
+    public int getTextWatcherDepth() {
+        return mTextWatcherDepth;
+    }
+
     private void sendBeforeTextChanged(TextWatcher[] watchers, int start, int before, int after) {
         int n = watchers.length;
 
+        mTextWatcherDepth++;
         for (int i = 0; i < n; i++) {
             watchers[i].beforeTextChanged(this, start, before, after);
         }
+        mTextWatcherDepth--;
     }
 
     private void sendTextChanged(TextWatcher[] watchers, int start, int before, int after) {
         int n = watchers.length;
 
+        mTextWatcherDepth++;
         for (int i = 0; i < n; i++) {
             watchers[i].onTextChanged(this, start, before, after);
         }
+        mTextWatcherDepth--;
     }
 
     private void sendAfterTextChanged(TextWatcher[] watchers) {
         int n = watchers.length;
 
+        mTextWatcherDepth++;
         for (int i = 0; i < n; i++) {
             watchers[i].afterTextChanged(this);
         }
+        mTextWatcherDepth--;
     }
 
     private void sendSpanAdded(Object what, int start, int end) {
@@ -1524,6 +1539,10 @@
     private IdentityHashMap<Object, Integer> mIndexOfSpan;
     private int mLowWaterMark;  // indices below this have not been touched
 
+    // TextWatcher callbacks may trigger changes that trigger more callbacks. This keeps track of
+    // how deep the callbacks go.
+    private int mTextWatcherDepth;
+
     // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned}
     private static final int MARK = 1;
     private static final int POINT = 2;
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 90e1f86..3caf6f0 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
 import android.graphics.NinePatch;
 import android.graphics.Paint;
@@ -32,8 +33,10 @@
  * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
  * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
  * the DisplayList is still holding a native reference to the memory.
+ *
+ * @hide
  */
-class DisplayListCanvas extends HardwareCanvas {
+public class DisplayListCanvas extends Canvas {
     // The recording canvas pool should be large enough to handle a deeply nested
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
@@ -85,7 +88,6 @@
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
 
-
     private DisplayListCanvas() {
         super(nCreateDisplayListRenderer());
     }
@@ -103,6 +105,16 @@
     ///////////////////////////////////////////////////////////////////////////
 
     @Override
+    public boolean isHardwareAccelerated() {
+        return true;
+    }
+
+    @Override
+    public void setBitmap(Bitmap bitmap) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean isOpaque() {
         return false;
     }
@@ -171,7 +183,11 @@
 
     private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
 
-    @Override
+    /**
+     * Invoked before any drawing operation is performed in this canvas.
+     *
+     * @param dirty The dirty rectangle to update, can be null.
+     */
     public void onPreDraw(Rect dirty) {
         if (dirty != null) {
             nPrepareDirty(mNativeCanvasWrapper, dirty.left, dirty.top, dirty.right, dirty.bottom);
@@ -183,7 +199,9 @@
     private static native void nPrepare(long renderer);
     private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom);
 
-    @Override
+    /**
+     * Invoked after all drawing operation have been performed.
+     */
     public void onPostDraw() {
         nFinish(mNativeCanvasWrapper);
     }
@@ -194,7 +212,13 @@
     // Functor
     ///////////////////////////////////////////////////////////////////////////
 
-    @Override
+    /**
+     * Calls the function specified with the drawGLFunction function pointer. This is
+     * functionality used by webkit for calling into their renderer from our display lists.
+     * This function may return true if an invalidation is needed after the call.
+     *
+     * @param drawGLFunction A native function pointer
+     */
     public void callDrawGLFunction2(long drawGLFunction) {
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
     }
@@ -207,7 +231,23 @@
 
     protected static native long nFinishRecording(long renderer);
 
-    @Override
+    /**
+     * Draws the specified display list onto this canvas. The display list can only
+     * be drawn if {@link android.view.RenderNode#isValid()} returns true.
+     *
+     * @param renderNode The RenderNode to replay.
+     */
+    public void drawRenderNode(RenderNode renderNode) {
+        drawRenderNode(renderNode, RenderNode.FLAG_CLIP_CHILDREN);
+    }
+
+    /**
+     * Draws the specified display list onto this canvas.
+     *
+     * @param renderNode The RenderNode to replay.
+     * @param flags Optional flags about drawing, see {@link RenderNode} for
+     *              the possible flags.
+     */
     public void drawRenderNode(RenderNode renderNode, int flags) {
         nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags);
     }
@@ -219,6 +259,14 @@
     // Hardware layer
     ///////////////////////////////////////////////////////////////////////////
 
+    /**
+     * Draws the specified layer onto this canvas.
+     *
+     * @param layer The layer to composite on this canvas
+     * @param x The left coordinate of the layer
+     * @param y The top coordinate of the layer
+     * @param paint The paint used to draw the layer
+     */
     void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
         layer.setLayerPaint(paint);
         nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
@@ -253,7 +301,6 @@
     private static native void nDrawPatch(long renderer, long bitmap, long chunk,
             float left, float top, float right, float bottom, long paint);
 
-    @Override
     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
         nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
@@ -263,7 +310,6 @@
     private static native void nDrawCircle(long renderer, long propCx,
             long propCy, long propRadius, long propPaint);
 
-    @Override
     public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
             CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
             CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 20baad0..d58e7c0 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -46,14 +46,14 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (canvas instanceof HardwareCanvas) {
-            HardwareCanvas hwCanvas = (HardwareCanvas) canvas;
+        if (canvas instanceof DisplayListCanvas) {
+            DisplayListCanvas dlCanvas = (DisplayListCanvas) canvas;
             mView.mRecreateDisplayList = true;
             RenderNode renderNode = mView.getDisplayList();
             if (renderNode.isValid()) {
-                hwCanvas.insertReorderBarrier(); // enable shadow for this rendernode
-                hwCanvas.drawRenderNode(renderNode);
-                hwCanvas.insertInorderBarrier(); // re-disable reordering/shadows
+                dlCanvas.insertReorderBarrier(); // enable shadow for this rendernode
+                dlCanvas.drawRenderNode(renderNode);
+                dlCanvas.insertInorderBarrier(); // re-disable reordering/shadows
             }
         }
     }
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
deleted file mode 100644
index fc2b55b..0000000
--- a/core/java/android/view/HardwareCanvas.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.CanvasProperty;
-import android.graphics.Paint;
-import android.graphics.Rect;
-
-/**
- * Hardware accelerated canvas.
- *
- * @hide
- */
-public abstract class HardwareCanvas extends Canvas {
-
-    /**
-     * Pass a reference to the native renderer to our superclass's
-     * constructor.
-     */
-    protected HardwareCanvas(long renderer) {
-        super(renderer);
-    }
-
-    @Override
-    public boolean isHardwareAccelerated() {
-        return true;
-    }
-
-    @Override
-    public void setBitmap(Bitmap bitmap) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Invoked before any drawing operation is performed in this canvas.
-     *
-     * @param dirty The dirty rectangle to update, can be null.
-     *
-     * @hide
-     */
-    public abstract void onPreDraw(Rect dirty);
-
-    /**
-     * Invoked after all drawing operation have been performed.
-     *
-     * @hide
-     */
-    public abstract void onPostDraw();
-
-    /**
-     * Draws the specified display list onto this canvas. The display list can only
-     * be drawn if {@link android.view.RenderNode#isValid()} returns true.
-     *
-     * @param renderNode The RenderNode to replay.
-     */
-    public void drawRenderNode(RenderNode renderNode) {
-        drawRenderNode(renderNode, RenderNode.FLAG_CLIP_CHILDREN);
-    }
-
-    /**
-     * Draws the specified display list onto this canvas.
-     *
-     * @param renderNode The RenderNode to replay.
-     * @param dirty Ignored, can be null.
-     * @param flags Optional flags about drawing, see {@link RenderNode} for
-     *              the possible flags.
-     *
-     * @hide
-     */
-    public abstract void drawRenderNode(RenderNode renderNode, int flags);
-
-    /**
-     * Draws the specified layer onto this canvas.
-     *
-     * @param layer The layer to composite on this canvas
-     * @param x The left coordinate of the layer
-     * @param y The top coordinate of the layer
-     * @param paint The paint used to draw the layer
-     *
-     * @hide
-     */
-    abstract void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint);
-
-    /**
-     * Calls the function specified with the drawGLFunction function pointer. This is
-     * functionality used by webkit for calling into their renderer from our display lists.
-     * This function may return true if an invalidation is needed after the call.
-     *
-     * @param drawGLFunction A native function pointer
-     *
-     * @hide
-     */
-    public void callDrawGLFunction2(long drawGLFunction) {
-        // Noop - this is done in the display list recorder subclass
-    }
-
-    public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
-            CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
-
-    public abstract void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
-            CanvasProperty<Float> right, CanvasProperty<Float> bottom,
-            CanvasProperty<Float> rx, CanvasProperty<Float> ry,
-            CanvasProperty<Paint> paint);
-
-    public static void setProperty(String name, String value) {
-        DisplayListCanvas.setProperty(name, value);
-    }
-}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index afa7f51..6632f39 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -326,7 +326,7 @@
          *
          * @param canvas The Canvas used to render the view.
          */
-        void onHardwarePreDraw(HardwareCanvas canvas);
+        void onHardwarePreDraw(DisplayListCanvas canvas);
 
         /**
          * Invoked after a view is drawn by a hardware renderer.
@@ -334,7 +334,7 @@
          *
          * @param canvas The Canvas used to render the view.
          */
-        void onHardwarePostDraw(HardwareCanvas canvas);
+        void onHardwarePostDraw(DisplayListCanvas canvas);
     }
 
     /**
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 38867a8..ef98bbc 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -26,7 +26,7 @@
 /**
  * <p>A display list records a series of graphics related operations and can replay
  * them later. Display lists are usually built by recording operations on a
- * {@link HardwareCanvas}. Replaying the operations from a display list avoids
+ * {@link DisplayListCanvas}. Replaying the operations from a display list avoids
  * executing application code on every frame, and is thus much more efficient.</p>
  *
  * <p>Display lists are used internally for all views by default, and are not
@@ -43,7 +43,7 @@
  * affected paragraph needs to be recorded again.</p>
  *
  * <h3>Hardware acceleration</h3>
- * <p>Display lists can only be replayed using a {@link HardwareCanvas}. They are not
+ * <p>Display lists can only be replayed using a {@link DisplayListCanvas}. They are not
  * supported in software. Always make sure that the {@link android.graphics.Canvas}
  * you are using to render a display list is hardware accelerated using
  * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
@@ -53,7 +53,7 @@
  *     HardwareRenderer renderer = myView.getHardwareRenderer();
  *     if (renderer != null) {
  *         DisplayList displayList = renderer.createDisplayList();
- *         HardwareCanvas canvas = displayList.start(width, height);
+ *         DisplayListCanvas canvas = displayList.start(width, height);
  *         try {
  *             // Draw onto the canvas
  *             // For instance: canvas.drawBitmap(...);
@@ -67,8 +67,8 @@
  * <pre class="prettyprint">
  *     protected void onDraw(Canvas canvas) {
  *         if (canvas.isHardwareAccelerated()) {
- *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
- *             hardwareCanvas.drawDisplayList(mDisplayList);
+ *             DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ *             displayListCanvas.drawDisplayList(mDisplayList);
  *         }
  *     }
  * </pre>
@@ -92,7 +92,7 @@
  * <pre class="prettyprint">
  *     private void createDisplayList() {
  *         mDisplayList = DisplayList.create("MyDisplayList");
- *         HardwareCanvas canvas = mDisplayList.start(width, height);
+ *         DisplayListCanvas canvas = mDisplayList.start(width, height);
  *         try {
  *             for (Bitmap b : mBitmaps) {
  *                 canvas.drawBitmap(b, 0.0f, 0.0f, null);
@@ -105,8 +105,8 @@
  *
  *     protected void onDraw(Canvas canvas) {
  *         if (canvas.isHardwareAccelerated()) {
- *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
- *             hardwareCanvas.drawDisplayList(mDisplayList);
+ *             DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ *             displayListCanvas.drawDisplayList(mDisplayList);
  *         }
  *     }
  *
@@ -128,7 +128,7 @@
 public class RenderNode {
     /**
      * Flag used when calling
-     * {@link HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)}
+     * {@link DisplayListCanvas#drawRenderNode
      * When this flag is set, draw operations lying outside of the bounds of the
      * display list will be culled early. It is recommeneded to always set this
      * flag.
@@ -140,29 +140,29 @@
     /**
      * Indicates that the display list is done drawing.
      *
-     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
+     * @see DisplayListCanvas#drawRenderNode(RenderNode, int)
      */
     public static final int STATUS_DONE = 0x0;
 
     /**
      * Indicates that the display list needs another drawing pass.
      *
-     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
+     * @see DisplayListCanvas#drawRenderNode(RenderNode, int)
      */
     public static final int STATUS_DRAW = 0x1;
 
     /**
      * Indicates that the display list needs to re-execute its GL functors.
      *
-     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
-     * @see HardwareCanvas#callDrawGLFunction(long)
+     * @see DisplayListCanvas#drawRenderNode(RenderNode, int)
+     * @see DisplayListCanvas#callDrawGLFunction2(long)
      */
     public static final int STATUS_INVOKE = 0x2;
 
     /**
      * Indicates that the display list performed GL drawing operations.
      *
-     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
+     * @see DisplayListCanvas#drawRenderNode(RenderNode, int)
      */
     public static final int STATUS_DREW = 0x4;
 
@@ -213,7 +213,7 @@
      * stored in this display list.
      *
      * Calling this method will mark the render node invalid until
-     * {@link #end(HardwareCanvas)} is called.
+     * {@link #end(DisplayListCanvas)} is called.
      * Only valid render nodes can be replayed.
      *
      * @param width The width of the recording viewport
@@ -221,11 +221,11 @@
      *
      * @return A canvas to record drawing operations.
      *
-     * @see #end(HardwareCanvas)
+     * @see #end(DisplayListCanvas)
      * @see #isValid()
      */
-    public HardwareCanvas start(int width, int height) {
-        HardwareCanvas canvas = DisplayListCanvas.obtain(this);
+    public DisplayListCanvas start(int width, int height) {
+        DisplayListCanvas canvas = DisplayListCanvas.obtain(this);
         canvas.setViewport(width, height);
         // The dirty rect should always be null for a display list
         canvas.onPreDraw(null);
@@ -240,7 +240,7 @@
      * @see #start(int, int)
      * @see #isValid()
      */
-    public void end(HardwareCanvas endCanvas) {
+    public void end(DisplayListCanvas endCanvas) {
         if (!(endCanvas instanceof DisplayListCanvas)) {
             throw new IllegalArgumentException("Passed an invalid canvas to end!");
         }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 83b8100..6de4d3e 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -572,7 +572,7 @@
     private final class HwuiContext {
         private final RenderNode mRenderNode;
         private long mHwuiRenderer;
-        private HardwareCanvas mCanvas;
+        private DisplayListCanvas mCanvas;
 
         HwuiContext() {
             mRenderNode = RenderNode.create("HwuiCanvas", null);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 51fefe9..031be07 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -276,7 +276,7 @@
         updateViewTreeDisplayList(view);
 
         if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
-            HardwareCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+            DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
             try {
                 final int saveCount = canvas.save();
                 canvas.translate(mInsetLeft, mInsetTop);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d345bed..f5de8e3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14216,7 +14216,7 @@
             int height = mBottom - mTop;
             int layerType = getLayerType();
 
-            final HardwareCanvas canvas = renderNode.start(width, height);
+            final DisplayListCanvas canvas = renderNode.start(width, height);
             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
 
             try {
@@ -15197,7 +15197,7 @@
                 if (layer != null && layer.isValid()) {
                     int restoreAlpha = mLayerPaint.getAlpha();
                     mLayerPaint.setAlpha((int) (alpha * 255));
-                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
+                    ((DisplayListCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
                     mLayerPaint.setAlpha(restoreAlpha);
                     layerRendered = true;
                 } else {
@@ -15220,7 +15220,7 @@
                     }
                 } else {
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-                    ((HardwareCanvas) canvas).drawRenderNode(renderNode, flags);
+                    ((DisplayListCanvas) canvas).drawRenderNode(renderNode, flags);
                 }
             }
         } else if (cache != null) {
@@ -15494,7 +15494,7 @@
             final RenderNode renderNode = mBackgroundRenderNode;
             if (renderNode != null && renderNode.isValid()) {
                 setBackgroundRenderNodeProperties(renderNode);
-                ((HardwareCanvas) canvas).drawRenderNode(renderNode);
+                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
                 return;
             }
         }
@@ -15531,7 +15531,7 @@
         final Rect bounds = drawable.getBounds();
         final int width = bounds.width();
         final int height = bounds.height();
-        final HardwareCanvas canvas = renderNode.start(width, height);
+        final DisplayListCanvas canvas = renderNode.start(width, height);
 
         // Reverse left/top translation done by drawable canvas, which will
         // instead be applied by rendernode's LTRB bounds below. This way, the
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1473806..e790d4c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2309,12 +2309,12 @@
     final Paint mResizePaint = new Paint();
 
     @Override
-    public void onHardwarePreDraw(HardwareCanvas canvas) {
+    public void onHardwarePreDraw(DisplayListCanvas canvas) {
         canvas.translate(-mHardwareXOffset, -mHardwareYOffset);
     }
 
     @Override
-    public void onHardwarePostDraw(HardwareCanvas canvas) {
+    public void onHardwarePostDraw(DisplayListCanvas canvas) {
         if (mResizeBuffer != null) {
             mResizePaint.setAlpha(mResizeAlpha);
             canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 1cebe3f..57558ff 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -249,12 +249,12 @@
         final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
         if (parentWindow != null) {
             parentWindow.adjustLayoutParamsForSubWindow(wparams);
-        } else if (ActivityManager.isHighEndGfx()) {
-            // If there's no parent and we're running on L or above (or in the
-            // system context), assume we want hardware acceleration.
+        } else {
+            // If there's no parent, then hardware acceleration for this view is
+            // set from the application's hardware acceleration setting.
             final Context context = view.getContext();
-            if (context != null && context.getApplicationInfo().targetSdkVersion
-                    >= Build.VERSION_CODES.LOLLIPOP) {
+            if (context != null
+                    && context.getApplicationInfo().hardwareAccelerated) {
                 wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
         }
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index ac360fa..23af384 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -25,7 +25,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.util.SparseArray;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.View;
 import android.view.ViewRootImpl;
 
@@ -101,12 +101,12 @@
      * @throws IllegalArgumentException if the canvas is not hardware accelerated
      */
     public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
-        if (!(canvas instanceof HardwareCanvas)) {
+        if (!(canvas instanceof DisplayListCanvas)) {
             // Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas.
             throw new IllegalArgumentException(canvas.getClass().getName()
-                    + " is not hardware accelerated");
+                    + " is not a DisplayList canvas");
         }
-        ((HardwareCanvas) canvas).callDrawGLFunction2(nativeDrawGLFunctor);
+        ((DisplayListCanvas) canvas).callDrawGLFunction2(nativeDrawGLFunctor);
     }
 
     /**
@@ -153,7 +153,7 @@
     }
 
     /**
-     * Adds the WebView asset path to {@link AssetManager}.
+     * Adds the WebView asset path to {@link android.content.res.AssetManager}.
      */
     public void addWebViewAssetPath(Context context) {
         context.getAssets().addAssetPath(
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 13d7f13..7d3c9c9 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -77,14 +77,14 @@
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
-import android.view.RenderNode;
+import android.view.DisplayListCanvas;
 import android.view.DragEvent;
 import android.view.Gravity;
-import android.view.HardwareCanvas;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.RenderNode;
 import android.view.View;
 import android.view.View.DragShadowBuilder;
 import android.view.View.OnClickListener;
@@ -236,12 +236,17 @@
     }
 
     ParcelableParcel saveInstanceState() {
-        // For now there is only undo state.
-        return (ParcelableParcel) mUndoManager.saveInstanceState();
+        ParcelableParcel state = new ParcelableParcel(getClass().getClassLoader());
+        Parcel parcel = state.getParcel();
+        mUndoManager.saveInstanceState(parcel);
+        mUndoInputFilter.saveInstanceState(parcel);
+        return state;
     }
 
     void restoreInstanceState(ParcelableParcel state) {
-        mUndoManager.restoreInstanceState(state);
+        Parcel parcel = state.getParcel();
+        mUndoManager.restoreInstanceState(parcel, state.getClassLoader());
+        mUndoInputFilter.restoreInstanceState(parcel);
         // Re-associate this object as the owner of undo state.
         mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
     }
@@ -1509,18 +1514,18 @@
 
                     // Rebuild display list if it is invalid
                     if (blockDisplayListIsInvalid) {
-                        final HardwareCanvas hardwareCanvas = blockDisplayList.start(
+                        final DisplayListCanvas displayListCanvas = blockDisplayList.start(
                                 right - left, bottom - top);
                         try {
                             // drawText is always relative to TextView's origin, this translation
                             // brings this range of text back to the top left corner of the viewport
-                            hardwareCanvas.translate(-left, -top);
-                            layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
+                            displayListCanvas.translate(-left, -top);
+                            layout.drawText(displayListCanvas, blockBeginLine, blockEndLine);
                             mTextDisplayLists[blockIndex].isDirty = false;
                             // No need to untranslate, previous context is popped after
                             // drawDisplayList
                         } finally {
-                            blockDisplayList.end(hardwareCanvas);
+                            blockDisplayList.end(displayListCanvas);
                             // Same as drawDisplayList below, handled by our TextView's parent
                             blockDisplayList.setClipToBounds(false);
                         }
@@ -1531,7 +1536,7 @@
                     blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
                 }
 
-                ((HardwareCanvas) canvas).drawRenderNode(blockDisplayList,
+                ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList,
                         0 /* no child clipping, our TextView parent enforces it */);
 
                 endOfPreviousBlock = blockEndLine;
@@ -4581,20 +4586,30 @@
         // Whether the current filter pass is directly caused by an end-user text edit.
         private boolean mIsUserEdit;
 
-        // Whether this is the first pass through the filter for a given end-user text edit.
-        private boolean mFirstFilterPass;
+        // Whether the text field is handling an IME composition. Must be parceled in case the user
+        // rotates the screen during composition.
+        private boolean mHasComposition;
 
         public UndoInputFilter(Editor editor) {
             mEditor = editor;
         }
 
+        public void saveInstanceState(Parcel parcel) {
+            parcel.writeInt(mIsUserEdit ? 1 : 0);
+            parcel.writeInt(mHasComposition ? 1 : 0);
+        }
+
+        public void restoreInstanceState(Parcel parcel) {
+            mIsUserEdit = parcel.readInt() != 0;
+            mHasComposition = parcel.readInt() != 0;
+        }
+
         /**
          * Signals that a user-triggered edit is starting.
          */
         public void beginBatchEdit() {
             if (DEBUG_UNDO) Log.d(TAG, "beginBatchEdit");
             mIsUserEdit = true;
-            mFirstFilterPass = true;
         }
 
         public void endBatchEdit() {
@@ -4615,17 +4630,63 @@
                 return null;
             }
 
+            // Check for and handle IME composition edits.
+            if (handleCompositionEdit(source, start, end, dstart)) {
+                return null;
+            }
+
+            // Handle keyboard edits.
+            handleKeyboardEdit(source, start, end, dest, dstart, dend);
+            return null;
+        }
+
+        /**
+         * Returns true iff the edit was handled, either because it should be ignored or because
+         * this function created an undo operation for it.
+         */
+        private boolean handleCompositionEdit(CharSequence source, int start, int end, int dstart) {
+            // Ignore edits while the user is composing.
+            if (isComposition(source)) {
+                mHasComposition = true;
+                return true;
+            }
+            final boolean hadComposition = mHasComposition;
+            mHasComposition = false;
+
+            // Check for the transition out of the composing state.
+            if (hadComposition) {
+                // If there was no text the user canceled composition. Ignore the edit.
+                if (start == end) {
+                    return true;
+                }
+
+                // Otherwise the user inserted the composition.
+                String newText = TextUtils.substring(source, start, end);
+                EditOperation edit = new EditOperation(mEditor, false, "", dstart, newText);
+                recordEdit(edit);
+                return true;
+            }
+
+            // This was neither a composition event nor a transition out of composing.
+            return false;
+        }
+
+        private void handleKeyboardEdit(CharSequence source, int start, int end,
+                Spanned dest, int dstart, int dend) {
             // An application may install a TextWatcher to provide additional modifications after
             // the initial input filters run (e.g. a credit card formatter that adds spaces to a
             // string). This results in multiple filter() calls for what the user considers to be
             // a single operation. Always undo the whole set of changes in one step.
-            final boolean forceMerge = !mFirstFilterPass;
-            mFirstFilterPass = false;
+            final boolean forceMerge = isInTextWatcher();
 
             // Build a new operation with all the information from this edit.
-            EditOperation edit = new EditOperation(mEditor, forceMerge,
-                    source, start, end, dest, dstart, dend);
+            String newText = TextUtils.substring(source, start, end);
+            String oldText = TextUtils.substring(dest, dstart, dend);
+            EditOperation edit = new EditOperation(mEditor, forceMerge, oldText, dstart, newText);
+            recordEdit(edit);
+        }
 
+        private void recordEdit(EditOperation edit) {
             // Fetch the last edit operation and attempt to merge in the new edit.
             final UndoManager um = mEditor.mUndoManager;
             um.beginUpdate("Edit text");
@@ -4651,7 +4712,6 @@
                 um.addOperation(edit, UndoManager.MERGE_MODE_NONE);
             }
             um.endUpdate();
-            return null;  // Text not changed.
         }
 
         private boolean canUndoEdit(CharSequence source, int start, int end,
@@ -4683,6 +4743,23 @@
 
             return true;
         }
+
+        private boolean isComposition(CharSequence source) {
+            if (!(source instanceof Spannable)) {
+                return false;
+            }
+            // This is a composition edit if the source has a non-zero-length composing span.
+            Spannable text = (Spannable) source;
+            int composeBegin = EditableInputConnection.getComposingSpanStart(text);
+            int composeEnd = EditableInputConnection.getComposingSpanEnd(text);
+            return composeBegin < composeEnd;
+        }
+
+        private boolean isInTextWatcher() {
+            CharSequence text = mEditor.mTextView.getText();
+            return (text instanceof SpannableStringBuilder)
+                    && ((SpannableStringBuilder) text).getTextWatcherDepth() > 0;
+        }
     }
 
     /**
@@ -4704,17 +4781,16 @@
         private int mNewCursorPos;
 
         /**
-         * Constructs an edit operation from a text input operation that replaces the range
-         * (dstart, dend) of dest with (start, end) of source. See {@link InputFilter#filter}.
-         * If forceMerge is true then always forcibly merge this operation with any previous one.
+         * Constructs an edit operation from a text input operation on editor that replaces the
+         * oldText starting at dstart with newText. If forceMerge is true then always forcibly
+         * merge this operation with any previous one.
          */
-        public EditOperation(Editor editor, boolean forceMerge,
-                CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
+        public EditOperation(Editor editor, boolean forceMerge, String oldText, int dstart,
+                String newText) {
             super(editor.mUndoOwner);
             mForceMerge = forceMerge;
-
-            mOldText = dest.subSequence(dstart, dend).toString();
-            mNewText = source.subSequence(start, end).toString();
+            mOldText = oldText;
+            mNewText = newText;
 
             // Determine the type of the edit and store where it occurred. Avoid storing
             // irrevelant data (e.g. mNewTextStart for a delete) because that makes the
@@ -4733,7 +4809,7 @@
 
             // Store cursor data.
             mOldCursorPos = editor.mTextView.getSelectionStart();
-            mNewCursorPos = dstart + (end - start);
+            mNewCursorPos = dstart + mNewText.length();
         }
 
         public EditOperation(Parcel src, ClassLoader loader) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2bfee1c..718ef93 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -111,8 +111,6 @@
 import android.view.HapticFeedbackConstants;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewAssistStructure;
@@ -8957,9 +8955,10 @@
      *
      * A custom implementation can add new entries in the default menu in its
      * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
-     * default actions can also be removed from the menu using {@link Menu#removeItem(int)} and
-     * passing {@link android.R.id#selectAll}, {@link android.R.id#cut}, {@link android.R.id#copy}
-     * or {@link android.R.id#paste} ids as parameters.
+     * default actions can also be removed from the menu using
+     * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
+     * {@link android.R.id#cut}, {@link android.R.id#copy} or {@link android.R.id#paste} ids as
+     * parameters.
      *
      * Returning false from
      * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
@@ -9534,7 +9533,6 @@
         // TODO: Add an option to configure this
         private static final float MARQUEE_DELTA_MAX = 0.07f;
         private static final int MARQUEE_DELAY = 1200;
-        private static final int MARQUEE_RESTART_DELAY = 1200;
         private static final int MARQUEE_DP_PER_SECOND = 30;
 
         private static final byte MARQUEE_STOPPED = 0x0;
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index a43ba3c..06577720 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -28,21 +28,21 @@
 
 
 
-sdk.linux_download=android-sdk_r24.0.2-linux.tgz
-sdk.linux_bytes=140097024
-sdk.linux_checksum=b6fd75e8b06b0028c2427e6da7d8a09d8f956a86
+sdk.linux_download=android-sdk_r24.1.2-linux.tgz
+sdk.linux_bytes=168121693
+sdk.linux_checksum=68980e4a26cca0182abb1032abffbb72a1240c51
 
-sdk.mac_download=android-sdk_r24.0.2-macosx.zip
-sdk.mac_bytes=87262823
-sdk.mac_checksum=3ab5e0ab0db5e7c45de9da7ff525dee6cfa97455
+sdk.mac_download=android-sdk_r24.1.2-macosx.zip
+sdk.mac_bytes=89151287
+sdk.mac_checksum=00e43ff1557e8cba7da53e4f64f3a34498048256
 
-sdk.win_download=android-sdk_r24.0.2-windows.zip
-sdk.win_bytes=139473113
-sdk.win_checksum=51269c8336f936fc9b9538f9b9ca236b78fb4e4b
+sdk.win_download=android-sdk_r24.1.2-windows.zip
+sdk.win_bytes=159778618
+sdk.win_checksum=704f6c874373b98e061fe2e7eb34f9fcb907a341
 
-sdk.win_installer=installer_r24.0.2-windows.exe
-sdk.win_installer_bytes=91428280
-sdk.win_installer_checksum=edac14e1541e97d68821fa3a709b4ea8c659e676
+sdk.win_installer=installer_r24.1.2-windows.exe
+sdk.win_installer_bytes=111364285
+sdk.win_installer_checksum=e0ec864efa0e7449db2d7ed069c03b1f4d36f0cd
 
 
 
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 6d1b1fe..1c14e2f 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -25,7 +25,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.util.FloatProperty;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.animation.LinearInterpolator;
 
@@ -73,7 +73,7 @@
     }
 
     @Override
-    protected boolean drawHardware(HardwareCanvas c) {
+    protected boolean drawHardware(DisplayListCanvas c) {
         c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
         return true;
     }
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index 79407f7..7976e82 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -20,7 +20,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 
 import java.util.ArrayList;
@@ -36,7 +36,7 @@
     protected final Rect mBounds;
 
     /** Whether we can use hardware acceleration for the exit animation. */
-    private boolean mHasHardwareCanvas;
+    private boolean mHasDisplayListCanvas;
 
     private boolean mHasPendingHardwareAnimator;
     private RenderNodeAnimatorSet mHardwareAnimator;
@@ -93,7 +93,7 @@
     public final void exit() {
         cancel();
 
-        if (mHasHardwareCanvas) {
+        if (mHasDisplayListCanvas) {
             // We don't have access to a canvas here, but we expect one on the
             // next frame. We'll start the render thread animation then.
             mHasPendingHardwareAnimator = true;
@@ -132,19 +132,19 @@
      * @return {@code true} if something was drawn, {@code false} otherwise
      */
     public boolean draw(Canvas c, Paint p) {
-        final boolean hasHardwareCanvas = c.isHardwareAccelerated()
-                && c instanceof HardwareCanvas;
-        if (mHasHardwareCanvas != hasHardwareCanvas) {
-            mHasHardwareCanvas = hasHardwareCanvas;
+        final boolean hasDisplayListCanvas = c.isHardwareAccelerated()
+                && c instanceof DisplayListCanvas;
+        if (mHasDisplayListCanvas != hasDisplayListCanvas) {
+            mHasDisplayListCanvas = hasDisplayListCanvas;
 
-            if (!hasHardwareCanvas) {
+            if (!hasDisplayListCanvas) {
                 // We've switched from hardware to non-hardware mode. Panic.
                 endHardwareAnimations();
             }
         }
 
-        if (hasHardwareCanvas) {
-            final HardwareCanvas hw = (HardwareCanvas) c;
+        if (hasDisplayListCanvas) {
+            final DisplayListCanvas hw = (DisplayListCanvas) c;
             startPendingAnimation(hw, p);
 
             if (mHardwareAnimator != null) {
@@ -173,7 +173,7 @@
      * @param hw hardware canvas on which the animation should draw
      * @param p paint whose properties the hardware canvas should use
      */
-    private void startPendingAnimation(HardwareCanvas hw, Paint p) {
+    private void startPendingAnimation(DisplayListCanvas hw, Paint p) {
         if (mHasPendingHardwareAnimator) {
             mHasPendingHardwareAnimator = false;
 
@@ -258,7 +258,7 @@
 
     protected abstract RenderNodeAnimatorSet createHardwareExit(Paint p);
 
-    protected abstract boolean drawHardware(HardwareCanvas c);
+    protected abstract boolean drawHardware(DisplayListCanvas c);
 
     protected abstract boolean drawSoftware(Canvas c, Paint p);
 
@@ -279,7 +279,7 @@
             mAnimators.clear();
         }
 
-        public void start(HardwareCanvas target) {
+        public void start(DisplayListCanvas target) {
             if (target == null) {
                 throw new IllegalArgumentException("Hardware canvas must be non-null");
             }
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index 334122d..4853b04 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -27,7 +27,7 @@
 import android.graphics.Rect;
 import android.util.FloatProperty;
 import android.util.MathUtils;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.animation.LinearInterpolator;
 
@@ -127,7 +127,7 @@
     }
 
     @Override
-    protected boolean drawHardware(HardwareCanvas c) {
+    protected boolean drawHardware(DisplayListCanvas c) {
         c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
         return true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index a3ebb09..3f63b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -26,7 +26,7 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -106,7 +106,7 @@
     public void draw(Canvas canvas) {
         mSupportHardware = canvas.isHardwareAccelerated();
         if (mSupportHardware) {
-            drawHardware((HardwareCanvas) canvas);
+            drawHardware((DisplayListCanvas) canvas);
         } else {
             drawSoftware(canvas);
         }
@@ -131,7 +131,7 @@
         return getBounds().width() > getBounds().height();
     }
 
-    private void drawHardware(HardwareCanvas c) {
+    private void drawHardware(DisplayListCanvas c) {
         if (mDrawingHardwareGlow) {
             c.drawRoundRect(mLeftProp, mTopProp, mRightProp, mBottomProp, mRxProp, mRyProp,
                     mPaintProp);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index ab586515..22b7bb1 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -208,16 +208,22 @@
          */
         public static final int CAPABILITY_WIFI = 0x00010000;
 
-        //******************************************************************************************
-        // Next CAPABILITY value: 0x00020000
-        //******************************************************************************************
-
         /**
          * Indicates that the current device callback number should be shown.
          *
          * @hide
          */
-        public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00008000;
+        public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
+
+        /**
+         * Speed up audio setup for MT call.
+         * @hide
+         */
+        public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
+
+        //**********************************************************************************************
+        // Next CAPABILITY value: 0x00080000
+        //**********************************************************************************************
 
         private final Uri mHandle;
         private final int mHandlePresentation;
@@ -316,6 +322,9 @@
             if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
                 builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
             }
+            if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
+                builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+            }
             builder.append("]");
             return builder.toString();
         }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index f7a19f8..a335e47 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -173,18 +173,22 @@
      */
     public static final int CAPABILITY_WIFI = 0x000010000;
 
-    //**********************************************************************************************
-    // Next CAPABILITY value: 0x00020000
-    //**********************************************************************************************
-
     /**
      * Indicates that the current device callback number should be shown.
      *
      * @hide
      */
-    public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00008000;
+    public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
 
+    /**
+     * Speed up audio setup for MT call.
+     * @hide
+     */
+    public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
 
+    //**********************************************************************************************
+    // Next CAPABILITY value: 0x00080000
+    //**********************************************************************************************
 
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -287,6 +291,9 @@
         if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
             builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
         }
+        if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
+            builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+        }
         builder.append("]");
         return builder.toString();
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index afd6a8d..5bc8934 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -24,7 +24,7 @@
 import android.graphics.Paint.Style;
 import android.os.Bundle;
 import android.os.Trace;
-import android.view.HardwareCanvas;
+import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -88,8 +88,8 @@
             super.onDraw(canvas);
 
             if (canvas.isHardwareAccelerated()) {
-                HardwareCanvas hwcanvas = (HardwareCanvas) canvas;
-                hwcanvas.drawCircle(mX, mY, mRadius, mPaint);
+                DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+                displayListCanvas.drawCircle(mX, mY, mRadius, mPaint);
             }
         }