Merge "Workaround for apps loading foreign native libs"
diff --git a/api/current.txt b/api/current.txt
index e044da9..5361d0a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -50208,13 +50208,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -50745,7 +50748,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -51439,7 +51445,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -51449,7 +51458,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 359a4f1..a43e3f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -53192,13 +53192,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -53729,7 +53732,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -54423,7 +54429,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -54433,7 +54442,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 8aee25d..278a47d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -50225,13 +50225,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -50762,7 +50765,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -51456,7 +51462,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -51466,7 +51475,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 980329f..1ab55dd 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1030,20 +1030,6 @@
         }
     }
 
-    /**
-     * @hide
-     * TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order
-     * if defined (i.e. sequential or together), then we can use the flag instead of calculate
-     * dynamically.
-     * @return whether all the animators in the set are supposed to play together
-     */
-    public boolean shouldPlayTogether() {
-        updateAnimatorsDuration();
-        createDependencyGraph();
-        // All the child nodes are set out to play right after the delay animation
-        return mRootNode.mChildNodes.size() == mNodes.size() - 1;
-    }
-
     @Override
     public long getTotalDuration() {
         updateAnimatorsDuration();
diff --git a/core/java/android/animation/PathKeyframes.java b/core/java/android/animation/PathKeyframes.java
index 8230ac5..2a47b68 100644
--- a/core/java/android/animation/PathKeyframes.java
+++ b/core/java/android/animation/PathKeyframes.java
@@ -231,7 +231,7 @@
         }
     }
 
-    abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes {
+    private abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes {
         @Override
         public Class getType() {
             return Integer.class;
@@ -243,7 +243,7 @@
         }
     }
 
-    abstract static class FloatKeyframesBase extends SimpleKeyframes
+    private abstract static class FloatKeyframesBase extends SimpleKeyframes
             implements FloatKeyframes {
         @Override
         public Class getType() {
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 6ba5b96..e993cca 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -21,7 +21,6 @@
 import android.util.FloatProperty;
 import android.util.IntProperty;
 import android.util.Log;
-import android.util.PathParser;
 import android.util.Property;
 
 import java.lang.reflect.InvocationTargetException;
@@ -1047,43 +1046,6 @@
         return mAnimatedValue;
     }
 
-    /**
-     * PropertyValuesHolder is Animators use to hold internal animation related data.
-     * Therefore, in order to replicate the animation behavior, we need to get data out of
-     * PropertyValuesHolder.
-     * @hide
-     */
-    public void getPropertyValues(PropertyValues values) {
-        init();
-        values.propertyName = mPropertyName;
-        values.type = mValueType;
-        values.startValue = mKeyframes.getValue(0);
-        if (values.startValue instanceof PathParser.PathData) {
-            // PathData evaluator returns the same mutable PathData object when query fraction,
-            // so we have to make a copy here.
-            values.startValue = new PathParser.PathData((PathParser.PathData) values.startValue);
-        }
-        values.endValue = mKeyframes.getValue(1);
-        if (values.endValue instanceof PathParser.PathData) {
-            // PathData evaluator returns the same mutable PathData object when query fraction,
-            // so we have to make a copy here.
-            values.endValue = new PathParser.PathData((PathParser.PathData) values.endValue);
-        }
-        // TODO: We need a better way to get data out of keyframes.
-        if (mKeyframes instanceof PathKeyframes.FloatKeyframesBase
-                || mKeyframes instanceof PathKeyframes.IntKeyframesBase) {
-            // property values will animate based on external data source (e.g. Path)
-            values.dataSource = new PropertyValues.DataSource() {
-                @Override
-                public Object getValueAtFraction(float fraction) {
-                    return mKeyframes.getValue(fraction);
-                }
-            };
-        } else {
-            values.dataSource = null;
-        }
-    }
-
     @Override
     public String toString() {
         return mPropertyName + ": " + mKeyframes.toString();
@@ -1639,24 +1601,6 @@
         }
     };
 
-    /**
-     * @hide
-     */
-    public static class PropertyValues {
-        public String propertyName;
-        public Class type;
-        public Object startValue;
-        public Object endValue;
-        public DataSource dataSource = null;
-        public interface DataSource {
-            Object getValueAtFraction(float fraction);
-        }
-        public String toString() {
-            return ("property name: " + propertyName + ", type: " + type + ", startValue: "
-                    + startValue.toString() + ", endValue: " + endValue.toString());
-        }
-    }
-
     native static private long nGetIntMethod(Class targetClass, String methodName);
     native static private long nGetFloatMethod(Class targetClass, String methodName);
     native static private long nGetMultipleIntMethod(Class targetClass, String methodName,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1247afe..02eb115 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4109,6 +4109,29 @@
     }
 
     /**
+     * Called by the system to check if a specific accessibility service is disabled by admin.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName Accessibility service package name that needs to be checked.
+     * @param userHandle user id the admin is running as.
+     * @return true if the accessibility service is permitted, otherwise false.
+     *
+     * @hide
+     */
+    public boolean isAccessibilityServicePermittedByAdmin(@NonNull ComponentName admin,
+            @NonNull String packageName, int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.isAccessibilityServicePermittedByAdmin(admin, packageName,
+                        userHandle);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the list of accessibility services permitted by the device or profiles
      * owners of this user.
      *
@@ -4188,6 +4211,28 @@
     }
 
     /**
+     * Called by the system to check if a specific input method is disabled by admin.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName Input method package name that needs to be checked.
+     * @param userHandle user id the admin is running as.
+     * @return true if the input method is permitted, otherwise false.
+     *
+     * @hide
+     */
+    public boolean isInputMethodPermittedByAdmin(@NonNull ComponentName admin,
+            @NonNull String packageName, int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the list of input methods permitted by the device or profiles
      * owners of the current user.  (*Not* calling user, due to a limitation in InputMethodManager.)
      *
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b57e1b7..c6a5344 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -174,10 +174,12 @@
     boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList);
     List getPermittedAccessibilityServices(in ComponentName admin);
     List getPermittedAccessibilityServicesForUser(int userId);
+    boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
     boolean setPermittedInputMethods(in ComponentName admin,in List packageList);
     List getPermittedInputMethods(in ComponentName admin);
     List getPermittedInputMethodsForCurrentUser();
+    boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
     boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden);
     boolean isApplicationHidden(in ComponentName admin, in String packageName);
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 29a72fd..78d5bcd 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -104,7 +104,6 @@
             }
             super.finalize();
         }
-
     }
 
     /**
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 2aace0f..3122c0b 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -22,7 +22,6 @@
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
 
 /**
  * <p>A display list records a series of graphics related operations and can replay
@@ -136,6 +135,9 @@
     private RenderNode(String name, View owningView) {
         mNativeRenderNode = nCreate(name);
         mOwningView = owningView;
+        if (mOwningView instanceof SurfaceView) {
+            nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
+        }
     }
 
     /**
@@ -772,14 +774,6 @@
         mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
     }
 
-    public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) {
-        if (mOwningView == null || mOwningView.mAttachInfo == null) {
-            throw new IllegalStateException("Cannot start this animator on a detached view!");
-        }
-        nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr());
-        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
-    }
-
     public void endAllAnimators() {
         nEndAllAnimators(mNativeRenderNode);
     }
@@ -863,6 +857,8 @@
     private static native void nOutput(long renderNode);
     private static native int nGetDebugSize(long renderNode);
 
+    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
+
     ///////////////////////////////////////////////////////////////////////////
     // Animations
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java
deleted file mode 100644
index ba592d29..0000000
--- a/core/java/android/view/RenderNodeAnimatorSetHelper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.view;
-
-import android.animation.TimeInterpolator;
-import com.android.internal.view.animation.FallbackLUTInterpolator;
-import com.android.internal.view.animation.NativeInterpolatorFactory;
-import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
-
-/**
- * This is a helper class to get access to methods and fields needed for RenderNodeAnimatorSet
- * that are internal or package private to android.view package.
- *
- * @hide
- */
-public class RenderNodeAnimatorSetHelper {
-
-    public static RenderNode getTarget(DisplayListCanvas recordingCanvas) {
-        return recordingCanvas.mNode;
-    }
-
-    public static long createNativeInterpolator(TimeInterpolator interpolator, long
-            duration) {
-        if (interpolator == null) {
-            // create LinearInterpolator
-            return NativeInterpolatorFactoryHelper.createLinearInterpolator();
-        } else if (RenderNodeAnimator.isNativeInterpolator(interpolator)) {
-            return ((NativeInterpolatorFactory)interpolator).createNativeInterpolator();
-        } else {
-            return FallbackLUTInterpolator.createNativeInterpolator(interpolator, duration);
-        }
-    }
-
-}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5b48e28..a296051 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -135,7 +135,7 @@
         }
     };
 
-    final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
+    private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
             = new ViewTreeObserver.OnScrollChangedListener() {
                     @Override
                     public void onScrollChanged() {
@@ -143,6 +143,17 @@
                     }
             };
 
+    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
+            new ViewTreeObserver.OnPreDrawListener() {
+                @Override
+                public boolean onPreDraw() {
+                    // reposition ourselves where the surface is
+                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
+                    updateWindow(false, false);
+                    return true;
+                }
+            };
+
     boolean mRequestedVisible = false;
     boolean mWindowVisibility = false;
     boolean mViewVisibility = false;
@@ -168,17 +179,9 @@
     boolean mUpdateWindowNeeded;
     boolean mReportDrawNeeded;
     private Translator mTranslator;
+    private int mWindowInsetLeft;
+    private int mWindowInsetTop;
 
-    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
-            new ViewTreeObserver.OnPreDrawListener() {
-                @Override
-                public boolean onPreDraw() {
-                    // reposition ourselves where the surface is
-                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
-                    updateWindow(false, false);
-                    return true;
-                }
-            };
     private boolean mGlobalListenersAdded;
 
     public SurfaceView(Context context) {
@@ -443,17 +446,17 @@
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        getLocationInWindow(mLocation);
         final boolean creating = mWindow == null;
         final boolean formatChanged = mFormat != mRequestedFormat;
         final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
         final boolean visibleChanged = mVisible != mRequestedVisible;
         final boolean layoutSizeChanged = getWidth() != mLayout.width
                 || getHeight() != mLayout.height;
-        final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1];
 
         if (force || creating || formatChanged || sizeChanged || visibleChanged
             || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
+            getLocationInWindow(mLocation);
+
             if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                     + " format=" + formatChanged + " size=" + sizeChanged
                     + " visible=" + visibleChanged
@@ -643,27 +646,69 @@
                 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                 " w=" + mLayout.width + " h=" + mLayout.height +
                 ", frame=" + mSurfaceFrame);
-        } else if (positionChanged || layoutSizeChanged) { // Only the position has changed
-            mWindowSpaceLeft = mLocation[0];
-            mWindowSpaceTop = mLocation[1];
-            // For our size changed check, we keep mLayout.width and mLayout.height
-            // in view local space.
-            mLocation[0] = mLayout.width = getWidth();
-            mLocation[1] = mLayout.height = getHeight();
+        } else if (!isHardwareAccelerated()) {
+            getLocationInWindow(mLocation);
+            final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
+                    || mWindowSpaceTop != mLocation[1];
+            if (positionChanged || layoutSizeChanged) { // Only the position has changed
+                mWindowSpaceLeft = mLocation[0];
+                mWindowSpaceTop = mLocation[1];
+                // For our size changed check, we keep mLayout.width and mLayout.height
+                // in view local space.
+                mLocation[0] = mLayout.width = getWidth();
+                mLocation[1] = mLayout.height = getHeight();
 
-            transformFromViewToWindowSpace(mLocation);
+                transformFromViewToWindowSpace(mLocation);
 
-            try {
-                mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
-                        mLocation[0], mLocation[1],
-                        viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
-                        mWinFrame);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "Exception from relayout", ex);
+                try {
+                    Log.d(TAG, String.format("updateWindowPosition UI, " +
+                            "postion = [%d, %d, %d, %d]", mWindowSpaceLeft, mWindowSpaceTop,
+                            mLocation[0], mLocation[1]));
+                    mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
+                            mLocation[0], mLocation[1], -1, mWinFrame);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Exception from relayout", ex);
+                }
             }
         }
     }
 
+    private Rect mRTLastReportedPosition = new Rect();
+
+    /**
+     * Called by native on RenderThread to update the window position
+     * @hide
+     */
+    public final void updateWindowPositionRT(long frameNumber,
+            int left, int top, int right, int bottom) {
+        IWindowSession session = mSession;
+        MyWindow window = mWindow;
+        if (session == null || window == null) {
+            // Guess we got detached, that sucks
+            return;
+        }
+        if (mRTLastReportedPosition.left == left
+                && mRTLastReportedPosition.top == top
+                && mRTLastReportedPosition.right == right
+                && mRTLastReportedPosition.bottom == bottom) {
+            return;
+        }
+        try {
+            if (DEBUG) {
+                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
+                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
+                        right, bottom));
+            }
+            // Just using mRTLastReportedPosition as a dummy rect here
+            session.repositionChild(window, left, top, right, bottom, frameNumber,
+                    mRTLastReportedPosition);
+            // Now overwrite mRTLastReportedPosition with our values
+            mRTLastReportedPosition.set(left, top, right, bottom);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Exception from repositionChild", ex);
+        }
+    }
+
     private SurfaceHolder.Callback[] getSurfaceCallbacks() {
         SurfaceHolder.Callback callbacks[];
         synchronized (mCallbacks) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4a0a0b0..127157b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4506,9 +4506,15 @@
                     }
                     break;
                 case R.styleable.View_pointerShape:
-                    final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
-                    if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
-                        setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
+                    final int resourceId = a.getResourceId(attr, 0);
+                    if (resourceId != 0) {
+                        setPointerIcon(PointerIcon.loadCustomIcon(
+                                context.getResources(), resourceId));
+                    } else {
+                        final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
+                        if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
+                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
+                        }
                     }
                     break;
             }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 98e3289..97e0143 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6815,20 +6815,6 @@
         }
     }
 
-    long getNextFrameNumber() {
-        long frameNumber = -1;
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.mSurfaceLock.lock();
-        }
-        if (mSurface.isValid()) {
-            frameNumber =  mSurface.getNextFrameNumber();
-        }
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.mSurfaceLock.unlock();
-        }
-        return frameNumber;
-    }
-
     class TakenSurfaceHolder extends BaseSurfaceHolder {
         @Override
         public boolean onAllowLockCanvas() {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1b6b53a..ffa3fa6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -51,7 +51,6 @@
     android_database_SQLiteConnection.cpp \
     android_database_SQLiteGlobal.cpp \
     android_database_SQLiteDebug.cpp \
-    android_graphics_drawable_AnimatedVectorDrawable.cpp \
     android_graphics_drawable_VectorDrawable.cpp \
     android_view_DisplayEventReceiver.cpp \
     android_view_DisplayListCanvas.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 223fc1a..2e45f8c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
 extern int register_android_graphics_Region(JNIEnv* env);
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
-extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env);
 extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
@@ -1322,7 +1321,6 @@
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
-    REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable),
     REG_JNI(register_android_graphics_drawable_VectorDrawable),
     REG_JNI(register_android_graphics_pdf_PdfDocument),
     REG_JNI(register_android_graphics_pdf_PdfEditor),
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
deleted file mode 100644
index 7a3c598..0000000
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "OpenGLRenderer"
-
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include "core_jni_helpers.h"
-#include "log/log.h"
-
-#include "Animator.h"
-#include "Interpolator.h"
-#include "PropertyValuesAnimatorSet.h"
-#include "PropertyValuesHolder.h"
-#include "VectorDrawable.h"
-
-namespace android {
-using namespace uirenderer;
-using namespace VectorDrawable;
-
-static struct {
-    jclass clazz;
-    jmethodID callOnFinished;
-} gVectorDrawableAnimatorClassInfo;
-
-static JNIEnv* getEnv(JavaVM* vm) {
-    JNIEnv* env;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        return 0;
-    }
-    return env;
-}
-
-static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) {
-    class AnimationListenerBridge : public AnimationListener {
-    public:
-        AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
-            mFinishListener = env->NewGlobalRef(finishListener);
-            env->GetJavaVM(&mJvm);
-        }
-
-        virtual ~AnimationListenerBridge() {
-            if (mFinishListener) {
-                onAnimationFinished(NULL);
-            }
-        }
-
-        virtual void onAnimationFinished(BaseRenderNodeAnimator*) {
-            LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?");
-            JNIEnv* env = getEnv(mJvm);
-            env->CallStaticVoidMethod(
-                    gVectorDrawableAnimatorClassInfo.clazz,
-                    gVectorDrawableAnimatorClassInfo.callOnFinished,
-                    mFinishListener);
-            releaseJavaObject();
-        }
-
-    private:
-        void releaseJavaObject() {
-            JNIEnv* env = getEnv(mJvm);
-            env->DeleteGlobalRef(mFinishListener);
-            mFinishListener = NULL;
-        }
-
-        JavaVM* mJvm;
-        jobject mFinishListener;
-    };
-    return new AnimationListenerBridge(env, finishListener);
-}
-
-static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
-        jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) {
-    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
-    Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
-    set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount);
-}
-
-static jlong createAnimatorSet(JNIEnv*, jobject) {
-    PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet();
-    return reinterpret_cast<jlong>(animatorSet);
-}
-
-static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
-        jfloat startValue, jfloat endValue) {
-    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(nativePtr);
-    GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId,
-            startValue, endValue);
-    return reinterpret_cast<jlong>(newHolder);
-}
-
-static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr,
-        jlong endValuePtr) {
-    VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(nativePtr);
-    PathData* startData = reinterpret_cast<PathData*>(startValuePtr);
-    PathData* endData = reinterpret_cast<PathData*>(endValuePtr);
-    PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path,
-            startData, endData);
-    return reinterpret_cast<jlong>(newHolder);
-}
-
-static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
-        int startValue, jint endValue) {
-    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr);
-    FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath,
-            propertyId, startValue, endValue);
-    return reinterpret_cast<jlong>(newHolder);
-}
-
-static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
-        float startValue, jfloat endValue) {
-    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr);
-    FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath,
-            propertyId, startValue, endValue);
-    return reinterpret_cast<jlong>(newHolder);
-}
-
-static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue,
-        float endValue) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(nativePtr);
-    RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree,
-            startValue, endValue);
-    return reinterpret_cast<jlong>(newHolder);
-}
-static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr,
-        jfloatArray srcData, jint length) {
-
-    jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr);
-    PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
-    holder->setPropertyDataSource(propertyData, length);
-    env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
-}
-static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
-    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    // TODO: keep a ref count in finish listener
-    AnimationListener* listener = createAnimationListener(env, finishListener);
-    set->start(listener);
-}
-
-static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
-    // TODO: implement reverse
-}
-
-static void end(JNIEnv*, jobject, jlong animatorSetPtr) {
-    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    set->end();
-}
-
-static void reset(JNIEnv*, jobject, jlong animatorSetPtr) {
-    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    set->reset();
-}
-
-static const JNINativeMethod gMethods[] = {
-    {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet},
-    {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator},
-    {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder},
-    {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder},
-    {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
-    {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
-    {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
-    {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
-    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start},
-    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse},
-    {"nEnd", "!(J)V", (void*)end},
-    {"nReset", "!(J)V", (void*)reset},
-};
-
-const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator";
-int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {
-    gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName);
-    gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env,
-            gVectorDrawableAnimatorClassInfo.clazz);
-
-    gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
-            env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
-            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V");
-    return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
-            gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index e882876..563ec8b 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -32,6 +32,11 @@
     return reinterpret_cast<jlong>(tree);
 }
 
+static void deleteTree(JNIEnv*, jobject, jlong treePtr) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    delete tree;
+}
+
 static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
         jfloat viewportWidth, jfloat viewportHeight) {
     VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
@@ -328,6 +333,7 @@
 
 static const JNINativeMethod gMethods[] = {
         {"nCreateRenderer", "!(J)J", (void*)createTree},
+        {"nDestroyRenderer", "!(J)V", (void*)deleteTree},
         {"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
         {"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
         {"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index b1d4e26..a9003c1 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #include <EGL/egl.h>
 
@@ -24,7 +25,10 @@
 #include <android_runtime/AndroidRuntime.h>
 
 #include <Animator.h>
+#include <DamageAccumulator.h>
+#include <Matrix.h>
 #include <RenderNode.h>
+#include <TreeInfo.h>
 #include <Paint.h>
 
 #include "core_jni_helpers.h"
@@ -462,6 +466,69 @@
 }
 
 // ----------------------------------------------------------------------------
+// SurfaceView position callback
+// ----------------------------------------------------------------------------
+
+jmethodID gSurfaceViewPositionUpdateMethod;
+
+static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
+        jlong renderNodePtr, jobject surfaceview) {
+    class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
+    public:
+        SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
+            env->GetJavaVM(&mVm);
+            mWeakRef = env->NewWeakGlobalRef(surfaceview);
+        }
+
+        virtual ~SurfaceViewPositionUpdater() {
+            jnienv()->DeleteWeakGlobalRef(mWeakRef);
+            mWeakRef = nullptr;
+        }
+
+        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
+            if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
+            ATRACE_NAME("Update SurfaceView position");
+
+            JNIEnv* env = jnienv();
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+            Matrix4 transform;
+            info.damageAccumulator->computeCurrentTransform(&transform);
+            const RenderProperties& props = node.properties();
+            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
+            transform.mapRect(bounds);
+            bounds.left -= info.windowInsetLeft;
+            bounds.right -= info.windowInsetLeft;
+            bounds.top -= info.windowInsetTop;
+            bounds.bottom -= info.windowInsetTop;
+            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+                    (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
+                    (jint) bounds.right, (jint) bounds.bottom);
+            env->DeleteLocalRef(localref);
+        }
+
+    private:
+        JNIEnv* jnienv() {
+            JNIEnv* env;
+            if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+                LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+            }
+            return env;
+        }
+
+        JavaVM* mVm;
+        jobject mWeakRef;
+    };
+
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
+}
+
+// ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
 
@@ -539,9 +606,14 @@
 
     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
+
+    { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
 };
 
 int register_android_view_RenderNode(JNIEnv* env) {
+    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
+    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
+            "updateWindowPositionRT", "(JIIII)V");
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 8c907dd..acd0501 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -134,7 +134,14 @@
 
     virtual void prepareTree(TreeInfo& info) {
         info.errorHandler = this;
+        // TODO: This is hacky
+        info.windowInsetLeft = -stagingProperties().getLeft();
+        info.windowInsetTop = -stagingProperties().getTop();
+        info.updateWindowPositions = true;
         RenderNode::prepareTree(info);
+        info.updateWindowPositions = false;
+        info.windowInsetLeft = 0;
+        info.windowInsetTop = 0;
         info.errorHandler = NULL;
     }
 
@@ -369,28 +376,28 @@
 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
-    proxy->initialize(window);
+    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
+    proxy->initialize(surface);
 }
 
 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window;
+    sp<Surface> surface;
     if (jsurface) {
-        window = android_view_Surface_getNativeWindow(env, jsurface);
+        surface = android_view_Surface_getSurface(env, jsurface);
     }
-    proxy->updateSurface(window);
+    proxy->updateSurface(surface);
 }
 
 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window;
+    sp<Surface> surface;
     if (jsurface) {
-        window = android_view_Surface_getNativeWindow(env, jsurface);
+        surface = android_view_Surface_getSurface(env, jsurface);
     }
-    return proxy->pauseSurface(window);
+    return proxy->pauseSurface(surface);
 }
 
 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index d2bd106..de741b3 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -89,10 +89,7 @@
 endef
 
 font_src_files := \
-    Clockopia.ttf \
-    AndroidClock.ttf \
-    AndroidClock_Highlight.ttf \
-    AndroidClock_Solid.ttf
+    AndroidClock.ttf
 
 $(foreach f, $(font_src_files), $(call build-one-font-module, $(f)))
 
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
deleted file mode 100644
index 923bb30..0000000
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf
deleted file mode 100644
index 923bb30..0000000
--- a/data/fonts/AndroidClock_Solid.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/Clockopia.ttf b/data/fonts/Clockopia.ttf
deleted file mode 100644
index 3f7b6aaa..0000000
--- a/data/fonts/Clockopia.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/MTLc3m.ttf b/data/fonts/MTLc3m.ttf
deleted file mode 100644
index e9018f6..0000000
--- a/data/fonts/MTLc3m.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/MTLmr3m.ttf b/data/fonts/MTLmr3m.ttf
deleted file mode 100644
index 14f27d4..0000000
--- a/data/fonts/MTLmr3m.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 597a122..acd785e 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -20,7 +20,4 @@
 PRODUCT_PACKAGES := \
     DroidSansFallback.ttf \
     DroidSansMono.ttf \
-    Clockopia.ttf \
     AndroidClock.ttf \
-    AndroidClock_Highlight.ttf \
-    AndroidClock_Solid.ttf \
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 21ed7dd..c48c371 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -19,10 +19,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.Animator.AnimatorListener;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.ColorStateList;
@@ -38,23 +34,14 @@
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.LongArray;
-import android.util.PathParser;
-import android.util.TimeUtils;
-import android.view.Choreographer;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-import android.view.RenderNodeAnimatorSetHelper;
 import android.view.View;
 
 import com.android.internal.R;
 
-import com.android.internal.util.VirtualRefBasePtr;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -151,7 +138,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
-    private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator();
+    private final AnimatorSet mAnimatorSet = new AnimatorSet();
 
     /**
      * The resources against which this drawable was created. Used to attempt
@@ -213,9 +200,6 @@
 
     @Override
     public void draw(Canvas canvas) {
-        if (canvas.isHardwareAccelerated()) {
-            mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
-        }
         mAnimatedVectorState.mVectorDrawable.draw(canvas);
         if (isStarted()) {
             invalidateSelf();
@@ -598,8 +582,9 @@
      * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
      */
     public void reset() {
-        mAnimatorSet.reset();
-        invalidateSelf();
+        // TODO: Use reverse or seek to implement reset, when AnimatorSet supports them.
+        start();
+        mAnimatorSet.cancel();
     }
 
     @Override
@@ -618,12 +603,8 @@
     @NonNull
     private void ensureAnimatorSet() {
         if (!mHasAnimatorSet) {
-            // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
-            // with a list of LocalAnimators.
-            AnimatorSet set = new AnimatorSet();
-            mAnimatedVectorState.prepareLocalAnimators(set, mRes);
+            mAnimatedVectorState.prepareLocalAnimators(mAnimatorSet, mRes);
             mHasAnimatorSet = true;
-            mAnimatorSet.initWithAnimatorSet(set);
             mRes = null;
         }
     }
@@ -713,13 +694,13 @@
                 }
             };
         }
-        mAnimatorSet.setListener(mAnimatorListener);
+        mAnimatorSet.addListener(mAnimatorListener);
     }
 
     // A helper function to clean up the animator listener in the mAnimatorSet.
     private void removeAnimatorSetListener() {
         if (mAnimatorListener != null) {
-            mAnimatorSet.removeListener();
+            mAnimatorSet.removeListener(mAnimatorListener);
             mAnimatorListener = null;
         }
     }
@@ -748,407 +729,4 @@
 
         mAnimationCallbacks.clear();
     }
-
-    /**
-     * @hide
-     */
-    public static class VectorDrawableAnimator {
-        private AnimatorListener mListener = null;
-        private final LongArray mStartDelays = new LongArray();
-        private PropertyValuesHolder.PropertyValues mTmpValues =
-                new PropertyValuesHolder.PropertyValues();
-        private long mSetPtr = 0;
-        private boolean mContainsSequentialAnimators = false;
-        private boolean mStarted = false;
-        private boolean mInitialized = false;
-        private boolean mAnimationPending = false;
-        private boolean mIsReversible = false;
-        // TODO: Consider using NativeAllocationRegistery to track native allocation
-        private final VirtualRefBasePtr mSetRefBasePtr;
-        private WeakReference<RenderNode> mTarget = null;
-        private WeakReference<RenderNode> mLastSeenTarget = null;
-
-
-        VectorDrawableAnimator() {
-            mSetPtr = nCreateAnimatorSet();
-            // Increment ref count on native AnimatorSet, so it doesn't get released before Java
-            // side is done using it.
-            mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
-        }
-
-        private void initWithAnimatorSet(AnimatorSet set) {
-            if (mInitialized) {
-                // Already initialized
-                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
-                        "re-initialized");
-            }
-            parseAnimatorSet(set, 0);
-            mInitialized = true;
-
-            // Check reversible.
-            if (mContainsSequentialAnimators) {
-                mIsReversible = false;
-            } else {
-                // Check if there's any start delay set on child
-                for (int i = 0; i < mStartDelays.size(); i++) {
-                    if (mStartDelays.get(i) > 0) {
-                        mIsReversible = false;
-                        return;
-                    }
-                }
-            }
-            mIsReversible = true;
-        }
-
-        private void parseAnimatorSet(AnimatorSet set, long startTime) {
-            ArrayList<Animator> animators = set.getChildAnimations();
-
-            boolean playTogether = set.shouldPlayTogether();
-            // Convert AnimatorSet to VectorDrawableAnimator
-            for (int i = 0; i < animators.size(); i++) {
-                Animator animator = animators.get(i);
-                // Here we only support ObjectAnimator
-                if (animator instanceof AnimatorSet) {
-                    parseAnimatorSet((AnimatorSet) animator, startTime);
-                } else if (animator instanceof ObjectAnimator) {
-                    createRTAnimator((ObjectAnimator) animator, startTime);
-                } // ignore ValueAnimators and others because they don't directly modify VD
-                  // therefore will be useless to AVD.
-
-                if (!playTogether) {
-                    // Assume not play together means play sequentially
-                    startTime += animator.getTotalDuration();
-                    mContainsSequentialAnimators = true;
-                }
-            }
-        }
-
-        // TODO: This method reads animation data from already parsed Animators. We need to move
-        // this step further up the chain in the parser to avoid the detour.
-        private void createRTAnimator(ObjectAnimator animator, long startTime) {
-            PropertyValuesHolder[] values = animator.getValues();
-            Object target = animator.getTarget();
-            if (target instanceof VectorDrawable.VGroup) {
-                createRTAnimatorForGroup(values, animator, (VectorDrawable.VGroup) target,
-                        startTime);
-            } else if (target instanceof VectorDrawable.VPath) {
-                for (int i = 0; i < values.length; i++) {
-                    values[i].getPropertyValues(mTmpValues);
-                    if (mTmpValues.endValue instanceof PathParser.PathData &&
-                            mTmpValues.propertyName.equals("pathData")) {
-                        createRTAnimatorForPath(animator, (VectorDrawable.VPath) target,
-                                startTime);
-                    }  else if (target instanceof VectorDrawable.VFullPath) {
-                        createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target,
-                                startTime);
-                    } else {
-                        throw new IllegalArgumentException("ClipPath only supports PathData " +
-                                "property");
-                    }
-
-                }
-            } else if (target instanceof VectorDrawable.VectorDrawableState) {
-                createRTAnimatorForRootGroup(values, animator,
-                        (VectorDrawable.VectorDrawableState) target, startTime);
-            } else {
-                // Should never get here
-                throw new UnsupportedOperationException("Target should be group, path or vector. " +
-                        target == null ? "Null target" : target.getClass() + " is not supported");
-            }
-        }
-
-        private void createRTAnimatorForGroup(PropertyValuesHolder[] values,
-                ObjectAnimator animator, VectorDrawable.VGroup target,
-                long startTime) {
-
-            long nativePtr = target.getNativePtr();
-            int propertyId;
-            for (int i = 0; i < values.length; i++) {
-                // TODO: We need to support the rare case in AVD where no start value is provided
-                values[i].getPropertyValues(mTmpValues);
-                propertyId = VectorDrawable.VGroup.getPropertyIndex(mTmpValues.propertyName);
-                if (mTmpValues.type != Float.class && mTmpValues.type != float.class) {
-                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                        Log.e(LOGTAG, "Unsupported type: " +
-                                mTmpValues.type + ". Only float value is supported for Groups.");
-                    }
-                    continue;
-                }
-                if (propertyId < 0) {
-                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                        Log.e(LOGTAG, "Unsupported property: " +
-                                mTmpValues.propertyName + " for Vector Drawable Group");
-                    }
-                    continue;
-                }
-                long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId,
-                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
-                if (mTmpValues.dataSource != null) {
-                    float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
-                            .getDuration());
-                    nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
-                }
-                createNativeChildAnimator(propertyPtr, startTime, animator);
-            }
-        }
-        private void createRTAnimatorForPath( ObjectAnimator animator, VectorDrawable.VPath target,
-                long startTime) {
-
-            long nativePtr = target.getNativePtr();
-            long startPathDataPtr = ((PathParser.PathData) mTmpValues.startValue)
-                    .getNativePtr();
-            long endPathDataPtr = ((PathParser.PathData) mTmpValues.endValue)
-                    .getNativePtr();
-            long propertyPtr = nCreatePathDataPropertyHolder(nativePtr, startPathDataPtr,
-                    endPathDataPtr);
-            createNativeChildAnimator(propertyPtr, startTime, animator);
-        }
-
-        private void createRTAnimatorForFullPath(ObjectAnimator animator,
-                VectorDrawable.VFullPath target, long startTime) {
-
-            int propertyId = target.getPropertyIndex(mTmpValues.propertyName);
-            long propertyPtr;
-            long nativePtr = target.getNativePtr();
-            if (mTmpValues.type == Float.class || mTmpValues.type == float.class) {
-                if (propertyId < 0) {
-                    throw new IllegalArgumentException("Property: " + mTmpValues
-                            .propertyName + " is not supported for FullPath");
-                }
-                propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId,
-                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
-
-            } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) {
-                propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId,
-                        (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue);
-            } else {
-                throw new UnsupportedOperationException("Unsupported type: " +
-                        mTmpValues.type + ". Only float, int or PathData value is " +
-                        "supported for Paths.");
-            }
-            if (mTmpValues.dataSource != null) {
-                float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
-                        .getDuration());
-                nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
-            }
-            createNativeChildAnimator(propertyPtr, startTime, animator);
-        }
-
-        private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values,
-                ObjectAnimator animator, VectorDrawable.VectorDrawableState target,
-                long startTime) {
-                long nativePtr = target.getNativeRenderer();
-                if (!animator.getPropertyName().equals("alpha")) {
-                    throw new UnsupportedOperationException("Only alpha is supported for root " +
-                            "group");
-                }
-                Float startValue = null;
-                Float endValue = null;
-                for (int i = 0; i < values.length; i++) {
-                    values[i].getPropertyValues(mTmpValues);
-                    if (mTmpValues.propertyName.equals("alpha")) {
-                        startValue = (Float) mTmpValues.startValue;
-                        endValue = (Float) mTmpValues.endValue;
-                        break;
-                    }
-                }
-                if (startValue == null && endValue == null) {
-                    throw new UnsupportedOperationException("No alpha values are specified");
-                }
-                long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
-                createNativeChildAnimator(propertyPtr, startTime, animator);
-        }
-
-        // These are the data points that define the value of the animating properties.
-        // e.g. translateX and translateY can animate along a Path, at any fraction in [0, 1]
-        // a point on the path corresponds to the values of translateX and translateY.
-        // TODO: (Optimization) We should pass the path down in native and chop it into segments
-        // in native.
-        private static float[] createDataPoints(
-                PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
-            long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
-            int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
-            int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs);
-            float values[] = new float[numAnimFrames];
-            float lastFrame = numAnimFrames - 1;
-            for (int i = 0; i < numAnimFrames; i++) {
-                float fraction = i / lastFrame;
-                values[i] = (Float) dataSource.getValueAtFraction(fraction);
-            }
-            return values;
-        }
-
-        private void createNativeChildAnimator(long propertyPtr, long extraDelay,
-                                               ObjectAnimator animator) {
-            long duration = animator.getDuration();
-            int repeatCount = animator.getRepeatCount();
-            long startDelay = extraDelay + animator.getStartDelay();
-            TimeInterpolator interpolator = animator.getInterpolator();
-            long nativeInterpolator =
-                    RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration);
-
-            startDelay *= ValueAnimator.getDurationScale();
-            duration *= ValueAnimator.getDurationScale();
-
-            mStartDelays.add(startDelay);
-            nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration,
-                    repeatCount);
-        }
-
-        /**
-         * Holds a weak reference to the target that was last seen (through the DisplayListCanvas
-         * in the last draw call), so that when animator set needs to start, we can add the animator
-         * to the last seen RenderNode target and start right away.
-         */
-        protected void recordLastSeenTarget(DisplayListCanvas canvas) {
-            if (mAnimationPending) {
-                mLastSeenTarget = new WeakReference<RenderNode>(
-                        RenderNodeAnimatorSetHelper.getTarget(canvas));
-                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                    Log.d(LOGTAG, "Target is set in the next frame");
-                }
-                mAnimationPending = false;
-                start();
-            } else {
-                mLastSeenTarget = new WeakReference<RenderNode>(
-                        RenderNodeAnimatorSetHelper.getTarget(canvas));
-            }
-
-        }
-
-        private boolean setTarget(RenderNode node) {
-            if (mTarget != null && mTarget.get() != null) {
-                // TODO: Maybe we want to support target change.
-                throw new IllegalStateException("Target already set!");
-            }
-
-            node.addAnimator(this);
-            mTarget = new WeakReference<RenderNode>(node);
-            return true;
-        }
-
-        private boolean useLastSeenTarget() {
-            if (mLastSeenTarget != null && mLastSeenTarget.get() != null) {
-                setTarget(mLastSeenTarget.get());
-                return true;
-            }
-            return false;
-        }
-
-        public void start() {
-            if (!mInitialized) {
-                return;
-            }
-
-            if (mStarted) {
-                return;
-            }
-
-            if (!useLastSeenTarget()) {
-                mAnimationPending = true;
-                return;
-            }
-
-            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
-            }
-
-           nStart(mSetPtr, this);
-            if (mListener != null) {
-                mListener.onAnimationStart(null);
-            }
-            mStarted = true;
-        }
-
-        public void end() {
-            if (mInitialized && mStarted) {
-                nEnd(mSetPtr);
-                onAnimationEnd();
-            }
-        }
-
-        void reset() {
-            if (!mInitialized) {
-                return;
-            }
-            // TODO: Need to implement reset.
-            Log.w(LOGTAG, "Reset is yet to be implemented");
-            nReset(mSetPtr);
-        }
-
-        // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
-        // animators or when the animator set has a start delay
-        void reverse() {
-            if (!mIsReversible) {
-                return;
-            }
-            // TODO: Need to support reverse (non-public API)
-            Log.w(LOGTAG, "Reverse is yet to be implemented");
-            nReverse(mSetPtr, this);
-        }
-
-        public long getAnimatorNativePtr() {
-            return mSetPtr;
-        }
-
-        boolean canReverse() {
-            return mIsReversible;
-        }
-
-        boolean isStarted() {
-            return mStarted;
-        }
-
-        boolean isRunning() {
-            if (!mInitialized) {
-                return false;
-            }
-            return mStarted;
-        }
-
-        void setListener(AnimatorListener listener) {
-            mListener = listener;
-        }
-
-        void removeListener() {
-            mListener = null;
-        }
-
-        private void onAnimationEnd() {
-            mStarted = false;
-            if (mListener != null) {
-                mListener.onAnimationEnd(null);
-            }
-            mTarget = null;
-        }
-
-        // onFinished: should be called from native
-        private static void callOnFinished(VectorDrawableAnimator set) {
-            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "on finished called from native");
-            }
-            set.onAnimationEnd();
-        }
-    }
-
-    private static native long nCreateAnimatorSet();
-    private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
-             long nativeInterpolator, long startDelay, long duration, int repeatCount);
-
-    private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
-            float startValue, float endValue);
-
-    private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
-            long endValuePtr);
-    private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
-            int startValue, int endValue);
-    private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId,
-            float startValue, float endValue);
-    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
-            float endValue);
-    private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
-    private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set);
-    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set);
-    private static native void nEnd(long animatorSetPtr);
-    private static native void nReset(long animatorSetPtr);
 }
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index f4bbc8c..1fc1b83 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -39,7 +39,6 @@
 import android.util.Xml;
 
 import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -48,7 +47,6 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Stack;
 
 /**
@@ -524,13 +522,13 @@
     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
             @NonNull AttributeSet attrs, @Nullable Theme theme)
             throws XmlPullParserException, IOException {
-        if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererRefBase != null) {
+        if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererPtr != 0) {
             // This VD has been used to display other VD resource content, clean up.
             mVectorState.mRootGroup = new VGroup();
-            if (mVectorState.mNativeRendererRefBase != null) {
-                mVectorState.mNativeRendererRefBase.release();
+            if (mVectorState.mNativeRendererPtr != 0) {
+                nDestroyRenderer(mVectorState.mNativeRendererPtr);
             }
-            mVectorState.createNativeRenderer(mVectorState.mRootGroup.mNativePtr);
+            mVectorState.mNativeRendererPtr = nCreateRenderer(mVectorState.mRootGroup.mNativePtr);
         }
         final VectorDrawableState state = mVectorState;
         state.setDensity(Drawable.resolveDensity(r, 0));
@@ -709,7 +707,7 @@
         return mVectorState.mAutoMirrored;
     }
 
-    static class VectorDrawableState extends ConstantState {
+    private static class VectorDrawableState extends ConstantState {
         // Variables below need to be copied (deep copy if applicable) for mutation.
         int[] mThemeAttrs;
         int mChangingConfigurations;
@@ -724,7 +722,7 @@
         Insets mOpticalInsets = Insets.NONE;
         String mRootName = null;
         VGroup mRootGroup;
-        VirtualRefBasePtr mNativeRendererRefBase = null;
+        long mNativeRendererPtr;
 
         int mDensity = DisplayMetrics.DENSITY_DEFAULT;
         final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
@@ -745,7 +743,7 @@
                 mTintMode = copy.mTintMode;
                 mAutoMirrored = copy.mAutoMirrored;
                 mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
-                createNativeRenderer(mRootGroup.mNativePtr);
+                mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr);
 
                 mBaseWidth = copy.mBaseWidth;
                 mBaseHeight = copy.mBaseHeight;
@@ -760,15 +758,18 @@
             }
         }
 
-        private void createNativeRenderer(long rootGroupPtr) {
-            mNativeRendererRefBase = new VirtualRefBasePtr(nCreateRenderer(rootGroupPtr));
+        @Override
+        public void finalize() throws Throwable {
+            if (mNativeRendererPtr != 0) {
+                nDestroyRenderer(mNativeRendererPtr);
+                mNativeRendererPtr = 0;
+            }
+            super.finalize();
         }
 
+
         long getNativeRenderer() {
-            if (mNativeRendererRefBase == null) {
-                return 0;
-            }
-            return mNativeRendererRefBase.get();
+            return mNativeRendererPtr;
         }
 
         public boolean canReuseCache() {
@@ -807,7 +808,7 @@
 
         public VectorDrawableState() {
             mRootGroup = new VGroup();
-            createNativeRenderer(mRootGroup.mNativePtr);
+            mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr);
         }
 
         @Override
@@ -871,16 +872,16 @@
          * has changed.
          */
         public boolean setAlpha(float alpha) {
-            return nSetRootAlpha(mNativeRendererRefBase.get(), alpha);
+            return nSetRootAlpha(mNativeRendererPtr, alpha);
         }
 
         @SuppressWarnings("unused")
         public float getAlpha() {
-            return nGetRootAlpha(mNativeRendererRefBase.get());
+            return nGetRootAlpha(mNativeRendererPtr);
         }
     }
 
-    static class VGroup implements VObject {
+    private static class VGroup implements VObject {
         private static final int ROTATE_INDEX = 0;
         private static final int PIVOT_X_INDEX = 1;
         private static final int PIVOT_Y_INDEX = 2;
@@ -890,28 +891,6 @@
         private static final int TRANSLATE_Y_INDEX = 6;
         private static final int TRANSFORM_PROPERTY_COUNT = 7;
 
-        private static final HashMap<String, Integer> sPropertyMap =
-                new HashMap<String, Integer>() {
-                    {
-                        put("translateX", TRANSLATE_X_INDEX);
-                        put("translateY", TRANSLATE_Y_INDEX);
-                        put("scaleX", SCALE_X_INDEX);
-                        put("scaleY", SCALE_Y_INDEX);
-                        put("pivotX", PIVOT_X_INDEX);
-                        put("pivotY", PIVOT_Y_INDEX);
-                        put("rotation", ROTATE_INDEX);
-                    }
-                };
-
-        static int getPropertyIndex(String propertyName) {
-            if (sPropertyMap.containsKey(propertyName)) {
-                return sPropertyMap.get(propertyName);
-            } else {
-                // property not found
-                return -1;
-            }
-        }
-
         // Temp array to store transform values obtained from native.
         private float[] mTransform;
         /////////////////////////////////////////////////////
@@ -1170,7 +1149,7 @@
     /**
      * Common Path information for clip path and normal path.
      */
-    static abstract class VPath implements VObject {
+    private static abstract class VPath implements VObject {
         protected PathParser.PathData mPathData = null;
 
         String mPathName;
@@ -1281,7 +1260,7 @@
     /**
      * Normal path, which contains all the fill / paint information.
      */
-    static class VFullPath extends VPath {
+    private static class VFullPath extends VPath {
         private static final int STROKE_WIDTH_INDEX = 0;
         private static final int STROKE_COLOR_INDEX = 1;
         private static final int STROKE_ALPHA_INDEX = 2;
@@ -1295,20 +1274,6 @@
         private static final int STROKE_MITER_LIMIT_INDEX = 10;
         private static final int TOTAL_PROPERTY_COUNT = 11;
 
-        private final static HashMap<String, Integer> sPropertyMap
-                = new HashMap<String, Integer> () {
-            {
-                put("strokeWidth", STROKE_WIDTH_INDEX);
-                put("strokeColor", STROKE_COLOR_INDEX);
-                put("strokeAlpha", STROKE_ALPHA_INDEX);
-                put("fillColor", FILL_COLOR_INDEX);
-                put("fillAlpha", FILL_ALPHA_INDEX);
-                put("trimPathStart", TRIM_PATH_START_INDEX);
-                put("trimPathEnd", TRIM_PATH_END_INDEX);
-                put("trimPathOffset", TRIM_PATH_OFFSET_INDEX);
-            }
-        };
-
         // Temp array to store property data obtained from native getter.
         private byte[] mPropertyData;
         /////////////////////////////////////////////////////
@@ -1332,14 +1297,6 @@
             mFillColors = copy.mFillColors;
         }
 
-        int getPropertyIndex(String propertyName) {
-            if (!sPropertyMap.containsKey(propertyName)) {
-                return -1;
-            } else {
-                return sPropertyMap.get(propertyName);
-            }
-        }
-
         @Override
         public boolean onStateChange(int[] stateSet) {
             boolean changed = false;
@@ -1638,6 +1595,7 @@
     }
 
     private static native long nCreateRenderer(long rootGroupPtr);
+    private static native void nDestroyRenderer(long rendererPtr);
     private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
             float viewportHeight);
     private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index c232bd1..1fb9ac5 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -78,8 +78,6 @@
     Program.cpp \
     ProgramCache.cpp \
     Properties.cpp \
-    PropertyValuesHolder.cpp \
-    PropertyValuesAnimatorSet.cpp \
     RenderBufferCache.cpp \
     RenderNode.cpp \
     RenderProperties.cpp \
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 7bd2b24..5ca2a2f 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -90,9 +90,6 @@
         doSetStartValue(getValue(mTarget));
     }
     if (mStagingPlayState > mPlayState) {
-        if (mStagingPlayState == PlayState::Restarted) {
-            mStagingPlayState = PlayState::Running;
-        }
         mPlayState = mStagingPlayState;
         // Oh boy, we're starting! Man the battle stations!
         if (mPlayState == PlayState::Running) {
@@ -134,11 +131,6 @@
         return true;
     }
 
-    // This should be set before setValue() so animators can query this time when setValue
-    // is called.
-    nsecs_t currentFrameTime = context.frameTimeMs();
-    onPlayTimeChanged(currentFrameTime - mStartTime);
-
     // If BaseRenderNodeAnimator is handling the delay (not typical), then
     // because the staging properties reflect the final value, we always need
     // to call setValue even if the animation isn't yet running or is still
@@ -149,9 +141,8 @@
     }
 
     float fraction = 1.0f;
-
     if (mPlayState == PlayState::Running && mDuration > 0) {
-        fraction = (float)(currentFrameTime - mStartTime) / mDuration;
+        fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration;
     }
     if (fraction >= 1.0f) {
         fraction = 1.0f;
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 2c9c9c3..aea95bf 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -59,13 +59,7 @@
         mMayRunAsync = mayRunAsync;
     }
     bool mayRunAsync() { return mMayRunAsync; }
-    ANDROID_API void start() {
-        if (mStagingPlayState == PlayState::NotStarted) {
-            mStagingPlayState = PlayState::Running;
-        } else {
-            mStagingPlayState = PlayState::Restarted;
-        }
-        onStagingPlayStateChanged(); }
+    ANDROID_API void start() { mStagingPlayState = PlayState::Running; onStagingPlayStateChanged(); }
     ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
 
     void attach(RenderNode* target);
@@ -83,27 +77,10 @@
     void forceEndNow(AnimationContext& context);
 
 protected:
-    // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
-    // thread and Render Thread animation state, respectively.
-    // From the UI thread, mStagingPlayState transition looks like
-    // NotStarted -> Running -> Finished
-    //                ^            |
-    //                |            |
-    //            Restarted <------
-    // Note: For mStagingState, the Finished state (optional) is only set when the animation is
-    // terminated by user.
-    //
-    // On Render Thread, mPlayState transition:
-    // NotStart -> Running -> Finished
-    //                ^            |
-    //                |            |
-    //                -------------
-
     enum class PlayState {
         NotStarted,
         Running,
         Finished,
-        Restarted,
     };
 
     BaseRenderNodeAnimator(float finalValue);
@@ -116,7 +93,6 @@
     void callOnFinishedListener(AnimationContext& context);
 
     virtual void onStagingPlayStateChanged() {}
-    virtual void onPlayTimeChanged(nsecs_t playTime) {}
 
     RenderNode* mTarget;
 
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 2184755..e3a5f3e 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -663,7 +663,7 @@
 }
 
 void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
-    TessellationCache::vertexBuffer_pair_t buffers = *(op.shadowTask->getResult());
+    TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult();
     renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
 }
 
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index 27facdf..dbd502d 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -52,13 +52,6 @@
 
 } // namespace SaveFlags
 
-namespace uirenderer {
-namespace VectorDrawable {
-class Tree;
-};
-};
-typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
-
 class ANDROID_API Canvas {
 public:
     virtual ~Canvas() {};
@@ -224,11 +217,6 @@
      */
     virtual bool drawTextAbsolutePos() const = 0;
 
-    /**
-     * Draws a VectorDrawable onto the canvas.
-     */
-    virtual void drawVectorDrawable(VectorDrawableRoot* tree);
-
 protected:
     void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
 };
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 160090d..9c08b4d 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -213,6 +213,7 @@
 
 void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
         SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     switch (mMode) {
     case ClipMode::Rectangle:
@@ -228,6 +229,7 @@
 }
 
 void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     enterRegionMode();
     mClipRegion.op(region, op);
@@ -236,6 +238,7 @@
 
 void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
         SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     SkMatrix skTransform;
     transform->copyTo(skTransform);
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index e44fc20..250296e 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -57,7 +57,7 @@
     // Returns the current dirty area, *NOT* transformed by pushed transforms
     void peekAtDirty(SkRect* dest) const;
 
-    void computeCurrentTransform(Matrix4* outMatrix) const;
+    ANDROID_API void computeCurrentTransform(Matrix4* outMatrix) const;
 
     void finish(SkRect* totalDirty);
 
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 3db14b5..7eaa785 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -16,12 +16,11 @@
 
 #include "DisplayListCanvas.h"
 
+#include "ResourceCache.h"
 #include "DeferredDisplayList.h"
 #include "DeferredLayerUpdater.h"
 #include "DisplayListOp.h"
-#include "ResourceCache.h"
 #include "RenderNode.h"
-#include "VectorDrawable.h"
 #include "utils/PaintUtils.h"
 
 #include <SkCamera.h>
@@ -413,16 +412,6 @@
     addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint)));
 }
 
-void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
-    mDisplayList->ref(tree);
-    const SkBitmap& bitmap = tree->getBitmapUpdateIfDirty();
-    SkPaint* paint = tree->getPaint();
-    const SkRect bounds = tree->getBounds();
-    addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
-            0, 0, bitmap.width(), bitmap.height(),
-            bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), refPaint(paint)));
-}
-
 void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
         const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
     if (!glyphs || count <= 0) return;
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 06e72a0..ad93960 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -206,8 +206,6 @@
             float dstLeft, float dstTop, float dstRight, float dstBottom,
             const SkPaint* paint) override;
 
-    virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
-
     // Text
     virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
             const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
@@ -216,6 +214,7 @@
             float hOffset, float vOffset, const SkPaint& paint) override;
     virtual bool drawTextAbsolutePos() const override { return false; }
 
+
 private:
 
     CanvasState mState;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 57e5b9d..c8910cb 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -19,7 +19,6 @@
 #include "Canvas.h"
 #include "LayerUpdateQueue.h"
 #include "RenderNode.h"
-#include "VectorDrawable.h"
 #include "renderstate/OffscreenBufferPool.h"
 #include "utils/FatVector.h"
 #include "utils/PaintUtils.h"
@@ -203,7 +202,9 @@
         mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline()));
     }
 
-    if (!mCanvasState.quickRejectConservative(0, 0, width, height)) {
+    bool quickRejected = properties.getClipToBounds()
+            && mCanvasState.quickRejectConservative(0, 0, width, height);
+    if (!quickRejected) {
         // not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
         if (node.getLayer()) {
             // HW layer
@@ -544,18 +545,6 @@
     currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
 }
 
-void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
-    const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
-    SkPaint* paint = op.vectorDrawable->getPaint();
-    const BitmapRectOp* resolvedOp = new (mAllocator) BitmapRectOp(op.unmappedBounds,
-            op.localMatrix,
-            op.localClip,
-            paint,
-            &bitmap,
-            Rect(bitmap.width(), bitmap.height()));
-    deferBitmapRectOp(*resolvedOp);
-}
-
 void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) {
     // allocate a temporary oval op (with mAllocator, so it persists until render), so the
     // renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
deleted file mode 100644
index eca1afcc..0000000
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "PropertyValuesAnimatorSet.h"
-#include "RenderNode.h"
-
-namespace android {
-namespace uirenderer {
-
-void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
-            Interpolator* interpolator, nsecs_t startDelay,
-            nsecs_t duration, int repeatCount) {
-
-    PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
-            interpolator, startDelay, duration, repeatCount);
-    mAnimators.emplace_back(animator);
-    setListener(new PropertyAnimatorSetListener(this));
-}
-
-PropertyValuesAnimatorSet::PropertyValuesAnimatorSet()
-        : BaseRenderNodeAnimator(1.0f) {
-    setStartValue(0);
-    mLastFraction = 0.0f;
-    setInterpolator(new LinearInterpolator());
-}
-
-void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) {
-    if (mOneShotListener.get()) {
-        mOneShotListener->onAnimationFinished(animator);
-        mOneShotListener = nullptr;
-    }
-}
-
-float PropertyValuesAnimatorSet::getValue(RenderNode* target) const {
-    return mLastFraction;
-}
-
-void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) {
-    mLastFraction = value;
-}
-
-void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
-    for (size_t i = 0; i < mAnimators.size(); i++) {
-        mAnimators[i]->setCurrentPlayTime(playTime);
-    }
-}
-
-void PropertyValuesAnimatorSet::reset() {
-    // TODO: implement reset through adding a play state because we need to support reset() even
-    // during an animation run.
-}
-
-void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
-    init();
-    mOneShotListener = listener;
-    BaseRenderNodeAnimator::start();
-}
-
-void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
-// TODO: implement reverse
-}
-
-void PropertyValuesAnimatorSet::init() {
-    if (mInitialized) {
-        return;
-    }
-    nsecs_t maxDuration = 0;
-    for (size_t i = 0; i < mAnimators.size(); i++) {
-        if (maxDuration < mAnimators[i]->getTotalDuration()) {
-            maxDuration = mAnimators[i]->getTotalDuration();
-        }
-    }
-    mDuration = maxDuration;
-    mInitialized = true;
-}
-
-uint32_t PropertyValuesAnimatorSet::dirtyMask() {
-    return RenderNode::DISPLAY_LIST;
-}
-
-PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
-        nsecs_t startDelay, nsecs_t duration, int repeatCount)
-        : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay),
-          mDuration(duration) {
-    if (repeatCount < 0) {
-        mRepeatCount = UINT32_MAX;
-    } else {
-        mRepeatCount = repeatCount;
-    }
-    mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay;
-}
-
-void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
-    if (playTime >= mStartDelay && playTime < mTotalDuration) {
-         nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
-         mLatestFraction = currentIterationPlayTime / (float) mDuration;
-    } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
-        mLatestFraction = 1.0f;
-    } else {
-        return;
-    }
-
-    setFraction(mLatestFraction);
-}
-
-void PropertyAnimator::setFraction(float fraction) {
-    float interpolatedFraction = mInterpolator->interpolate(mLatestFraction);
-    mPropertyValuesHolder->setFraction(interpolatedFraction);
-}
-
-void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) {
-    mSet->onFinished(animator);
-}
-
-}
-}
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
deleted file mode 100644
index 4c7ce52..0000000
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "Animator.h"
-#include "PropertyValuesHolder.h"
-#include "Interpolator.h"
-
-namespace android {
-namespace uirenderer {
-
-class PropertyAnimator {
-public:
-    PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay,
-            nsecs_t duration, int repeatCount);
-    void setCurrentPlayTime(nsecs_t playTime);
-    nsecs_t getTotalDuration() {
-        return mTotalDuration;
-    }
-    void setFraction(float fraction);
-
-private:
-    std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder;
-    std::unique_ptr<Interpolator> mInterpolator;
-    nsecs_t mStartDelay;
-    nsecs_t mDuration;
-    uint32_t mRepeatCount;
-    nsecs_t mTotalDuration;
-    float mLatestFraction = 0.0f;
-};
-
-class ANDROID_API PropertyValuesAnimatorSet : public BaseRenderNodeAnimator {
-public:
-    friend class PropertyAnimatorSetListener;
-    PropertyValuesAnimatorSet();
-
-    void start(AnimationListener* listener);
-    void reverse(AnimationListener* listener);
-    void reset();
-
-    void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
-            Interpolator* interpolators, int64_t startDelays,
-            nsecs_t durations, int repeatCount);
-    virtual uint32_t dirtyMask();
-
-protected:
-    virtual float getValue(RenderNode* target) const override;
-    virtual void setValue(RenderNode* target, float value) override;
-    virtual void onPlayTimeChanged(nsecs_t playTime) override;
-
-private:
-    void init();
-    void onFinished(BaseRenderNodeAnimator* animator);
-    // Listener set from outside
-    sp<AnimationListener> mOneShotListener;
-    std::vector< std::unique_ptr<PropertyAnimator> > mAnimators;
-    float mLastFraction = 0.0f;
-    bool mInitialized = false;
-};
-
-class PropertyAnimatorSetListener : public AnimationListener {
-public:
-    PropertyAnimatorSetListener(PropertyValuesAnimatorSet* set) : mSet(set) {}
-    virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) override;
-
-private:
-    PropertyValuesAnimatorSet* mSet;
-};
-
-} // namespace uirenderer
-} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
deleted file mode 100644
index 8f837f6..0000000
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "PropertyValuesHolder.h"
-
-#include "utils/VectorDrawableUtils.h"
-
-#include <utils/Log.h>
-
-namespace android {
-namespace uirenderer {
-
-using namespace VectorDrawable;
-
-float PropertyValuesHolder::getValueFromData(float fraction) {
-    if (mDataSource.size() == 0) {
-        LOG_ALWAYS_FATAL("No data source is defined");
-        return 0;
-    }
-    if (fraction <= 0.0f) {
-        return mDataSource.front();
-    }
-    if (fraction >= 1.0f) {
-        return mDataSource.back();
-    }
-
-    fraction *= mDataSource.size() - 1;
-    int lowIndex = floor(fraction);
-    fraction -= lowIndex;
-
-    float value = mDataSource[lowIndex] * (1.0f - fraction)
-            + mDataSource[lowIndex + 1] * fraction;
-    return value;
-}
-
-void GroupPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue;
-    if (mDataSource.size() > 0) {
-        animatedValue = getValueFromData(fraction);
-    } else {
-        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
-    }
-    mGroup->setPropertyValue(mPropertyId, animatedValue);
-}
-
-inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
-    return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
-}
-
-// TODO: Add a test for this
-SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor,
-        float fraction) {
-    U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
-    U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
-    U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
-    U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
-    return SkColorSetARGB(alpha, red, green, blue);
-}
-
-void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
-    SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
-    mFullPath->setColorPropertyValue(mPropertyId, animatedValue);
-}
-
-void FullPathPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue;
-    if (mDataSource.size() > 0) {
-        animatedValue = getValueFromData(fraction);
-    } else {
-        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
-    }
-    mFullPath->setPropertyValue(mPropertyId, animatedValue);
-}
-
-void PathDataPropertyValuesHolder::setFraction(float fraction) {
-    VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
-    mPath->setPathData(mPathData);
-}
-
-void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
-    mTree->setRootAlpha(animatedValue);
-}
-
-} // namepace uirenderer
-} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h
deleted file mode 100644
index b905fae..0000000
--- a/libs/hwui/PropertyValuesHolder.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "VectorDrawable.h"
-
-#include <SkColor.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * PropertyValues holder contains data needed to change a property of a Vector Drawable object.
- * When a fraction in [0f, 1f] is provided, the holder will calculate an interpolated value based
- * on its start and end value, and set the new value on the VectorDrawble's corresponding property.
- */
-class ANDROID_API PropertyValuesHolder {
-public:
-    virtual void setFraction(float fraction) = 0;
-    void setPropertyDataSource(float* dataSource, int length) {
-        mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
-    }
-   float getValueFromData(float fraction);
-   virtual ~PropertyValuesHolder() {}
-protected:
-   std::vector<float> mDataSource;
-};
-
-class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder {
-public:
-    GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue,
-            float endValue)
-            : mGroup(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue){
-    }
-    void setFraction(float fraction) override;
-private:
-    VectorDrawable::Group* mGroup;
-    int mPropertyId;
-    float mStartValue;
-    float mEndValue;
-};
-
-class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder {
-public:
-    FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue,
-            int32_t endValue)
-            : mFullPath(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {};
-    void setFraction(float fraction) override;
-    static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction);
-private:
-    VectorDrawable::FullPath* mFullPath;
-    int mPropertyId;
-    int32_t mStartValue;
-    int32_t mEndValue;
-};
-
-class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder {
-public:
-    FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue,
-            float endValue)
-            : mFullPath(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {};
-    void setFraction(float fraction) override;
-private:
-    VectorDrawable::FullPath* mFullPath;
-    int mPropertyId;
-    float mStartValue;
-    float mEndValue;
-};
-
-class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder {
-public:
-    PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue,
-            PathData* endValue)
-            : mPath(ptr)
-            , mStartValue(*startValue)
-            , mEndValue(*endValue) {};
-    void setFraction(float fraction) override;
-private:
-    VectorDrawable::Path* mPath;
-    PathData mPathData;
-    PathData mStartValue;
-    PathData mEndValue;
-};
-
-class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder {
-public:
-    RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue)
-            : mTree(tree)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {}
-    void setFraction(float fraction) override;
-private:
-    VectorDrawable::Tree* mTree;
-    float mStartValue;
-    float mEndValue;
-};
-}
-}
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index bb26e2e..593d690 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -17,7 +17,6 @@
 #ifndef ANDROID_HWUI_RECORDED_OP_H
 #define ANDROID_HWUI_RECORDED_OP_H
 
-#include "RecordedOp.h"
 #include "font/FontUtil.h"
 #include "Matrix.h"
 #include "Rect.h"
@@ -40,10 +39,6 @@
 class RenderNode;
 struct Vertex;
 
-namespace VectorDrawable {
-class Tree;
-}
-
 /**
  * Authoritative op list, used for generating the op ID enum, ID based LUTS, and
  * the functions to which they dispatch. Parameter macros are executed for each op,
@@ -80,7 +75,6 @@
         PRE_RENDER_OP_FN(EndLayerOp) \
         PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
         PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
-        PRE_RENDER_OP_FN(VectorDrawableOp) \
         \
         RENDER_ONLY_OP_FN(ShadowOp) \
         RENDER_ONLY_OP_FN(LayerOp) \
@@ -331,13 +325,6 @@
     const float* ry;
 };
 
-struct VectorDrawableOp : RecordedOp {
-    VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
-            : SUPER_PAINTLESS(VectorDrawableOp)
-            , vectorDrawable(tree) {}
-    VectorDrawable::Tree* vectorDrawable;
-};
-
 /**
  * Real-time, dynamic-lit shadow.
  *
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 16929b8..2387962 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -19,7 +19,6 @@
 #include "DeferredLayerUpdater.h"
 #include "RecordedOp.h"
 #include "RenderNode.h"
-#include "VectorDrawable.h"
 
 namespace android {
 namespace uirenderer {
@@ -396,6 +395,7 @@
             &x->value, &y->value, &radius->value));
 }
 
+
 void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
     addOp(new (alloc()) OvalOp(
             Rect(left, top, right, bottom),
@@ -422,15 +422,6 @@
             refPaint(&paint), refPath(&path)));
 }
 
-void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
-    mDisplayList->ref(tree);
-    addOp(new (alloc()) VectorDrawableOp(
-            tree,
-            Rect(tree->getBounds()),
-            *(mState.currentSnapshot()->transform),
-            getRecordedClip()));
-}
-
 // Bitmap-based
 void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
     save(SaveFlags::Matrix);
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index cc14e61..375760f 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -175,8 +175,6 @@
             const uint16_t* indices, int indexCount, const SkPaint& paint) override
         { /* RecordingCanvas does not support drawVertices(); ignore */ }
 
-    virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
-
     // Bitmap-based
     virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
     virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d4588ed..bade216 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -381,6 +381,10 @@
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
 
+    if (CC_UNLIKELY(mPositionListener.get())) {
+        mPositionListener->onPositionUpdated(*this, info);
+    }
+
     prepareLayer(info, animatorDirtyMask);
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingDisplayListChanges(info);
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 8e4a3df..f248de54 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -209,6 +209,19 @@
     OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
 #endif
 
+    class ANDROID_API PositionListener {
+    public:
+        virtual ~PositionListener() {}
+        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
+    };
+
+    // Note this is not thread safe, this needs to be called
+    // before the RenderNode is used for drawing.
+    // RenderNode takes ownership of the pointer
+    ANDROID_API void setPositionListener(PositionListener* listener) {
+        mPositionListener.reset(listener);
+    }
+
 private:
     typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
 
@@ -317,6 +330,8 @@
     // This is *NOT* thread-safe, and should therefore only be tracking
     // mDisplayList, not mStagingDisplayList.
     uint32_t mParentCount;
+
+    std::unique_ptr<PositionListener> mPositionListener;
 }; // class RenderNode
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index bd4442d..d320a41 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -32,8 +32,6 @@
 #include <SkTLazy.h>
 #include <SkTemplates.h>
 
-#include "VectorDrawable.h"
-
 #include <memory>
 
 namespace android {
@@ -155,7 +153,6 @@
             float hOffset, float vOffset, const SkPaint& paint) override;
 
     virtual bool drawTextAbsolutePos() const  override { return true; }
-    virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
 
     virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
             uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
@@ -745,14 +742,6 @@
     NinePatch::Draw(mCanvas, bounds, bitmap, chunk, paint, nullptr);
 }
 
-void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
-    const SkBitmap& bitmap = vectorDrawable->getBitmapUpdateIfDirty();
-    SkRect bounds = vectorDrawable->getBounds();
-    drawBitmap(bitmap, 0, 0, bitmap.width(), bitmap.height(),
-            bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
-            vectorDrawable->getPaint());
-}
-
 // ----------------------------------------------------------------------------
 // Canvas draw operations: Text
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 461e819..fd9fb852 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -242,23 +242,21 @@
             spotBuffer);
 }
 
-class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> {
+class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t> {
 public:
     ShadowProcessor(Caches& caches)
-            : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {}
+            : TaskProcessor<TessellationCache::vertexBuffer_pair_t>(&caches.tasks) {}
     ~ShadowProcessor() {}
 
-    virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) override {
+    virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t> >& task) override {
         TessellationCache::ShadowTask* t = static_cast<TessellationCache::ShadowTask*>(task.get());
         ATRACE_NAME("shadow tessellation");
 
-        VertexBuffer* ambientBuffer = new VertexBuffer;
-        VertexBuffer* spotBuffer = new VertexBuffer;
         tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
                 &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
-                *ambientBuffer, *spotBuffer);
+                t->ambientBuffer, t->spotBuffer);
 
-        t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer));
+        t->setResult(TessellationCache::vertexBuffer_pair_t(&t->ambientBuffer, &t->spotBuffer));
     }
 };
 
@@ -373,7 +371,7 @@
         task = static_cast<ShadowTask*>(mShadowCache.get(key));
     }
     LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
-    outBuffers = *(task->getResult());
+    outBuffers = task->getResult();
 }
 
 sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
@@ -392,13 +390,6 @@
     return task;
 }
 
-TessellationCache::ShadowTask::~ShadowTask() {
-    TessellationCache::vertexBuffer_pair_t* bufferPair = getResult();
-    delete bufferPair->getFirst();
-    delete bufferPair->getSecond();
-    delete bufferPair;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Tessellation precaching
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 977c2d9e..6dcc8120 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -21,6 +21,7 @@
 #include "Matrix.h"
 #include "Rect.h"
 #include "Vector.h"
+#include "VertexBuffer.h"
 #include "thread/TaskProcessor.h"
 #include "utils/Macros.h"
 #include "utils/Pair.h"
@@ -89,7 +90,7 @@
         hash_t hash() const;
     };
 
-    class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> {
+    class ShadowTask : public Task<vertexBuffer_pair_t> {
     public:
         ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
                 const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
@@ -104,13 +105,11 @@
             , lightRadius(lightRadius) {
         }
 
-        ~ShadowTask();
-
         /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
          * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
          * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
          *
-         * These deep copies could be avoided, long term, by cancelling or flushing outstanding
+         * These deep copies could be avoided, long term, by canceling or flushing outstanding
          * tasks before tearing down single-frame LinearAllocators.
          */
         const Matrix4 drawTransform;
@@ -121,6 +120,8 @@
         const Matrix4 transformZ;
         const Vector3 lightCenter;
         const float lightRadius;
+        VertexBuffer ambientBuffer;
+        VertexBuffer spotBuffer;
     };
 
     TessellationCache();
@@ -217,12 +218,12 @@
     ///////////////////////////////////////////////////////////////////////////////
     // Shadow tessellation caching
     ///////////////////////////////////////////////////////////////////////////////
-    sp<TaskProcessor<vertexBuffer_pair_t*> > mShadowProcessor;
+    sp<TaskProcessor<vertexBuffer_pair_t> > mShadowProcessor;
 
     // holds a pointer, and implicit strong ref to each shadow task of the frame
-    LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*> mShadowCache;
-    class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t*>*> {
-        void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t*>*& bufferPairTask) override {
+    LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache;
+    class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
+        void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t>*& bufferPairTask) override {
             bufferPairTask->decStrong(nullptr);
         }
     };
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index be25516..accd303 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -86,6 +86,12 @@
 #endif
     ErrorHandler* errorHandler = nullptr;
 
+    // Frame number for use with synchronized surfaceview position updating
+    int64_t frameNumber = -1;
+    int32_t windowInsetLeft = 0;
+    int32_t windowInsetTop = 0;
+    bool updateWindowPositions = false;
+
     struct Out {
         bool hasFunctors = false;
         // This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 541c799..1cf15ac 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -138,7 +138,18 @@
 }
 
 FullPath::FullPath(const FullPath& path) : Path(path) {
-    mProperties = path.mProperties;
+    mStrokeWidth = path.mStrokeWidth;
+    mStrokeColor = path.mStrokeColor;
+    mStrokeAlpha = path.mStrokeAlpha;
+    mFillColor = path.mFillColor;
+    mFillAlpha = path.mFillAlpha;
+    mTrimPathStart = path.mTrimPathStart;
+    mTrimPathEnd = path.mTrimPathEnd;
+    mTrimPathOffset = path.mTrimPathOffset;
+    mStrokeMiterLimit = path.mStrokeMiterLimit;
+    mStrokeLineCap = path.mStrokeLineCap;
+    mStrokeLineJoin = path.mStrokeLineJoin;
+
     SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient);
     SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient);
 }
@@ -148,7 +159,7 @@
         return mTrimmedSkPath;
     }
     Path::getUpdatedPath();
-    if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) {
+    if (mTrimPathStart != 0.0f || mTrimPathEnd != 1.0f) {
         applyTrim();
         return mTrimmedSkPath;
     } else {
@@ -159,14 +170,14 @@
 void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
         SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
         float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) {
-    mProperties.strokeWidth = strokeWidth;
-    mProperties.strokeColor = strokeColor;
-    mProperties.strokeAlpha = strokeAlpha;
-    mProperties.fillColor = fillColor;
-    mProperties.fillAlpha = fillAlpha;
-    mProperties.strokeMiterLimit = strokeMiterLimit;
-    mProperties.strokeLineCap = strokeLineCap;
-    mProperties.strokeLineJoin = strokeLineJoin;
+    mStrokeWidth = strokeWidth;
+    mStrokeColor = strokeColor;
+    mStrokeAlpha = strokeAlpha;
+    mFillColor = fillColor;
+    mFillAlpha = fillAlpha;
+    mStrokeMiterLimit = strokeMiterLimit;
+    mStrokeLineCap = SkPaint::Cap(strokeLineCap);
+    mStrokeLineJoin = SkPaint::Join(strokeLineJoin);
 
     // If any trim property changes, mark trim dirty and update the trim path
     setTrimPathStart(trimPathStart);
@@ -184,12 +195,12 @@
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
     if (mFillGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha));
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha));
         SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix);
         mPaint.setShader(newShader);
         needsFill = true;
-    } else if (mProperties.fillColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha));
+    } else if (mFillColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mFillColor, mFillAlpha));
         needsFill = true;
     }
 
@@ -202,21 +213,21 @@
     // Draw path's stroke, if stroke color or gradient is valid
     bool needsStroke = false;
     if (mStrokeGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha));
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha));
         SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix);
         mPaint.setShader(newShader);
         needsStroke = true;
-    } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha));
+    } else if (mStrokeColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha));
         needsStroke = true;
     }
     if (needsStroke) {
         mPaint.setStyle(SkPaint::Style::kStroke_Style);
         mPaint.setAntiAlias(true);
-        mPaint.setStrokeJoin(SkPaint::Join(mProperties.strokeLineJoin));
-        mPaint.setStrokeCap(SkPaint::Cap(mProperties.strokeLineCap));
-        mPaint.setStrokeMiter(mProperties.strokeMiterLimit);
-        mPaint.setStrokeWidth(mProperties.strokeWidth * strokeScale);
+        mPaint.setStrokeJoin(mStrokeLineJoin);
+        mPaint.setStrokeCap(mStrokeLineCap);
+        mPaint.setStrokeMiter(mStrokeMiterLimit);
+        mPaint.setStrokeWidth(mStrokeWidth * strokeScale);
         outCanvas->drawPath(renderPath, mPaint);
     }
 }
@@ -225,14 +236,14 @@
  * Applies trimming to the specified path.
  */
 void FullPath::applyTrim() {
-    if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) {
+    if (mTrimPathStart == 0.0f && mTrimPathEnd == 1.0f) {
         // No trimming necessary.
         return;
     }
     SkPathMeasure measure(mSkPath, false);
     float len = SkScalarToFloat(measure.getLength());
-    float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f);
-    float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f);
+    float start = len * fmod((mTrimPathStart + mTrimPathOffset), 1.0f);
+    float end = len * fmod((mTrimPathEnd + mTrimPathOffset), 1.0f);
 
     mTrimmedSkPath.reset();
     if (start > end) {
@@ -244,69 +255,76 @@
     mTrimDirty = false;
 }
 
-REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties);
+inline int putData(int8_t* outBytes, int startIndex, float value) {
+    int size = sizeof(float);
+    memcpy(&outBytes[startIndex], &value, size);
+    return size;
+}
+
+inline int putData(int8_t* outBytes, int startIndex, int value) {
+    int size = sizeof(int);
+    memcpy(&outBytes[startIndex], &value, size);
+    return size;
+}
+
+struct FullPathProperties {
+    // TODO: Consider storing full path properties in this struct instead of the fields.
+    float strokeWidth;
+    SkColor strokeColor;
+    float strokeAlpha;
+    SkColor fillColor;
+    float fillAlpha;
+    float trimPathStart;
+    float trimPathEnd;
+    float trimPathOffset;
+    int32_t strokeLineCap;
+    int32_t strokeLineJoin;
+    float strokeMiterLimit;
+};
+
+REQUIRE_COMPATIBLE_LAYOUT(FullPathProperties);
 
 static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t");
 static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t");
 
 bool FullPath::getProperties(int8_t* outProperties, int length) {
-    int propertyDataSize = sizeof(Properties);
+    int propertyDataSize = sizeof(FullPathProperties);
     if (length != propertyDataSize) {
         LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                 propertyDataSize, length);
         return false;
     }
-    Properties* out = reinterpret_cast<Properties*>(outProperties);
-    *out = mProperties;
+    // TODO: consider replacing the property fields with a FullPathProperties struct.
+    FullPathProperties properties;
+    properties.strokeWidth = mStrokeWidth;
+    properties.strokeColor = mStrokeColor;
+    properties.strokeAlpha = mStrokeAlpha;
+    properties.fillColor = mFillColor;
+    properties.fillAlpha = mFillAlpha;
+    properties.trimPathStart = mTrimPathStart;
+    properties.trimPathEnd = mTrimPathEnd;
+    properties.trimPathOffset = mTrimPathOffset;
+    properties.strokeLineCap = mStrokeLineCap;
+    properties.strokeLineJoin = mStrokeLineJoin;
+    properties.strokeMiterLimit = mStrokeMiterLimit;
+
+    memcpy(outProperties, &properties, length);
     return true;
 }
 
-void FullPath::setColorPropertyValue(int propertyId, int32_t value) {
-    Property currentProperty = static_cast<Property>(propertyId);
-    if (currentProperty == Property::StrokeColor) {
-        mProperties.strokeColor = value;
-    } else if (currentProperty == Property::FillColor) {
-        mProperties.fillColor = value;
-    } else {
-        LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d",
-                propertyId);
-    }
-}
-
-void FullPath::setPropertyValue(int propertyId, float value) {
-    Property property = static_cast<Property>(propertyId);
-    switch (property) {
-    case Property::StrokeWidth:
-        setStrokeWidth(value);
-        break;
-    case Property::StrokeAlpha:
-        setStrokeAlpha(value);
-        break;
-    case Property::FillAlpha:
-        setFillAlpha(value);
-        break;
-    case Property::TrimPathStart:
-        setTrimPathStart(value);
-        break;
-    case Property::TrimPathEnd:
-        setTrimPathEnd(value);
-        break;
-    case Property::TrimPathOffset:
-        setTrimPathOffset(value);
-        break;
-    default:
-        LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId);
-        break;
-    }
-}
-
 void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
         float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
 
 Group::Group(const Group& group) : Node(group) {
-    mProperties = group.mProperties;
+    mRotate = group.mRotate;
+    mPivotX = group.mPivotX;
+    mPivotY = group.mPivotY;
+    mScaleX = group.mScaleX;
+    mScaleY = group.mScaleY;
+    mTranslateX = group.mTranslateX;
+    mTranslateY = group.mTranslateY;
 }
 
 void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX,
@@ -353,11 +371,10 @@
     outMatrix->reset();
     // TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of
     // translating to pivot for rotating and scaling, then translating back.
-    outMatrix->postTranslate(-mProperties.pivotX, -mProperties.pivotY);
-    outMatrix->postScale(mProperties.scaleX, mProperties.scaleY);
-    outMatrix->postRotate(mProperties.rotate, 0, 0);
-    outMatrix->postTranslate(mProperties.translateX + mProperties.pivotX,
-            mProperties.translateY + mProperties.pivotY);
+    outMatrix->postTranslate(-mPivotX, -mPivotY);
+    outMatrix->postScale(mScaleX, mScaleY);
+    outMatrix->postRotate(mRotate, 0, 0);
+    outMatrix->postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
 }
 
 void Group::addChild(Node* child) {
@@ -371,68 +388,38 @@
                 propertyCount, length);
         return false;
     }
-    Properties* out = reinterpret_cast<Properties*>(outProperties);
-    *out = mProperties;
+    for (int i = 0; i < propertyCount; i++) {
+        Property currentProperty = static_cast<Property>(i);
+        switch (currentProperty) {
+        case Property::Rotate_Property:
+            outProperties[i] = mRotate;
+            break;
+        case Property::PivotX_Property:
+            outProperties[i] = mPivotX;
+            break;
+        case Property::PivotY_Property:
+            outProperties[i] = mPivotY;
+            break;
+        case Property::ScaleX_Property:
+            outProperties[i] = mScaleX;
+            break;
+        case Property::ScaleY_Property:
+            outProperties[i] = mScaleY;
+            break;
+        case Property::TranslateX_Property:
+            outProperties[i] = mTranslateX;
+            break;
+        case Property::TranslateY_Property:
+            outProperties[i] = mTranslateY;
+            break;
+        default:
+            LOG_ALWAYS_FATAL("Invalid input index: %d", i);
+            return false;
+        }
+    }
     return true;
 }
 
-// TODO: Consider animating the properties as float pointers
-float Group::getPropertyValue(int propertyId) const {
-    Property currentProperty = static_cast<Property>(propertyId);
-    switch (currentProperty) {
-    case Property::Rotate:
-        return mProperties.rotate;
-    case Property::PivotX:
-        return mProperties.pivotX;
-    case Property::PivotY:
-        return mProperties.pivotY;
-    case Property::ScaleX:
-        return mProperties.scaleX;
-    case Property::ScaleY:
-        return mProperties.scaleY;
-    case Property::TranslateX:
-        return mProperties.translateX;
-    case Property::TranslateY:
-        return mProperties.translateY;
-    default:
-        LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
-        return 0;
-    }
-}
-
-void Group::setPropertyValue(int propertyId, float value) {
-    Property currentProperty = static_cast<Property>(propertyId);
-    switch (currentProperty) {
-    case Property::Rotate:
-        mProperties.rotate = value;
-        break;
-    case Property::PivotX:
-        mProperties.pivotX = value;
-        break;
-    case Property::PivotY:
-        mProperties.pivotY = value;
-        break;
-    case Property::ScaleX:
-        mProperties.scaleX = value;
-        break;
-    case Property::ScaleY:
-        mProperties.scaleY = value;
-        break;
-    case Property::TranslateX:
-        mProperties.translateX = value;
-        break;
-    case Property::TranslateY:
-        mProperties.translateY = value;
-        break;
-    default:
-        LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
-    }
-}
-
-bool Group::isValidProperty(int propertyId) {
-    return propertyId >= 0 && propertyId < static_cast<int>(Property::Count);
-}
-
 void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
         const SkRect& bounds, bool needsMirroring, bool canReuseCache) {
     // The imageView can scale the canvas in different ways, in order to
@@ -458,8 +445,6 @@
         return;
     }
 
-    mPaint.setColorFilter(colorFilter);
-
     int saveCount = outCanvas->save(SaveFlags::MatrixClip);
     outCanvas->translate(mBounds.fLeft, mBounds.fTop);
 
@@ -473,33 +458,43 @@
     // And we use this bound for the destination rect for the drawBitmap, so
     // we offset to (0, 0);
     mBounds.offsetTo(0, 0);
-    createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
 
-    outCanvas->drawVectorDrawable(this);
+    createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
+    if (!mAllowCaching) {
+        updateCachedBitmap(scaledWidth, scaledHeight);
+    } else {
+        if (!canReuseCache || mCacheDirty) {
+            updateCachedBitmap(scaledWidth, scaledHeight);
+        }
+    }
+    drawCachedBitmapWithRootAlpha(outCanvas, colorFilter, mBounds);
 
     outCanvas->restoreToCount(saveCount);
 }
 
-SkPaint* Tree::getPaint() {
+void Tree::drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
+        const SkRect& originalBounds) {
     SkPaint* paint;
-    if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) {
+    if (mRootAlpha == 1.0f && filter == NULL) {
         paint = NULL;
     } else {
         mPaint.setFilterQuality(kLow_SkFilterQuality);
         mPaint.setAlpha(mRootAlpha * 255);
+        mPaint.setColorFilter(filter);
         paint = &mPaint;
     }
-    return paint;
+    outCanvas->drawBitmap(mCachedBitmap, 0, 0, mCachedBitmap.width(), mCachedBitmap.height(),
+            originalBounds.fLeft, originalBounds.fTop, originalBounds.fRight,
+            originalBounds.fBottom, paint);
 }
 
-const SkBitmap& Tree::getBitmapUpdateIfDirty() {
+void Tree::updateCachedBitmap(int width, int height) {
     mCachedBitmap.eraseColor(SK_ColorTRANSPARENT);
     SkCanvas outCanvas(mCachedBitmap);
-    float scaleX = (float) mCachedBitmap.width() / mViewportWidth;
-    float scaleY = (float) mCachedBitmap.height() / mViewportHeight;
+    float scaleX = width / mViewportWidth;
+    float scaleY = height / mViewportHeight;
     mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY);
     mCacheDirty = false;
-    return mCachedBitmap;
 }
 
 void Tree::createCachedBitmapIfNeeded(int width, int height) {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index f8f1ea6..09bdce5 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -18,7 +18,6 @@
 #define ANDROID_HWUI_VPATH_H
 
 #include "Canvas.h"
-
 #include <SkBitmap.h>
 #include <SkColor.h>
 #include <SkCanvas.h>
@@ -105,21 +104,6 @@
 
 class ANDROID_API FullPath: public Path {
 public:
-
-struct Properties {
-    float strokeWidth = 0;
-    SkColor strokeColor = SK_ColorTRANSPARENT;
-    float strokeAlpha = 1;
-    SkColor fillColor = SK_ColorTRANSPARENT;
-    float fillAlpha = 1;
-    float trimPathStart = 0;
-    float trimPathEnd = 1;
-    float trimPathOffset = 0;
-    int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
-    int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
-    float strokeMiterLimit = 4;
-};
-
     FullPath(const FullPath& path); // for cloning
     FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
     FullPath() : Path() {}
@@ -134,58 +118,55 @@
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
             float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
-    // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
     float getStrokeWidth() {
-        return mProperties.strokeWidth;
+        return mStrokeWidth;
     }
     void setStrokeWidth(float strokeWidth) {
-        mProperties.strokeWidth = strokeWidth;
+        mStrokeWidth = strokeWidth;
     }
     SkColor getStrokeColor() {
-        return mProperties.strokeColor;
+        return mStrokeColor;
     }
     void setStrokeColor(SkColor strokeColor) {
-        mProperties.strokeColor = strokeColor;
+        mStrokeColor = strokeColor;
     }
     float getStrokeAlpha() {
-        return mProperties.strokeAlpha;
+        return mStrokeAlpha;
     }
     void setStrokeAlpha(float strokeAlpha) {
-        mProperties.strokeAlpha = strokeAlpha;
+        mStrokeAlpha = strokeAlpha;
     }
     SkColor getFillColor() {
-        return mProperties.fillColor;
+        return mFillColor;
     }
     void setFillColor(SkColor fillColor) {
-        mProperties.fillColor = fillColor;
+        mFillColor = fillColor;
     }
     float getFillAlpha() {
-        return mProperties.fillAlpha;
+        return mFillAlpha;
     }
     void setFillAlpha(float fillAlpha) {
-        mProperties.fillAlpha = fillAlpha;
+        mFillAlpha = fillAlpha;
     }
     float getTrimPathStart() {
-        return mProperties.trimPathStart;
+        return mTrimPathStart;
     }
     void setTrimPathStart(float trimPathStart) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
+        VD_SET_PROP_WITH_FLAG(mTrimPathStart, trimPathStart, mTrimDirty);
     }
     float getTrimPathEnd() {
-        return mProperties.trimPathEnd;
+        return mTrimPathEnd;
     }
     void setTrimPathEnd(float trimPathEnd) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
+        VD_SET_PROP_WITH_FLAG(mTrimPathEnd, trimPathEnd, mTrimDirty);
     }
     float getTrimPathOffset() {
-        return mProperties.trimPathOffset;
+        return mTrimPathOffset;
     }
     void setTrimPathOffset(float trimPathOffset) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty);
+        VD_SET_PROP_WITH_FLAG(mTrimPathOffset, trimPathOffset, mTrimDirty);
     }
     bool getProperties(int8_t* outProperties, int length);
-    void setColorPropertyValue(int propertyId, int32_t value);
-    void setPropertyValue(int propertyId, float value);
 
     void setFillGradient(SkShader* fillGradient) {
         SkRefCnt_SafeAssign(mFillGradient, fillGradient);
@@ -201,28 +182,24 @@
             float strokeScale, const SkMatrix& matrix) override;
 
 private:
-    enum class Property {
-        StrokeWidth = 0,
-        StrokeColor,
-        StrokeAlpha,
-        FillColor,
-        FillAlpha,
-        TrimPathStart,
-        TrimPathEnd,
-        TrimPathOffset,
-        StrokeLineCap,
-        StrokeLineJoin,
-        StrokeMiterLimit,
-        Count,
-    };
     // Applies trimming to the specified path.
     void applyTrim();
-    Properties mProperties;
-    bool mTrimDirty = true;
-    SkPath mTrimmedSkPath;
-    SkPaint mPaint;
+    float mStrokeWidth = 0;
+    SkColor mStrokeColor = SK_ColorTRANSPARENT;
+    float mStrokeAlpha = 1;
+    SkColor mFillColor = SK_ColorTRANSPARENT;
     SkShader* mStrokeGradient = nullptr;
     SkShader* mFillGradient = nullptr;
+    float mFillAlpha = 1;
+    float mTrimPathStart = 0;
+    float mTrimPathEnd = 1;
+    float mTrimPathOffset = 0;
+    bool mTrimDirty = true;
+    SkPaint::Cap mStrokeLineCap = SkPaint::Cap::kButt_Cap;
+    SkPaint::Join mStrokeLineJoin = SkPaint::Join::kMiter_Join;
+    float mStrokeMiterLimit = 4;
+    SkPath mTrimmedSkPath;
+    SkPaint mPaint;
 };
 
 class ANDROID_API ClipPath: public Path {
@@ -239,58 +216,49 @@
 
 class ANDROID_API Group: public Node {
 public:
-    struct Properties {
-        float rotate = 0;
-        float pivotX = 0;
-        float pivotY = 0;
-        float scaleX = 1;
-        float scaleY = 1;
-        float translateX = 0;
-        float translateY = 0;
-    };
     Group(const Group& group);
     Group() {}
     float getRotation() {
-        return mProperties.rotate;
+        return mRotate;
     }
     void setRotation(float rotation) {
-        mProperties.rotate = rotation;
+        mRotate = rotation;
     }
     float getPivotX() {
-        return mProperties.pivotX;
+        return mPivotX;
     }
     void setPivotX(float pivotX) {
-        mProperties.pivotX = pivotX;
+        mPivotX = pivotX;
     }
     float getPivotY() {
-        return mProperties.pivotY;
+        return mPivotY;
     }
     void setPivotY(float pivotY) {
-        mProperties.pivotY = pivotY;
+        mPivotY = pivotY;
     }
     float getScaleX() {
-        return mProperties.scaleX;
+        return mScaleX;
     }
     void setScaleX(float scaleX) {
-        mProperties.scaleX = scaleX;
+        mScaleX = scaleX;
     }
     float getScaleY() {
-        return mProperties.scaleY;
+        return mScaleY;
     }
     void setScaleY(float scaleY) {
-        mProperties.scaleY = scaleY;
+        mScaleY = scaleY;
     }
     float getTranslateX() {
-        return mProperties.translateX;
+        return mTranslateX;
     }
     void setTranslateX(float translateX) {
-        mProperties.translateX = translateX;
+        mTranslateX = translateX;
     }
     float getTranslateY() {
-        return mProperties.translateY;
+        return mTranslateY;
     }
     void setTranslateY(float translateY) {
-        mProperties.translateY = translateY;
+        mTranslateY = translateY;
     }
     virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
             float scaleX, float scaleY) override;
@@ -300,33 +268,38 @@
     void addChild(Node* child);
     void dump() override;
     bool getProperties(float* outProperties, int length);
-    float getPropertyValue(int propertyId) const;
-    void setPropertyValue(int propertyId, float value);
-    static bool isValidProperty(int propertyId);
 
 private:
     enum class Property {
-        Rotate = 0,
-        PivotX,
-        PivotY,
-        ScaleX,
-        ScaleY,
-        TranslateX,
-        TranslateY,
+        Rotate_Property = 0,
+        PivotX_Property,
+        PivotY_Property,
+        ScaleX_Property,
+        ScaleY_Property,
+        TranslateX_Property,
+        TranslateY_Property,
         // Count of the properties, must be at the end.
         Count,
     };
+    float mRotate = 0;
+    float mPivotX = 0;
+    float mPivotY = 0;
+    float mScaleX = 1;
+    float mScaleY = 1;
+    float mTranslateX = 0;
+    float mTranslateY = 0;
     std::vector<Node*> mChildren;
-    Properties mProperties;
 };
 
-class ANDROID_API Tree : public VirtualLightRefBase {
+class ANDROID_API Tree {
 public:
     Tree(Group* rootNode) : mRootNode(rootNode) {}
     void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
             const SkRect& bounds, bool needsMirroring, bool canReuseCache);
+    void drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
+            const SkRect& originalBounds);
 
-    const SkBitmap& getBitmapUpdateIfDirty();
+    void updateCachedBitmap(int width, int height);
     void createCachedBitmapIfNeeded(int width, int height);
     bool canReuseBitmap(int width, int height);
     void setAllowCaching(bool allowCaching) {
@@ -343,10 +316,6 @@
         mViewportWidth = viewportWidth;
         mViewportHeight = viewportHeight;
     }
-    SkPaint* getPaint();
-    const SkRect& getBounds() const {
-        return mBounds;
-    }
 
 private:
     // Cap the bitmap size, such that it won't hurt the performance too much
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index d411621..ea702c0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -92,18 +92,18 @@
     }
 }
 
-void CanvasContext::setSurface(ANativeWindow* window) {
+void CanvasContext::setSurface(Surface* surface) {
     ATRACE_CALL();
 
-    mNativeWindow = window;
+    mNativeSurface = surface;
 
     if (mEglSurface != EGL_NO_SURFACE) {
         mEglManager.destroySurface(mEglSurface);
         mEglSurface = EGL_NO_SURFACE;
     }
 
-    if (window) {
-        mEglSurface = mEglManager.createSurface(window);
+    if (surface) {
+        mEglSurface = mEglManager.createSurface(surface);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
@@ -127,8 +127,8 @@
     mSwapBehavior = swapBehavior;
 }
 
-void CanvasContext::initialize(ANativeWindow* window) {
-    setSurface(window);
+void CanvasContext::initialize(Surface* surface) {
+    setSurface(surface);
 #if !HWUI_NEW_OPS
     if (mCanvas) return;
     mCanvas = new OpenGLRenderer(mRenderThread.renderState());
@@ -136,11 +136,11 @@
 #endif
 }
 
-void CanvasContext::updateSurface(ANativeWindow* window) {
-    setSurface(window);
+void CanvasContext::updateSurface(Surface* surface) {
+    setSurface(surface);
 }
 
-bool CanvasContext::pauseSurface(ANativeWindow* window) {
+bool CanvasContext::pauseSurface(Surface* surface) {
     return mRenderThread.removeFrameCallback(this);
 }
 
@@ -204,6 +204,10 @@
     info.renderer = mCanvas;
 #endif
 
+    if (CC_LIKELY(mNativeSurface.get())) {
+        info.frameNumber = static_cast<int64_t>(mNativeSurface->getNextFrameNumber());
+    }
+
     mAnimationContext->startFrame(info.mode);
     for (const sp<RenderNode>& node : mRenderNodes) {
         // Only the primary target node will be drawn full - all other nodes would get drawn in
@@ -219,7 +223,7 @@
     freePrefetechedLayers();
     GL_CHECKPOINT(MODERATE);
 
-    if (CC_UNLIKELY(!mNativeWindow.get())) {
+    if (CC_UNLIKELY(!mNativeSurface.get())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
         return;
@@ -242,8 +246,9 @@
         } else {
             // We're maybe behind? Find out for sure
             int runningBehind = 0;
-            mNativeWindow->query(mNativeWindow.get(),
-                    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
+            // TODO: Have this method be on Surface, too, not just ANativeWindow...
+            ANativeWindow* window = mNativeSurface.get();
+            window->query(window, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
             info.out.canDrawThisFrame = !runningBehind;
         }
     } else {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 63a7977..168166e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -39,6 +39,7 @@
 #include <SkBitmap.h>
 #include <SkRect.h>
 #include <utils/Functor.h>
+#include <gui/Surface.h>
 
 #include <set>
 #include <string>
@@ -75,10 +76,10 @@
     // Won't take effect until next EGLSurface creation
     void setSwapBehavior(SwapBehavior swapBehavior);
 
-    void initialize(ANativeWindow* window);
-    void updateSurface(ANativeWindow* window);
-    bool pauseSurface(ANativeWindow* window);
-    bool hasSurface() { return mNativeWindow.get(); }
+    void initialize(Surface* surface);
+    void updateSurface(Surface* surface);
+    bool pauseSurface(Surface* surface);
+    bool hasSurface() { return mNativeSurface.get(); }
 
     void setup(int width, int height, float lightRadius,
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -172,7 +173,7 @@
     // lifecycle tracking
     friend class android::uirenderer::RenderState;
 
-    void setSurface(ANativeWindow* window);
+    void setSurface(Surface* window);
     void requireSurface();
 
     void freePrefetechedLayers();
@@ -182,7 +183,7 @@
 
     RenderThread& mRenderThread;
     EglManager& mEglManager;
-    sp<ANativeWindow> mNativeWindow;
+    sp<Surface> mNativeSurface;
     EGLSurface mEglSurface = EGL_NO_SURFACE;
     bool mBufferPreserved = false;
     SwapBehavior mSwapBehavior = kSwap_default;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 1d1b144..7c6cd7e 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -139,38 +139,38 @@
     postAndWait(task); // block since name/value pointers owned by caller
 }
 
-CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
-    args->context->initialize(args->window);
+CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
+    args->context->initialize(args->surface);
     return nullptr;
 }
 
-void RenderProxy::initialize(const sp<ANativeWindow>& window) {
+void RenderProxy::initialize(const sp<Surface>& surface) {
     SETUP_TASK(initialize);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     post(task);
 }
 
-CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
-    args->context->updateSurface(args->window);
+CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
+    args->context->updateSurface(args->surface);
     return nullptr;
 }
 
-void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
+void RenderProxy::updateSurface(const sp<Surface>& surface) {
     SETUP_TASK(updateSurface);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
-    return (void*) args->context->pauseSurface(args->window);
+CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
+    return (void*) args->context->pauseSurface(args->surface);
 }
 
-bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
+bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
     SETUP_TASK(pauseSurface);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     return (bool) postAndWait(task);
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 4180d802..178724a 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -67,9 +67,9 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void initialize(const sp<ANativeWindow>& window);
-    ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
-    ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
+    ANDROID_API void initialize(const sp<Surface>& surface);
+    ANDROID_API void updateSurface(const sp<Surface>& surface);
+    ANDROID_API bool pauseSurface(const sp<Surface>& surface);
     ANDROID_API void setup(int width, int height, float lightRadius,
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     ANDROID_API void setLightCenter(const Vector3& lightCenter);
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 01bfc5a..20d2f1f 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -455,6 +455,23 @@
     }
 }
 
+TEST(RecordingCanvas, firstClipWillReplace) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+        canvas.save(SaveFlags::MatrixClip);
+        // since no explicit clip set on canvas, this should be the one observed on op:
+        canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op);
+
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+
+        canvas.restore();
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
+    // first clip must be preserved, even if it extends beyond canvas bounds
+    EXPECT_CLIP_RECT(Rect(-100, -100, 300, 300), dl->getOps()[0]->localClip);
+}
+
 TEST(RecordingCanvas, insertReorderBarrier) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         canvas.drawRect(0, 0, 400, 400, SkPaint());
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 78c530c..f885110 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -155,7 +155,7 @@
             for (UserInfo userInfo : um.getProfiles(userId)) {
                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
                 if (admins == null) {
-                    return null;
+                    continue;
                 }
                 final boolean isSeparateProfileChallengeEnabled =
                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
@@ -209,16 +209,7 @@
         IPackageManager ipm = AppGlobals.getPackageManager();
         try {
             if (ipm.getBlockUninstallForUser(packageName, userId)) {
-                DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
-                        Context.DEVICE_POLICY_SERVICE);
-                if (dpm == null) {
-                    return null;
-                }
-                ComponentName admin = dpm.getProfileOwner();
-                if (admin == null) {
-                    admin = dpm.getDeviceOwnerComponentOnCallingUser();
-                }
-                return new EnforcedAdmin(admin, UserHandle.myUserId());
+                return getProfileOrDeviceOwner(context, userId);
             }
         } catch (RemoteException e) {
             // Nothing to do
@@ -238,7 +229,7 @@
         try {
             ApplicationInfo ai = ipm.getApplicationInfo(packageName, 0, userId);
             if (ai != null && ((ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0)) {
-                return getProfileOrDeviceOwnerOnCallingUser(context);
+                return getProfileOrDeviceOwner(context, userId);
             }
         } catch (RemoteException e) {
             // Nothing to do
@@ -246,6 +237,80 @@
         return null;
     }
 
+    public static EnforcedAdmin checkIfInputMethodDisallowed(Context context,
+            String packageName, int userId) {
+        DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm == null) {
+            return null;
+        }
+        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+        int managedProfileId = getManagedProfileId(context, userId);
+        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
+        boolean permittedByProfileAdmin = true;
+        if (profileAdmin != null) {
+            permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component,
+                    packageName, managedProfileId);
+        }
+        if (!permitted && !permittedByProfileAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByProfileAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
+            String packageName, int userId) {
+        DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm == null) {
+            return null;
+        }
+        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+        int managedProfileId = getManagedProfileId(context, userId);
+        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
+        boolean permittedByProfileAdmin = true;
+        if (profileAdmin != null) {
+            permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
+                    profileAdmin.component, packageName, managedProfileId);
+        }
+        if (!permitted && !permittedByProfileAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByProfileAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    private static int getManagedProfileId(Context context, int userId) {
+        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        List<UserInfo> userProfiles = um.getProfiles(userId);
+        for (UserInfo uInfo : userProfiles) {
+            if (uInfo.id == userId) {
+                continue;
+            }
+            if (uInfo.isManagedProfile()) {
+                return uInfo.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     /**
      * Check if account management for a specific type of account is disabled by admin.
      * Only a profile or device owner can disable account management. So, we check if account
@@ -255,7 +320,7 @@
      * or {@code null} if the account management is not disabled.
      */
     public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
-            String accountType) {
+            String accountType, int userId) {
         if (accountType == null) {
             return null;
         }
@@ -265,7 +330,7 @@
             return null;
         }
         boolean isAccountTypeDisabled = false;
-        String[] disabledTypes = dpm.getAccountTypesWithManagementDisabled();
+        String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
         for (String type : disabledTypes) {
             if (accountType.equals(type)) {
                 isAccountTypeDisabled = true;
@@ -275,7 +340,7 @@
         if (!isAccountTypeDisabled) {
             return null;
         }
-        return getProfileOrDeviceOwnerOnCallingUser(context);
+        return getProfileOrDeviceOwner(context, userId);
     }
 
     /**
@@ -296,7 +361,7 @@
     }
 
     /**
-     * Checks if an admin has enforced minimum password quality requirements on the device.
+     * Checks if an admin has enforced minimum password quality requirements on the given user.
      *
      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
      * or {@code null} if no quality requirements are set. If the requirements are set by
@@ -304,35 +369,73 @@
      * {@link UserHandle#USER_NULL}.
      *
      */
-    public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context) {
+    public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
             return null;
         }
-        boolean isDisabledByMultipleAdmins = false;
-        ComponentName adminComponent = null;
-        List<ComponentName> admins = dpm.getActiveAdmins();
-        int quality;
-        if (admins != null) {
+
+        LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+        EnforcedAdmin enforcedAdmin = null;
+        if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+            // userId is managed profile and has a separate challenge, only consider
+            // the admins in that user.
+            final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
+            if (admins == null) {
+                return null;
+            }
             for (ComponentName admin : admins) {
-                quality = dpm.getPasswordQuality(admin);
-                if (quality >= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
-                    if (adminComponent == null) {
-                        adminComponent = admin;
+                if (dpm.getPasswordQuality(admin, userId)
+                        > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                    if (enforcedAdmin == null) {
+                        enforcedAdmin = new EnforcedAdmin(admin, userId);
                     } else {
-                        isDisabledByMultipleAdmins = true;
-                        break;
+                        return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                     }
                 }
             }
-        }
-        EnforcedAdmin enforcedAdmin = null;
-        if (adminComponent != null) {
-            if (!isDisabledByMultipleAdmins) {
-                enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId());
-            } else {
-                enforcedAdmin = new EnforcedAdmin();
+        } else {
+            // Return all admins for this user and the profiles that are visible from this
+            // user that do not use a separate work challenge.
+            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+            for (UserInfo userInfo : um.getProfiles(userId)) {
+                final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
+                if (admins == null) {
+                    continue;
+                }
+                final boolean isSeparateProfileChallengeEnabled =
+                        lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+                for (ComponentName admin : admins) {
+                    if (!isSeparateProfileChallengeEnabled) {
+                        if (dpm.getPasswordQuality(admin, userInfo.id)
+                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                            if (enforcedAdmin == null) {
+                                enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+                            } else {
+                                return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+                            }
+                            // This same admins could have set policies both on the managed profile
+                            // and on the parent. So, if the admin has set the policy on the
+                            // managed profile here, we don't need to further check if that admin
+                            // has set policy on the parent admin.
+                            continue;
+                        }
+                    }
+                    if (userInfo.isManagedProfile()) {
+                        // If userInfo.id is a managed profile, we also need to look at
+                        // the policies set on the parent.
+                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+                        if (parentDpm.getPasswordQuality(admin, userInfo.id)
+                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                            if (enforcedAdmin == null) {
+                                enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+                            } else {
+                                return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+                            }
+                        }
+                    }
+                }
             }
         }
         return enforcedAdmin;
@@ -352,7 +455,8 @@
         EnforcedAdmin enforcedAdmin = null;
         final int userId = UserHandle.myUserId();
         if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
-            // If the user has a separate challenge, only consider the admins in that user.
+            // userId is managed profile and has a separate challenge, only consider
+            // the admins in that user.
             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
             if (admins == null) {
                 return null;
@@ -373,7 +477,7 @@
             for (UserInfo userInfo : um.getProfiles(userId)) {
                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
                 if (admins == null) {
-                    return null;
+                    continue;
                 }
                 final boolean isSeparateProfileChallengeEnabled =
                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
@@ -410,19 +514,24 @@
         return enforcedAdmin;
     }
 
-    public static EnforcedAdmin getProfileOrDeviceOwnerOnCallingUser(Context context) {
+    public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
+        if (userId == UserHandle.USER_NULL) {
+            return null;
+        }
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
             return null;
         }
-        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
+        ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+            return new EnforcedAdmin(adminComponent, userId);
         }
-        adminComponent = dpm.getProfileOwner();
-        if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+        if (dpm.getDeviceOwnerUserId() == userId) {
+            adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
+            if (adminComponent != null) {
+                return new EnforcedAdmin(adminComponent, userId);
+            }
         }
         return null;
     }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9bd79c9..423ef84 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1649,6 +1649,7 @@
             // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
             if (mState != STATE_ACTIVE) {
                 becomeActiveLocked("alarm", Process.myUid());
+                becomeInactiveIfAppropriateLocked();
             }
             return;
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 4f0d4d9..bef6f0a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -62,7 +62,7 @@
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
+    static final boolean DEBUG_PAUSE = DEBUG_ALL || true;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
@@ -77,7 +77,7 @@
     static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
     static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
     static final boolean DEBUG_STACK = DEBUG_ALL || false;
-    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
+    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || true;
     static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
     static final boolean DEBUG_TASKS = DEBUG_ALL || false;
     static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
@@ -85,7 +85,7 @@
     static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
     static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
     static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
-    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false;
+    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || true;
     static final boolean DEBUG_VISIBLE_BEHIND = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
     static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54c4ced..1506524 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5303,28 +5303,42 @@
 
     @Override
     public void killAllBackgroundProcesses() {
+        killAllBackgroundProcesses(-1);
+    }
+
+    /**
+     * Kills all background processes with targetSdkVersion below the specified
+     * target SDK version.
+     *
+     * @param targetSdkVersion the target SDK version below which to kill
+     *                         processes, or {@code -1} to kill all processes
+     */
+    private void killAllBackgroundProcesses(int targetSdkVersion) {
         if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
                 != PackageManager.PERMISSION_GRANTED) {
-            String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
+            final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                     + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
 
-        long callingId = Binder.clearCallingIdentity();
+        final long callingId = Binder.clearCallingIdentity();
         try {
-            synchronized(this) {
-                ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+            synchronized (this) {
+                final ArrayList<ProcessRecord> procs = new ArrayList<>();
                 final int NP = mProcessNames.getMap().size();
-                for (int ip=0; ip<NP; ip++) {
-                    SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+                for (int ip = 0; ip < NP; ip++) {
+                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
                     final int NA = apps.size();
-                    for (int ia=0; ia<NA; ia++) {
-                        ProcessRecord app = apps.valueAt(ia);
+                    for (int ia = 0; ia < NA; ia++) {
+                        final ProcessRecord app = apps.valueAt(ia);
                         if (app.persistent) {
-                            // we don't kill persistent processes
+                            // We don't kill persistent processes.
+                            continue;
+                        }
+                        if (targetSdkVersion > 0
+                                && app.info.targetSdkVersion >= targetSdkVersion) {
                             continue;
                         }
                         if (app.removed) {
@@ -5336,11 +5350,13 @@
                     }
                 }
 
-                int N = procs.size();
-                for (int i=0; i<N; i++) {
+                final int N = procs.size();
+                for (int i = 0; i < N; i++) {
                     removeProcessLocked(procs.get(i), false, true, "kill all background");
                 }
+
                 mAllowLowerMemLevel = true;
+
                 updateOomAdjLocked();
                 doLowMemReportIfNeededLocked(null);
             }
@@ -17805,6 +17821,11 @@
                     mHandler.sendMessage(msg);
                 }
 
+                final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+                if (isDensityChange) {
+                    killAllBackgroundProcesses(Build.VERSION_CODES.N);
+                }
+
                 for (int i=mLruProcesses.size()-1; i>=0; i--) {
                     ProcessRecord app = mLruProcesses.get(i);
                     try {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 908d2f0..f296d68 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4132,7 +4132,7 @@
     public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias,
             final IBinder response) {
         // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers.
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             return;
         }
 
@@ -5860,8 +5860,7 @@
         }
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
-        if (hasUserSetupCompleted(userHandle)
-                && !UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
+        if (hasUserSetupCompleted(userHandle) && !isCallerWithSystemUid()) {
             throw new IllegalStateException("Cannot set the profile owner on a user which is "
                     + "already set-up");
         }
@@ -5921,8 +5920,7 @@
 
     private void enforceManageUsers() {
         final int callingUid = mInjector.binderGetCallingUid();
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
-                || callingUid == Process.ROOT_UID)) {
+        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         }
     }
@@ -5945,8 +5943,7 @@
         if (userHandle == UserHandle.getUserId(callingUid)) {
             return;
         }
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
-                || callingUid == Process.ROOT_UID)) {
+        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(permission,
                     "Must be system or have " + permission + " permission");
         }
@@ -5964,6 +5961,10 @@
         }
     }
 
+    private boolean isCallerWithSystemUid() {
+        return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID);
+    }
+
     private int getProfileParentId(int userHandle) {
         final long ident = mInjector.binderClearCallingIdentity();
         try {
@@ -6248,7 +6249,7 @@
     @Override
     public ComponentName getRestrictionsProvider(int userHandle) {
         synchronized (this) {
-            if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+            if (!isCallerWithSystemUid()) {
                 throw new SecurityException("Only the system can query the permission provider");
             }
             DevicePolicyData userData = getUserData(userHandle);
@@ -6321,8 +6322,7 @@
      * permittedList or are a system app.
      */
     private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
-            List<String> permittedList) {
-        int userIdToCheck = UserHandle.getCallingUserId();
+            List<String> permittedList, int userIdToCheck) {
         long id = mInjector.binderClearCallingIdentity();
         try {
             // If we have an enabled packages list for a managed profile the packages
@@ -6389,7 +6389,8 @@
                 for (AccessibilityServiceInfo service : enabledServices) {
                     enabledPackages.add(service.getResolveInfo().serviceInfo.packageName);
                 }
-                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList,
+                        userId)) {
                     Slog.e(LOG_TAG, "Cannot set permitted accessibility services, "
                             + "because it contains already enabled accesibility services.");
                     return false;
@@ -6481,6 +6482,28 @@
         }
     }
 
+    @Override
+    public boolean isAccessibilityServicePermittedByAdmin(ComponentName who, String packageName,
+            int userHandle) {
+        if (!mHasFeature) {
+            return true;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        Preconditions.checkStringNotEmpty(packageName, "packageName is null");
+        if (!isCallerWithSystemUid()){
+            throw new SecurityException(
+                    "Only the system can query if an accessibility service is disabled by admin");
+        }
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+            if (admin.permittedAccessiblityServices == null) {
+                return true;
+            }
+            return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName),
+                    admin.permittedAccessiblityServices, userHandle);
+        }
+    }
+
     private boolean checkCallerIsCurrentUserOrProfile() {
         int callingUserId = UserHandle.getCallingUserId();
         long token = mInjector.binderClearCallingIdentity();
@@ -6536,7 +6559,8 @@
                 for (InputMethodInfo ime : enabledImes) {
                     enabledPackages.add(ime.getPackageName());
                 }
-                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList,
+                        mInjector.binderGetCallingUserHandle().getIdentifier())) {
                     Slog.e(LOG_TAG, "Cannot set permitted input methods, "
                             + "because it contains already enabled input method.");
                     return false;
@@ -6629,6 +6653,28 @@
     }
 
     @Override
+    public boolean isInputMethodPermittedByAdmin(ComponentName who, String packageName,
+            int userHandle) {
+        if (!mHasFeature) {
+            return true;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        Preconditions.checkStringNotEmpty(packageName, "packageName is null");
+        if (!isCallerWithSystemUid()) {
+            throw new SecurityException(
+                    "Only the system can query if an input method is disabled by admin");
+        }
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+            if (admin.permittedInputMethods == null) {
+                return true;
+            }
+            return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName),
+                    admin.permittedInputMethods, userHandle);
+        }
+    }
+
+    @Override
     public UserHandle createUser(ComponentName who, String name) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         synchronized (this) {
@@ -7425,7 +7471,7 @@
 
     @Override
     public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
         }
         synchronized (this) {
@@ -8180,7 +8226,7 @@
             return null;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("Only the system can query support message for user");
         }
         synchronized (this) {
@@ -8198,7 +8244,7 @@
             return null;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("Only the system can query support message for user");
         }
         synchronized (this) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index d1d6e0d..6229ed9 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -25,6 +25,7 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Typeface;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
@@ -338,7 +339,7 @@
     public static String givePrintableIccid(String iccId) {
         String iccIdToPrint = null;
         if (iccId != null) {
-            if (iccId.length() > 9) {
+            if (iccId.length() > 9 && !Build.IS_DEBUGGABLE) {
                 iccIdToPrint = iccId.substring(0, 9) + "XXXXXXXXXXX";
             } else {
                 iccIdToPrint = iccId;
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index b028ce6..de7b9c2 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -356,6 +356,15 @@
         </activity>
 
         <activity
+                android:name="MovingSurfaceViewActivity"
+                android:label="SurfaceView/Animated Movement">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.hwui.TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="GLTextureViewActivity"
                 android:label="TextureView/OpenGL">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
new file mode 100644
index 0000000..cd15ef1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.animation.LinearInterpolator;
+import android.widget.FrameLayout;
+
+public class MovingSurfaceViewActivity extends Activity implements Callback {
+    static final String TAG = "MovingSurfaceView";
+    SurfaceView mSurfaceView;
+    ObjectAnimator mAnimator;
+
+    class MySurfaceView extends SurfaceView {
+        boolean mSlowToggled;
+
+        public MySurfaceView(Context context) {
+            super(context);
+            setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mSlowToggled = !mSlowToggled;
+                    Log.d(TAG, "SLOW MODE: " + mSlowToggled);
+                    invalidate();
+                }
+            });
+            setWillNotDraw(false);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            if (mSlowToggled) {
+                try {
+                    Thread.sleep(16);
+                } catch (InterruptedException e) {}
+            }
+        }
+
+        public void setMyTranslationY(float ty) {
+            setTranslationY(ty);
+            if (mSlowToggled) {
+                invalidate();
+            }
+        }
+
+        public float getMyTranslationY() {
+            return getTranslationY();
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FrameLayout content = new FrameLayout(this);
+
+        mSurfaceView = new MySurfaceView(this);
+        mSurfaceView.getHolder().addCallback(this);
+
+        final float density = getResources().getDisplayMetrics().density;
+        int size = (int) (200 * density);
+
+        content.addView(mSurfaceView, new FrameLayout.LayoutParams(
+                size, size, Gravity.CENTER));
+        mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
+                0, size);
+        mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+        mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+        mAnimator.setDuration(200);
+        mAnimator.setInterpolator(new LinearInterpolator());
+        setContentView(content);
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        Canvas canvas = holder.lockCanvas();
+        canvas.drawARGB(0xFF, 0x00, 0xFF, 0x00);
+        holder.unlockCanvasAndPost(canvas);
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mAnimator.start();
+    }
+
+    @Override
+    protected void onPause() {
+        mAnimator.pause();
+        super.onPause();
+    }
+}