Merge "Unset is -1 not Nan"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 802880d..74f0c0e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -92,7 +92,7 @@
 import android.util.SparseIntArray;
 import android.util.SuperNotCalledException;
 import android.view.Display;
-import android.view.HardwareRenderer;
+import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewManager;
@@ -4612,7 +4612,7 @@
             // If there are several packages in this application we won't
             // initialize the graphics disk caches
             if (packages != null && packages.length == 1) {
-                HardwareRenderer.setupDiskCache(cacheDir);
+                ThreadedRenderer.setupDiskCache(cacheDir);
                 RenderScriptCacheDir.setupDiskCache(cacheDir);
             }
         } catch (RemoteException e) {
@@ -4659,7 +4659,7 @@
             // use hardware accelerated drawing, since this can add too much
             // overhead to the process.
             if (!ActivityManager.isHighEndGfx()) {
-                HardwareRenderer.disable(false);
+                ThreadedRenderer.disable(false);
             }
         }
 
@@ -5529,9 +5529,9 @@
         // accelerated drawing, since this can add too much overhead to the
         // process.
         if (!ActivityManager.isHighEndGfx()) {
-            HardwareRenderer.disable(true);
+            ThreadedRenderer.disable(true);
         } else {
-            HardwareRenderer.enableForegroundTrimming();
+            ThreadedRenderer.enableForegroundTrimming();
         }
         ActivityThread thread = new ActivityThread();
         thread.attach(true);
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 692ca7b..a12434c 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -33,10 +33,10 @@
  * @hide
  */
 final class HardwareLayer {
-    private HardwareRenderer mRenderer;
+    private ThreadedRenderer mRenderer;
     private VirtualRefBasePtr mFinalizer;
 
-    private HardwareLayer(HardwareRenderer renderer, long deferredUpdater) {
+    private HardwareLayer(ThreadedRenderer renderer, long deferredUpdater) {
         if (renderer == null || deferredUpdater == 0) {
             throw new IllegalArgumentException("Either hardware renderer: " + renderer
                     + " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -140,7 +140,7 @@
         mRenderer.pushLayerUpdate(this);
     }
 
-    static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
+    static HardwareLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
         return new HardwareLayer(renderer, layer);
     }
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
deleted file mode 100644
index 5e58250..0000000
--- a/core/java/android/view/HardwareRenderer.java
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (C) 2013 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.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.view.Surface.OutOfResourcesException;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Interface for rendering a view hierarchy using hardware acceleration.
- *
- * @hide
- */
-public abstract class HardwareRenderer {
-    static final String LOG_TAG = "HardwareRenderer";
-
-    /**
-     * Name of the file that holds the shaders cache.
-     */
-    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
-
-    /**
-     * System property used to enable or disable dirty regions invalidation.
-     * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
-     * The default value of this property is assumed to be true.
-     *
-     * Possible values:
-     * "true", to enable partial invalidates
-     * "false", to disable partial invalidates
-     */
-    static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
-
-    /**
-     * System property used to enable or disable hardware rendering profiling.
-     * The default value of this property is assumed to be false.
-     *
-     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
-     * output extra information about the time taken to execute by the last
-     * frames.
-     *
-     * Possible values:
-     * "true", to enable profiling
-     * "visual_bars", to enable profiling and visualize the results on screen
-     * "false", to disable profiling
-     *
-     * @see #PROFILE_PROPERTY_VISUALIZE_BARS
-     *
-     * @hide
-     */
-    public static final String PROFILE_PROPERTY = "debug.hwui.profile";
-
-    /**
-     * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
-     * value, profiling data will be visualized on screen as a bar chart.
-     *
-     * @hide
-     */
-    public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
-
-    /**
-     * System property used to specify the number of frames to be used
-     * when doing hardware rendering profiling.
-     * The default value of this property is #PROFILE_MAX_FRAMES.
-     *
-     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
-     * output extra information about the time taken to execute by the last
-     * frames.
-     *
-     * Possible values:
-     * "60", to set the limit of frames to 60
-     */
-    static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
-
-    /**
-     * System property used to debug EGL configuration choice.
-     *
-     * Possible values:
-     * "choice", print the chosen configuration only
-     * "all", print all possible configurations
-     */
-    static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
-
-    /**
-     * Turn on to draw dirty regions every other frame.
-     *
-     * Possible values:
-     * "true", to enable dirty regions debugging
-     * "false", to disable dirty regions debugging
-     *
-     * @hide
-     */
-    public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
-
-    /**
-     * Turn on to flash hardware layers when they update.
-     *
-     * Possible values:
-     * "true", to enable hardware layers updates debugging
-     * "false", to disable hardware layers updates debugging
-     *
-     * @hide
-     */
-    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
-            "debug.hwui.show_layers_updates";
-
-    /**
-     * Controls overdraw debugging.
-     *
-     * Possible values:
-     * "false", to disable overdraw debugging
-     * "show", to show overdraw areas on screen
-     * "count", to display an overdraw counter
-     *
-     * @hide
-     */
-    public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
-
-    /**
-     * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
-     * value, overdraw will be shown on screen by coloring pixels.
-     *
-     * @hide
-     */
-    public static final String OVERDRAW_PROPERTY_SHOW = "show";
-
-    /**
-     * Turn on to debug non-rectangular clip operations.
-     *
-     * Possible values:
-     * "hide", to disable this debug mode
-     * "highlight", highlight drawing commands tested against a non-rectangular clip
-     * "stencil", renders the clip region on screen when set
-     *
-     * @hide
-     */
-    public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
-            "debug.hwui.show_non_rect_clip";
-
-    /**
-     * A process can set this flag to false to prevent the use of hardware
-     * rendering.
-     *
-     * @hide
-     */
-    public static boolean sRendererDisabled = false;
-
-    /**
-     * Further hardware renderer disabling for the system process.
-     *
-     * @hide
-     */
-    public static boolean sSystemRendererDisabled = false;
-
-    private boolean mEnabled;
-    private boolean mRequested = true;
-
-    /**
-     * Invoke this method to disable hardware rendering in the current process.
-     *
-     * @hide
-     */
-    public static void disable(boolean system) {
-        sRendererDisabled = true;
-        if (system) {
-            sSystemRendererDisabled = true;
-        }
-    }
-
-    public static boolean sTrimForeground = false;
-
-    /**
-     * Controls whether or not the hardware renderer should aggressively
-     * trim memory. Note that this must not be set for any process that
-     * uses WebView! This should be only used by system_process or similar
-     * that do not go into the background.
-     */
-    public static void enableForegroundTrimming() {
-        sTrimForeground = true;
-    }
-
-    /**
-     * Indicates whether hardware acceleration is available under any form for
-     * the view hierarchy.
-     *
-     * @return True if the view hierarchy can potentially be hardware accelerated,
-     *         false otherwise
-     */
-    public static boolean isAvailable() {
-        return DisplayListCanvas.isAvailable();
-    }
-
-    /**
-     * Destroys the hardware rendering context.
-     */
-    abstract void destroy();
-
-    /**
-     * Initializes the hardware renderer for the specified surface.
-     *
-     * @param surface The surface to hardware accelerate
-     *
-     * @return True if the initialization was successful, false otherwise.
-     */
-    abstract boolean initialize(Surface surface) throws OutOfResourcesException;
-
-    /**
-     * Updates the hardware renderer for the specified surface.
-     *
-     * @param surface The surface to hardware accelerate
-     */
-    abstract void updateSurface(Surface surface) throws OutOfResourcesException;
-
-    /**
-     * Stops any rendering into the surface. Use this if it is unclear whether
-     * or not the surface used by the HardwareRenderer will be changing. It
-     * Suspends any rendering into the surface, but will not do any destruction
-     */
-    abstract boolean pauseSurface(Surface surface);
-
-    /**
-     * Destroys all hardware rendering resources associated with the specified
-     * view hierarchy.
-     *
-     * @param view The root of the view hierarchy
-     */
-    abstract void destroyHardwareResources(View view);
-
-    /**
-     * This method should be invoked whenever the current hardware renderer
-     * context should be reset.
-     *
-     * @param surface The surface to hardware accelerate
-     */
-    abstract void invalidate(Surface surface);
-
-    /**
-     * Detaches the layer's surface texture from the GL context and releases
-     * the texture id
-     */
-    abstract void detachSurfaceTexture(long hardwareLayer);
-
-    /**
-     * Gets the current width of the surface. This is the width that the surface
-     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
-     *
-     * @return the current width of the surface
-     */
-    abstract int getWidth();
-
-    /**
-     * Gets the current height of the surface. This is the height that the surface
-     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
-     *
-     * @return the current width of the surface
-     */
-    abstract int getHeight();
-
-    /**
-     * Outputs extra debugging information in the specified file descriptor.
-     */
-    abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args);
-
-    /**
-     * Loads system properties used by the renderer. This method is invoked
-     * whenever system properties are modified. Implementations can use this
-     * to trigger live updates of the renderer based on properties.
-     *
-     * @return True if a property has changed.
-     */
-    abstract boolean loadSystemProperties();
-
-    /**
-     * Sets the directory to use as a persistent storage for hardware rendering
-     * resources.
-     *
-     * @param cacheDir A directory the current process can write to
-     *
-     * @hide
-     */
-    public static void setupDiskCache(File cacheDir) {
-        ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
-    }
-
-    /**
-     * Indicates that the specified hardware layer needs to be updated
-     * as soon as possible.
-     *
-     * @param layer The hardware layer that needs an update
-     */
-    abstract void pushLayerUpdate(HardwareLayer layer);
-
-    /**
-     * Tells the HardwareRenderer that the layer is destroyed. The renderer
-     * should remove the layer from any update queues.
-     */
-    abstract void onLayerDestroyed(HardwareLayer layer);
-
-    /**
-     * Interface used to receive callbacks whenever a view is drawn by
-     * a hardware renderer instance.
-     */
-    interface HardwareDrawCallbacks {
-        /**
-         * Invoked before a view is drawn by a hardware renderer.
-         * This method can be used to apply transformations to the
-         * canvas but no drawing command should be issued.
-         *
-         * @param canvas The Canvas used to render the view.
-         */
-        void onHardwarePreDraw(DisplayListCanvas canvas);
-
-        /**
-         * Invoked after a view is drawn by a hardware renderer.
-         * It is safe to invoke drawing commands from this method.
-         *
-         * @param canvas The Canvas used to render the view.
-         */
-        void onHardwarePostDraw(DisplayListCanvas canvas);
-    }
-
-    /**
-     *  Indicates that the content drawn by HardwareDrawCallbacks needs to
-     *  be updated, which will be done by the next call to draw()
-     */
-    abstract void invalidateRoot();
-
-    /**
-     * Draws the specified view.
-     *
-     * @param view The view to draw.
-     * @param attachInfo AttachInfo tied to the specified view.
-     * @param callbacks Callbacks invoked when drawing happens.
-     */
-    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
-
-    /**
-     * Creates a new hardware layer. A hardware layer built by calling this
-     * method will be treated as a texture layer, instead of as a render target.
-     *
-     * @return A hardware layer
-     */
-    abstract HardwareLayer createTextureLayer();
-
-    abstract void buildLayer(RenderNode node);
-
-    abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
-
-    /**
-     * Initializes the hardware renderer for the specified surface and setup the
-     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
-     * potentially lost the hardware renderer. The hardware renderer should be
-     * reinitialized and setup when the render {@link #isRequested()} and
-     * {@link #isEnabled()}.
-     *
-     * @param width The width of the drawing surface.
-     * @param height The height of the drawing surface.
-     * @param attachInfo Information about the window.
-     * @param surface The surface to hardware accelerate
-     * @param surfaceInsets The drawing surface insets to apply
-     *
-     * @return true if the surface was initialized, false otherwise. Returning
-     *         false might mean that the surface was already initialized.
-     */
-    boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
-            Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
-        if (isRequested()) {
-            // We lost the gl context, so recreate it.
-            if (!isEnabled()) {
-                if (initialize(surface)) {
-                    setup(width, height, attachInfo, surfaceInsets);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Sets up the renderer for drawing.
-     *
-     * @param width The width of the drawing surface.
-     * @param height The height of the drawing surface.
-     * @param attachInfo Information about the window.
-     * @param surfaceInsets The drawing surface insets to apply
-     */
-    abstract void setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets);
-
-    /**
-     * Updates the light position based on the position of the window.
-     *
-     * @param attachInfo Information about the window.
-     */
-    abstract void setLightCenter(View.AttachInfo attachInfo);
-
-    /**
-     * Optional, sets the name of the renderer. Useful for debugging purposes.
-     *
-     * @param name The name of this renderer, can be null
-     */
-    abstract void setName(String name);
-
-    /**
-     * Change the HardwareRenderer's opacity
-     */
-    abstract void setOpaque(boolean opaque);
-
-    /**
-     * Creates a hardware renderer using OpenGL.
-     *
-     * @param translucent True if the surface is translucent, false otherwise
-     *
-     * @return A hardware renderer backed by OpenGL.
-     */
-    static HardwareRenderer create(Context context, boolean translucent) {
-        HardwareRenderer renderer = null;
-        if (DisplayListCanvas.isAvailable()) {
-            renderer = new ThreadedRenderer(context, translucent);
-        }
-        return renderer;
-    }
-
-    /**
-     * Invoke this method when the system is running out of memory. This
-     * method will attempt to recover as much memory as possible, based on
-     * the specified hint.
-     *
-     * @param level Hint about the amount of memory that should be trimmed,
-     *              see {@link android.content.ComponentCallbacks}
-     */
-    static void trimMemory(int level) {
-        ThreadedRenderer.trimMemory(level);
-    }
-
-    /**
-     * Indicates whether hardware acceleration is currently enabled.
-     *
-     * @return True if hardware acceleration is in use, false otherwise.
-     */
-    boolean isEnabled() {
-        return mEnabled;
-    }
-
-    /**
-     * Indicates whether hardware acceleration is currently enabled.
-     *
-     * @param enabled True if the hardware renderer is in use, false otherwise.
-     */
-    void setEnabled(boolean enabled) {
-        mEnabled = enabled;
-    }
-
-    /**
-     * Indicates whether hardware acceleration is currently request but not
-     * necessarily enabled yet.
-     *
-     * @return True if requested, false otherwise.
-     */
-    boolean isRequested() {
-        return mRequested;
-    }
-
-    /**
-     * Indicates whether hardware acceleration is currently requested but not
-     * necessarily enabled yet.
-     *
-     * @return True to request hardware acceleration, false otherwise.
-     */
-    void setRequested(boolean requested) {
-        mRequested = requested;
-    }
-
-    /**
-     * Blocks until all previously queued work has completed.
-     */
-    abstract void fence();
-
-    /**
-     * Prevents any further drawing until draw() is called. This is a signal
-     * that the contents of the RenderNode tree are no longer safe to play back.
-     * In practice this usually means that there are Functor pointers in the
-     * display list that are no longer valid.
-     */
-    abstract void stopDrawing();
-
-    /**
-     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
-     */
-    abstract void notifyFramePending();
-
-    abstract void registerAnimatingRenderNode(RenderNode animator);
-}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 304e9c0..f2a4d7b 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -35,6 +35,7 @@
 
 import com.android.internal.R;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -59,8 +60,230 @@
  *
  * @hide
  */
-public class ThreadedRenderer extends HardwareRenderer {
-    private static final String LOGTAG = "ThreadedRenderer";
+public final class ThreadedRenderer {
+    private static final String LOG_TAG = "ThreadedRenderer";
+
+    /**
+     * Name of the file that holds the shaders cache.
+     */
+    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+
+    /**
+     * System property used to enable or disable dirty regions invalidation.
+     * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
+     * The default value of this property is assumed to be true.
+     *
+     * Possible values:
+     * "true", to enable partial invalidates
+     * "false", to disable partial invalidates
+     */
+    static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
+
+    /**
+     * System property used to enable or disable hardware rendering profiling.
+     * The default value of this property is assumed to be false.
+     *
+     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
+     * output extra information about the time taken to execute by the last
+     * frames.
+     *
+     * Possible values:
+     * "true", to enable profiling
+     * "visual_bars", to enable profiling and visualize the results on screen
+     * "false", to disable profiling
+     *
+     * @see #PROFILE_PROPERTY_VISUALIZE_BARS
+     *
+     * @hide
+     */
+    public static final String PROFILE_PROPERTY = "debug.hwui.profile";
+
+    /**
+     * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
+     * value, profiling data will be visualized on screen as a bar chart.
+     *
+     * @hide
+     */
+    public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
+
+    /**
+     * System property used to specify the number of frames to be used
+     * when doing hardware rendering profiling.
+     * The default value of this property is #PROFILE_MAX_FRAMES.
+     *
+     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
+     * output extra information about the time taken to execute by the last
+     * frames.
+     *
+     * Possible values:
+     * "60", to set the limit of frames to 60
+     */
+    static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
+
+    /**
+     * System property used to debug EGL configuration choice.
+     *
+     * Possible values:
+     * "choice", print the chosen configuration only
+     * "all", print all possible configurations
+     */
+    static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
+
+    /**
+     * Turn on to draw dirty regions every other frame.
+     *
+     * Possible values:
+     * "true", to enable dirty regions debugging
+     * "false", to disable dirty regions debugging
+     *
+     * @hide
+     */
+    public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
+
+    /**
+     * Turn on to flash hardware layers when they update.
+     *
+     * Possible values:
+     * "true", to enable hardware layers updates debugging
+     * "false", to disable hardware layers updates debugging
+     *
+     * @hide
+     */
+    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
+            "debug.hwui.show_layers_updates";
+
+    /**
+     * Controls overdraw debugging.
+     *
+     * Possible values:
+     * "false", to disable overdraw debugging
+     * "show", to show overdraw areas on screen
+     * "count", to display an overdraw counter
+     *
+     * @hide
+     */
+    public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
+
+    /**
+     * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
+     * value, overdraw will be shown on screen by coloring pixels.
+     *
+     * @hide
+     */
+    public static final String OVERDRAW_PROPERTY_SHOW = "show";
+
+    /**
+     * Turn on to debug non-rectangular clip operations.
+     *
+     * Possible values:
+     * "hide", to disable this debug mode
+     * "highlight", highlight drawing commands tested against a non-rectangular clip
+     * "stencil", renders the clip region on screen when set
+     *
+     * @hide
+     */
+    public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
+            "debug.hwui.show_non_rect_clip";
+
+    /**
+     * A process can set this flag to false to prevent the use of hardware
+     * rendering.
+     *
+     * @hide
+     */
+    public static boolean sRendererDisabled = false;
+
+    /**
+     * Further hardware renderer disabling for the system process.
+     *
+     * @hide
+     */
+    public static boolean sSystemRendererDisabled = false;
+
+    /**
+     * Invoke this method to disable hardware rendering in the current process.
+     *
+     * @hide
+     */
+    public static void disable(boolean system) {
+        sRendererDisabled = true;
+        if (system) {
+            sSystemRendererDisabled = true;
+        }
+    }
+
+    public static boolean sTrimForeground = false;
+
+    /**
+     * Controls whether or not the hardware renderer should aggressively
+     * trim memory. Note that this must not be set for any process that
+     * uses WebView! This should be only used by system_process or similar
+     * that do not go into the background.
+     */
+    public static void enableForegroundTrimming() {
+        sTrimForeground = true;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is available under any form for
+     * the view hierarchy.
+     *
+     * @return True if the view hierarchy can potentially be hardware accelerated,
+     *         false otherwise
+     */
+    public static boolean isAvailable() {
+        return DisplayListCanvas.isAvailable();
+    }
+
+    /**
+     * Sets the directory to use as a persistent storage for hardware rendering
+     * resources.
+     *
+     * @param cacheDir A directory the current process can write to
+     *
+     * @hide
+     */
+    public static void setupDiskCache(File cacheDir) {
+        ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
+    }
+
+    /**
+     * Creates a hardware renderer using OpenGL.
+     *
+     * @param translucent True if the surface is translucent, false otherwise
+     *
+     * @return A hardware renderer backed by OpenGL.
+     */
+    public static ThreadedRenderer create(Context context, boolean translucent) {
+        ThreadedRenderer renderer = null;
+        if (DisplayListCanvas.isAvailable()) {
+            renderer = new ThreadedRenderer(context, translucent);
+        }
+        return renderer;
+    }
+
+    /**
+     * Invoke this method when the system is running out of memory. This
+     * method will attempt to recover as much memory as possible, based on
+     * the specified hint.
+     *
+     * @param level Hint about the amount of memory that should be trimmed,
+     *              see {@link android.content.ComponentCallbacks}
+     */
+    public static void trimMemory(int level) {
+        nTrimMemory(level);
+    }
+
+    public static void overrideProperty(@NonNull String name, @NonNull String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException("name and value must be non-null");
+        }
+        nOverrideProperty(name, value);
+    }
+
+    public static void dumpProfileData(byte[] data, FileDescriptor fd) {
+        nDumpProfileData(data, fd);
+    }
 
     // Keep in sync with DrawFrameTask.h SYNC_* flags
     // Nothing interesting to report
@@ -113,6 +336,9 @@
     private final Rect mCurrentContentBounds = new Rect();
     private final Rect mStagedContentBounds = new Rect();
 
+    private boolean mEnabled;
+    private boolean mRequested = true;
+
     ThreadedRenderer(Context context, boolean translucent) {
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
@@ -133,13 +359,53 @@
         loadSystemProperties();
     }
 
-    @Override
+    /**
+     * Destroys the hardware rendering context.
+     */
     void destroy() {
         mInitialized = false;
         updateEnabledState(null);
         nDestroy(mNativeProxy);
     }
 
+    /**
+     * Indicates whether hardware acceleration is currently enabled.
+     *
+     * @return True if hardware acceleration is in use, false otherwise.
+     */
+    boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently enabled.
+     *
+     * @param enabled True if the hardware renderer is in use, false otherwise.
+     */
+    void setEnabled(boolean enabled) {
+        mEnabled = enabled;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently request but not
+     * necessarily enabled yet.
+     *
+     * @return True if requested, false otherwise.
+     */
+    boolean isRequested() {
+        return mRequested;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently requested but not
+     * necessarily enabled yet.
+     *
+     * @return True to request hardware acceleration, false otherwise.
+     */
+    void setRequested(boolean requested) {
+        mRequested = requested;
+    }
+
     private void updateEnabledState(Surface surface) {
         if (surface == null || !surface.isValid()) {
             setEnabled(false);
@@ -148,7 +414,13 @@
         }
     }
 
-    @Override
+    /**
+     * Initializes the hardware renderer for the specified surface.
+     *
+     * @param surface The surface to hardware accelerate
+     *
+     * @return True if the initialization was successful, false otherwise.
+     */
     boolean initialize(Surface surface) throws OutOfResourcesException {
         mInitialized = true;
         updateEnabledState(surface);
@@ -156,18 +428,61 @@
         return status;
     }
 
-    @Override
+    /**
+     * Initializes the hardware renderer for the specified surface and setup the
+     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
+     * potentially lost the hardware renderer. The hardware renderer should be
+     * reinitialized and setup when the render {@link #isRequested()} and
+     * {@link #isEnabled()}.
+     *
+     * @param width The width of the drawing surface.
+     * @param height The height of the drawing surface.
+     * @param attachInfo Information about the window.
+     * @param surface The surface to hardware accelerate
+     * @param surfaceInsets The drawing surface insets to apply
+     *
+     * @return true if the surface was initialized, false otherwise. Returning
+     *         false might mean that the surface was already initialized.
+     */
+    boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
+            Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
+        if (isRequested()) {
+            // We lost the gl context, so recreate it.
+            if (!isEnabled()) {
+                if (initialize(surface)) {
+                    setup(width, height, attachInfo, surfaceInsets);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Updates the hardware renderer for the specified surface.
+     *
+     * @param surface The surface to hardware accelerate
+     */
     void updateSurface(Surface surface) throws OutOfResourcesException {
         updateEnabledState(surface);
         nUpdateSurface(mNativeProxy, surface);
     }
 
-    @Override
+    /**
+     * Stops any rendering into the surface. Use this if it is unclear whether
+     * or not the surface used by the HardwareRenderer will be changing. It
+     * Suspends any rendering into the surface, but will not do any destruction
+     */
     boolean pauseSurface(Surface surface) {
         return nPauseSurface(mNativeProxy, surface);
     }
 
-    @Override
+    /**
+     * Destroys all hardware rendering resources associated with the specified
+     * view hierarchy.
+     *
+     * @param view The root of the view hierarchy
+     */
     void destroyHardwareResources(View view) {
         destroyResources(view);
         nDestroyHardwareResources(mNativeProxy);
@@ -186,17 +501,32 @@
         }
     }
 
-    @Override
+    /**
+     * This method should be invoked whenever the current hardware renderer
+     * context should be reset.
+     *
+     * @param surface The surface to hardware accelerate
+     */
     void invalidate(Surface surface) {
         updateSurface(surface);
     }
 
-    @Override
+    /**
+     * Detaches the layer's surface texture from the GL context and releases
+     * the texture id
+     */
     void detachSurfaceTexture(long hardwareLayer) {
         nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
     }
 
-    @Override
+    /**
+     * Sets up the renderer for drawing.
+     *
+     * @param width The width of the drawing surface.
+     * @param height The height of the drawing surface.
+     * @param attachInfo Information about the window.
+     * @param surfaceInsets The drawing surface insets to apply
+     */
     void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
         mWidth = width;
         mHeight = height;
@@ -226,7 +556,11 @@
         setLightCenter(attachInfo);
     }
 
-    @Override
+    /**
+     * Updates the light position based on the position of the window.
+     *
+     * @param attachInfo Information about the window.
+     */
     void setLightCenter(AttachInfo attachInfo) {
         // Adjust light position for window offsets.
         final Point displaySize = attachInfo.mPoint;
@@ -237,22 +571,36 @@
         nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
     }
 
-    @Override
+    /**
+     * Change the HardwareRenderer's opacity
+     */
     void setOpaque(boolean opaque) {
         nSetOpaque(mNativeProxy, opaque && !mHasInsets);
     }
 
-    @Override
+    /**
+     * Gets the current width of the surface. This is the width that the surface
+     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
+     *
+     * @return the current width of the surface
+     */
     int getWidth() {
         return mWidth;
     }
 
-    @Override
+    /**
+     * Gets the current height of the surface. This is the height that the surface
+     * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
+     *
+     * @return the current width of the surface
+     */
     int getHeight() {
         return mHeight;
     }
 
-    @Override
+    /**
+     * Outputs extra debugging information in the specified file descriptor.
+     */
     void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
         pw.flush();
         int flags = 0;
@@ -269,7 +617,13 @@
         nDumpProfileInfo(mNativeProxy, fd, flags);
     }
 
-    @Override
+    /**
+     * Loads system properties used by the renderer. This method is invoked
+     * whenever system properties are modified. Implementations can use this
+     * to trigger live updates of the renderer based on properties.
+     *
+     * @return True if a property has changed.
+     */
     boolean loadSystemProperties() {
         boolean changed = nLoadSystemProperties(mNativeProxy);
         if (changed) {
@@ -353,12 +707,44 @@
         mStagedContentBounds.set(left, top, right, bottom);
     }
 
-    @Override
+    /**
+     * Interface used to receive callbacks whenever a view is drawn by
+     * a hardware renderer instance.
+     */
+    interface HardwareDrawCallbacks {
+        /**
+         * Invoked before a view is drawn by a hardware renderer.
+         * This method can be used to apply transformations to the
+         * canvas but no drawing command should be issued.
+         *
+         * @param canvas The Canvas used to render the view.
+         */
+        void onHardwarePreDraw(DisplayListCanvas canvas);
+
+        /**
+         * Invoked after a view is drawn by a hardware renderer.
+         * It is safe to invoke drawing commands from this method.
+         *
+         * @param canvas The Canvas used to render the view.
+         */
+        void onHardwarePostDraw(DisplayListCanvas canvas);
+    }
+
+    /**
+     *  Indicates that the content drawn by HardwareDrawCallbacks needs to
+     *  be updated, which will be done by the next call to draw()
+     */
     void invalidateRoot() {
         mRootNodeNeedsUpdate = true;
     }
 
-    @Override
+    /**
+     * Draws the specified view.
+     *
+     * @param view The view to draw.
+     * @param attachInfo AttachInfo tied to the specified view.
+     * @param callbacks Callbacks invoked when drawing happens.
+     */
     void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
         attachInfo.mIgnoreDirtyState = true;
 
@@ -409,54 +795,80 @@
         nInvokeFunctor(functor, waitForCompletion);
     }
 
-    @Override
+    /**
+     * Creates a new hardware layer. A hardware layer built by calling this
+     * method will be treated as a texture layer, instead of as a render target.
+     *
+     * @return A hardware layer
+     */
     HardwareLayer createTextureLayer() {
         long layer = nCreateTextureLayer(mNativeProxy);
         return HardwareLayer.adoptTextureLayer(this, layer);
     }
 
-    @Override
+
     void buildLayer(RenderNode node) {
         nBuildLayer(mNativeProxy, node.getNativeDisplayList());
     }
 
-    @Override
+
     boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
         return nCopyLayerInto(mNativeProxy,
                 layer.getDeferredLayerUpdater(), bitmap);
     }
 
-    @Override
+    /**
+     * Indicates that the specified hardware layer needs to be updated
+     * as soon as possible.
+     *
+     * @param layer The hardware layer that needs an update
+     */
     void pushLayerUpdate(HardwareLayer layer) {
         nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
     }
 
-    @Override
+    /**
+     * Tells the HardwareRenderer that the layer is destroyed. The renderer
+     * should remove the layer from any update queues.
+     */
     void onLayerDestroyed(HardwareLayer layer) {
         nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
     }
 
-    @Override
+    /**
+     * Optional, sets the name of the renderer. Useful for debugging purposes.
+     *
+     * @param name The name of this renderer, can be null
+     */
     void setName(String name) {
         nSetName(mNativeProxy, name);
     }
 
-    @Override
+    /**
+     * Blocks until all previously queued work has completed.
+     */
     void fence() {
         nFence(mNativeProxy);
     }
 
-    @Override
+    /**
+     * Prevents any further drawing until draw() is called. This is a signal
+     * that the contents of the RenderNode tree are no longer safe to play back.
+     * In practice this usually means that there are Functor pointers in the
+     * display list that are no longer valid.
+     */
     void stopDrawing() {
         nStopDrawing(mNativeProxy);
     }
 
-    @Override
+    /**
+     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
+     */
     public void notifyFramePending() {
         nNotifyFramePending(mNativeProxy);
     }
 
-    @Override
+
     void registerAnimatingRenderNode(RenderNode animator) {
         nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
     }
@@ -475,21 +887,6 @@
         }
     }
 
-    static void trimMemory(int level) {
-        nTrimMemory(level);
-    }
-
-    public static void overrideProperty(@NonNull String name, @NonNull String value) {
-        if (name == null || value == null) {
-            throw new IllegalArgumentException("name and value must be non-null");
-        }
-        nOverrideProperty(name, value);
-    }
-
-    public static void dumpProfileData(byte[] data, FileDescriptor fd) {
-        nDumpProfileData(data, fd);
-    }
-
     private static class ProcessInitializer {
         static ProcessInitializer sInstance = new ProcessInitializer();
         private static IBinder sProcToken;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index da66f97..1b8ef9e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13270,7 +13270,7 @@
     /**
      * @hide
      */
-    public HardwareRenderer getHardwareRenderer() {
+    public ThreadedRenderer getHardwareRenderer() {
         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
     }
 
@@ -17436,7 +17436,7 @@
         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
-                HardwareRenderer.isAvailable()) {
+                ThreadedRenderer.isAvailable()) {
             // This is set if HW acceleration is requested, even if the current
             // process doesn't allow it.  This is just to allow app preview
             // windows to better match their app.
@@ -22054,7 +22054,7 @@
 
         boolean mHardwareAccelerated;
         boolean mHardwareAccelerationRequested;
-        HardwareRenderer mHardwareRenderer;
+        ThreadedRenderer mHardwareRenderer;
         List<RenderNode> mPendingAnimatingRenderNodes;
 
         /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3c9310d..b7bb9a3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -102,7 +102,7 @@
  */
 @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
 public final class ViewRootImpl implements ViewParent,
-        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
+        View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
     private static final String TAG = "ViewRootImpl";
     private static final boolean DBG = false;
     private static final boolean LOCAL_LOGV = false;
@@ -761,7 +761,7 @@
                 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
 
         if (hardwareAccelerated) {
-            if (!HardwareRenderer.isAvailable()) {
+            if (!ThreadedRenderer.isAvailable()) {
                 return;
             }
 
@@ -784,8 +784,8 @@
                 // shows for launching applications, so they will look more like
                 // the app being launched.
                 mAttachInfo.mHardwareAccelerationRequested = true;
-            } else if (!HardwareRenderer.sRendererDisabled
-                    || (HardwareRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
+            } else if (!ThreadedRenderer.sRendererDisabled
+                    || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
                 if (mAttachInfo.mHardwareRenderer != null) {
                     mAttachInfo.mHardwareRenderer.destroy();
                 }
@@ -794,7 +794,7 @@
                 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
                         || insets.top != 0 || insets.bottom != 0;
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
-                mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
+                mAttachInfo.mHardwareRenderer = ThreadedRenderer.create(mContext, translucent);
                 if (mAttachInfo.mHardwareRenderer != null) {
                     mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
                     mAttachInfo.mHardwareAccelerated =
@@ -1865,7 +1865,7 @@
                 }
             }
 
-            final HardwareRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
+            final ThreadedRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
             if (hardwareRenderer != null && hardwareRenderer.isEnabled()) {
                 if (hwInitialized
                         || mWidth != hardwareRenderer.getWidth()
@@ -5733,7 +5733,7 @@
     }
 
     private void destroyHardwareRenderer() {
-        HardwareRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
+        ThreadedRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
 
         if (hardwareRenderer != null) {
             if (mView != null) {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index c08e1b5..8c68e92 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -425,7 +425,7 @@
                 mDyingViews.remove(view);
             }
         }
-        if (HardwareRenderer.sTrimForeground && HardwareRenderer.isAvailable()) {
+        if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
             doTrimForeground();
         }
     }
@@ -452,7 +452,7 @@
     }
 
     public void trimMemory(int level) {
-        if (HardwareRenderer.isAvailable()) {
+        if (ThreadedRenderer.isAvailable()) {
             if (shouldDestroyEglContext(level)) {
                 // Destroy all hardware surfaces and resources associated to
                 // known windows
@@ -465,16 +465,16 @@
                 level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             }
 
-            HardwareRenderer.trimMemory(level);
+            ThreadedRenderer.trimMemory(level);
 
-            if (HardwareRenderer.sTrimForeground) {
+            if (ThreadedRenderer.sTrimForeground) {
                 doTrimForeground();
             }
         }
     }
 
     public static void trimForeground() {
-        if (HardwareRenderer.sTrimForeground && HardwareRenderer.isAvailable()) {
+        if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
             WindowManagerGlobal wm = WindowManagerGlobal.getInstance();
             wm.doTrimForeground();
         }
@@ -494,7 +494,7 @@
             }
         }
         if (!hasVisibleWindows) {
-            HardwareRenderer.trimMemory(
+            ThreadedRenderer.trimMemory(
                     ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
         }
     }
@@ -513,7 +513,7 @@
                     String name = getWindowName(root);
                     pw.printf("\n\t%s (visibility=%d)", name, root.getHostVisibility());
 
-                    HardwareRenderer renderer =
+                    ThreadedRenderer renderer =
                             root.getView().mAttachInfo.mHardwareRenderer;
                     if (renderer != null) {
                         renderer.dumpGfxInfo(pw, fd, args);
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 63e310e..32cc6d6 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -315,9 +315,25 @@
                     (new TextCoordinates(mIndex)).calculateCoordinates(mTextView);
             final Rect bounds = new Rect();
             view.getBoundsOnScreen(bounds);
-            final float diffX = bounds.centerX() - currentCoordinates[0];
+            final Rect visibleDisplayBounds = new Rect();
+            mTextView.getWindowVisibleDisplayFrame(visibleDisplayBounds);
+            visibleDisplayBounds.right -= 1;
+            visibleDisplayBounds.bottom -= 1;
+            if (!visibleDisplayBounds.intersect(bounds)) {
+                throw new PerformException.Builder()
+                        .withActionDescription(mActionDescription
+                                + " The handle is entirely out of the visible display frame of"
+                                + "the TextView's window.")
+                        .withViewDescription(HumanReadables.describe(view))
+                        .build();
+            }
+            final float dragPointX = Math.max(Math.min(bounds.centerX(),
+                    visibleDisplayBounds.right), visibleDisplayBounds.left);
+            final float diffX = dragPointX - currentCoordinates[0];
             final float verticalOffset = bounds.height() * 0.7f;
-            float diffY = bounds.top + verticalOffset - currentCoordinates[1];
+            final float dragPointY = Math.max(Math.min(bounds.top + verticalOffset,
+                    visibleDisplayBounds.bottom), visibleDisplayBounds.top);
+            float diffY = dragPointY - currentCoordinates[1];
             if (currentLine > targetLine) {
                 diffY -= mTextView.getLineHeight() * LINE_SLOP_MULTIPLIER;
             } else if (currentLine < targetLine) {
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index bd11d0a..e7cc464 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1383,7 +1383,10 @@
     friend class TestUtils;
 public:
     DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
-            : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr)
+            : DrawBoundedOp(0, 0,
+                    renderNode->stagingProperties().getWidth(),
+                    renderNode->stagingProperties().getHeight(),
+                    nullptr)
             , renderNode(renderNode)
             , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
             , localMatrix(transformFromParent)
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index b416615..b7dd3b7 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -16,6 +16,7 @@
 #include "FrameInfoVisualizer.h"
 
 #include "OpenGLRenderer.h"
+#include "utils/Color.h"
 
 #include <cutils/compiler.h>
 #include <array>
@@ -27,19 +28,19 @@
 #define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
 #define PROFILE_DRAW_DP_PER_MS 7
 
+namespace android {
+namespace uirenderer {
+
 // Must be NUM_ELEMENTS in size
-static const SkColor THRESHOLD_COLOR = 0xff5faa4d;
-static const SkColor BAR_FAST_ALPHA = 0x8F000000;
-static const SkColor BAR_JANKY_ALPHA = 0xDF000000;
+static const SkColor THRESHOLD_COLOR = Color::Green_500;
+static const SkColor BAR_FAST_MASK = 0x8FFFFFFF;
+static const SkColor BAR_JANKY_MASK = 0xDFFFFFFF;
 
 // We could get this from TimeLord and use the actual frame interval, but
 // this is good enough
 #define FRAME_THRESHOLD 16
 #define FRAME_THRESHOLD_NS 16000000
 
-namespace android {
-namespace uirenderer {
-
 struct BarSegment {
     FrameInfoIndex start;
     FrameInfoIndex end;
@@ -47,13 +48,13 @@
 };
 
 static const std::array<BarSegment,7> Bar {{
-    { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, 0x00796B },
-    { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, 0x388E3C },
-    { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x689F38},
-    { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, 0x2196F3},
-    { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, 0x4FC3F7},
-    { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, 0xF44336},
-    { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, 0xFF9800},
+    { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, Color::Teal_700 },
+    { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, Color::Green_700 },
+    { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, Color::LightGreen_700 },
+    { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, Color::Blue_500 },
+    { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, Color::LightBlue_300 },
+    { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, Color::Red_500},
+    { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, Color::Orange_500},
 }};
 
 static int dpToPx(int dp, float density) {
@@ -197,9 +198,9 @@
     SkPaint paint;
     for (size_t i = 0; i < Bar.size(); i++) {
         nextBarSegment(Bar[i].start, Bar[i].end);
-        paint.setColor(Bar[i].color | BAR_FAST_ALPHA);
+        paint.setColor(Bar[i].color & BAR_FAST_MASK);
         canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
-        paint.setColor(Bar[i].color | BAR_JANKY_ALPHA);
+        paint.setColor(Bar[i].color & BAR_JANKY_MASK);
         canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
     }
 }
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 61fa384..69c686e 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -435,8 +435,9 @@
             refPaint(paint), refBitmap(*bitmap)));
 }
 void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
+    auto&& stagingProps = renderNode->stagingProperties();
     RenderNodeOp* op = new (alloc()) RenderNodeOp(
-            Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
+            Rect(stagingProps.getWidth(), stagingProps.getHeight()),
             *(mState.currentSnapshot()->transform),
             mState.getRenderTargetClipBounds(),
             renderNode);
diff --git a/libs/hwui/tests/scenes/ListViewAnimation.cpp b/libs/hwui/tests/scenes/ListViewAnimation.cpp
new file mode 100644
index 0000000..27adb12
--- /dev/null
+++ b/libs/hwui/tests/scenes/ListViewAnimation.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2015 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 "TestSceneBase.h"
+#include "utils/Color.h"
+
+#include <cstdio>
+
+class ListViewAnimation;
+
+static Benchmark _ListView(BenchmarkInfo{
+    "listview",
+    "A mock ListView of scrolling content. Doesn't re-bind/re-record views as they are recycled, so"
+    "won't upload much content (either glyphs, or bitmaps).",
+    simpleCreateScene<ListViewAnimation>
+});
+
+class ListViewAnimation : public TestScene {
+public:
+    int cardHeight;
+    int cardSpacing;
+    int cardWidth;
+    int cardLeft;
+    sp<RenderNode> listView;
+    std::vector< sp<RenderNode> > cards;
+    void createContent(int width, int height, TestCanvas& canvas) override {
+        srand(0);
+        cardHeight = dp(60);
+        cardSpacing = dp(16);
+        cardWidth = std::min((height - cardSpacing * 2), (int)dp(300));
+        cardLeft = (width - cardWidth) / 2;
+
+        for (int y = 0; y < height + (cardHeight + cardSpacing - 1); y += (cardHeight + cardSpacing)) {
+            cards.push_back(createCard(cards.size(), y));
+        }
+        listView = TestUtils::createNode(0, 0, width, height,
+                [this](RenderProperties& props, TestCanvas& canvas) {
+            for (size_t ci = 0; ci < cards.size(); ci++) {
+                canvas.drawRenderNode(cards[ci].get());
+            }
+        });
+
+        canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode);
+        canvas.drawRenderNode(listView.get());
+    }
+
+    void doFrame(int frameNr) override {
+        int scrollPx = dp(frameNr) * 3;
+        int cardIndexOffset = scrollPx / (cardSpacing + cardHeight);
+        int pxOffset = -(scrollPx % (cardSpacing + cardHeight));
+
+        TestCanvas canvas(cardWidth, cardHeight);
+        for (size_t ci = 0; ci < cards.size(); ci++) {
+            // update card position
+            auto card = cards[(ci + cardIndexOffset) % cards.size()];
+            int top = ((int)ci) * (cardSpacing + cardHeight) + pxOffset;
+            card->mutateStagingProperties().setLeftTopRightBottom(
+                    cardLeft, top, cardLeft + cardWidth, top + cardHeight);
+            card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+            // draw it to parent DisplayList
+            canvas.drawRenderNode(cards[ci].get());
+        }
+        listView->setStagingDisplayList(canvas.finishRecording());
+    }
+private:
+    SkBitmap createRandomCharIcon() {
+        int size = cardHeight - (dp(10) * 2);
+        SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
+        SkCanvas canvas(bitmap);
+        canvas.clear(0);
+
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        SkColor randomColor = BrightColors[rand() % BrightColorsCount];
+        paint.setColor(randomColor);
+        canvas.drawCircle(size / 2, size / 2, size / 2, paint);
+
+        bool bgDark = SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor)
+                < 128 * 3;
+        paint.setColor(bgDark ? Color::White : Color::Grey_700);
+        paint.setTextAlign(SkPaint::kCenter_Align);
+        paint.setTextSize(size / 2);
+        char charToShow = 'A' + (rand() % 26);
+        canvas.drawText(&charToShow, 1, size / 2, /*approximate centering*/ size * 0.7, paint);
+        return bitmap;
+    }
+
+    static SkBitmap createBoxBitmap(bool filled) {
+        int size = dp(20);
+        int stroke = dp(2);
+        SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
+        SkCanvas canvas(bitmap);
+        canvas.clear(Color::Transparent);
+
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        paint.setColor(filled ? Color::Yellow_500 : Color::Grey_700);
+        paint.setStyle(filled ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
+        paint.setStrokeWidth(stroke);
+        canvas.drawRect(SkRect::MakeLTRB(stroke, stroke, size - stroke, size - stroke), paint);
+        return bitmap;
+    }
+
+    sp<RenderNode> createCard(int cardId, int top) {
+        return TestUtils::createNode(cardLeft, top, cardLeft + cardWidth, top + cardHeight,
+                [this, cardId](RenderProperties& props, TestCanvas& canvas) {
+            static SkBitmap filledBox = createBoxBitmap(true);
+            static SkBitmap strokedBox = createBoxBitmap(false);
+
+            props.mutableOutline().setRoundRect(0, 0, cardWidth, cardHeight, dp(6), 1);
+            props.mutableOutline().setShouldClip(true);
+            canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+
+            SkPaint textPaint;
+            textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+            textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
+            textPaint.setTextSize(dp(20));
+            textPaint.setAntiAlias(true);
+            char buf[256];
+            snprintf(buf, sizeof(buf), "This card is #%d", cardId);
+            TestUtils::drawTextToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
+            textPaint.setTextSize(dp(15));
+            TestUtils::drawTextToCanvas(&canvas, "This is some more text on the card", textPaint,
+                    cardHeight, dp(45));
+
+            canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);
+
+            const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox;
+            canvas.drawBitmap(boxBitmap, cardWidth - dp(10) - boxBitmap.width(), dp(10), nullptr);
+        });
+    }
+};
diff --git a/libs/hwui/tests/scenes/RecentsAnimation.cpp b/libs/hwui/tests/scenes/RecentsAnimation.cpp
index 1e38d84..5d4ef96 100644
--- a/libs/hwui/tests/scenes/RecentsAnimation.cpp
+++ b/libs/hwui/tests/scenes/RecentsAnimation.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "TestSceneBase.h"
+#include "utils/Color.h"
 
 class RecentsAnimation;
 
@@ -29,16 +30,16 @@
 public:
     void createContent(int width, int height, TestCanvas& renderer) override {
         static SkColor COLORS[] = {
-                0xFFF44336,
-                0xFF9C27B0,
-                0xFF2196F3,
-                0xFF4CAF50,
+                Color::Red_500,
+                Color::Purple_500,
+                Color::Blue_500,
+                Color::Green_500,
         };
 
         thumbnailSize = std::min(std::min(width, height) / 2, 720);
         int cardsize = std::min(width, height) - dp(64);
 
-        renderer.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        renderer.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
         renderer.insertReorderBarrier(true);
 
         int x = dp(32);
@@ -63,7 +64,7 @@
             mCards[ci]->setPropertyFieldsDirty(RenderNode::Y);
         }
         mThumbnail.eraseColor(TestUtils::interpolateColor(
-                curFrame / 150.0f, 0xFF4CAF50, 0xFFFF5722));
+                curFrame / 150.0f, Color::Green_500, Color::DeepOrange_500));
     }
 
 private:
@@ -75,7 +76,7 @@
             props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
             props.mutableOutline().setShouldClip(true);
 
-            canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(Color::Grey_200, SkXfermode::kSrcOver_Mode);
             canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(),
                     0, 0, width, height, nullptr);
         });
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
new file mode 100644
index 0000000..b5157f4
--- /dev/null
+++ b/libs/hwui/utils/Color.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+#ifndef COLOR_H
+#define COLOR_H
+
+#include <SkColor.h>
+
+namespace android {
+namespace uirenderer {
+    namespace Color {
+        enum Color {
+            Red_500 = 0xFFF44336,
+            Pink_500 = 0xFFE91E63,
+            Purple_500 = 0xFF9C27B0,
+            DeepPurple_500 = 0xFF673AB7,
+            Indigo_500 = 0xFF3F51B5,
+            Blue_500 = 0xFF2196F3,
+            LightBlue_300 = 0xFF4FC3F7,
+            LightBlue_500 = 0xFF03A9F4,
+            Cyan_500 = 0xFF00BCD4,
+            Teal_500 = 0xFF009688,
+            Teal_700 = 0xFF00796B,
+            Green_500 = 0xFF4CAF50,
+            Green_700 = 0xFF388E3C,
+            LightGreen_500 = 0xFF8BC34A,
+            LightGreen_700 = 0xFF689F38,
+            Lime_500 = 0xFFCDDC39,
+            Yellow_500 = 0xFFFFEB3B,
+            Amber_500 = 0xFFFFC107,
+            Orange_500 = 0xFFFF9800,
+            DeepOrange_500 = 0xFFFF5722,
+            Brown_500 = 0xFF795548,
+            Grey_200 = 0xFFEEEEEE,
+            Grey_500 = 0xFF9E9E9E,
+            Grey_700 = 0xFF616161,
+            BlueGrey_500 = 0xFF607D8B,
+            Transparent = 0x00000000,
+            Black = 0xFF000000,
+            White = 0xFFFFFFFF,
+        };
+    }
+
+    static_assert(Color::White == SK_ColorWHITE, "color format has changed");
+    static_assert(Color::Black == SK_ColorBLACK, "color format has changed");
+
+    // Array of bright (500 intensity) colors for synthetic content
+    static const Color::Color BrightColors[] = {
+        Color::Red_500,
+        Color::Pink_500,
+        Color::Purple_500,
+        Color::DeepPurple_500,
+        Color::Indigo_500,
+        Color::Blue_500,
+        Color::LightBlue_500,
+        Color::Cyan_500,
+        Color::Teal_500,
+        Color::Green_500,
+        Color::LightGreen_500,
+        Color::Lime_500,
+        Color::Yellow_500,
+        Color::Amber_500,
+        Color::Orange_500,
+        Color::DeepOrange_500,
+        Color::Brown_500,
+        Color::Grey_500,
+        Color::BlueGrey_500,
+    };
+    static constexpr int BrightColorsCount = sizeof(BrightColors) / sizeof(Color::Color);
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TEST_UTILS_H */
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 91ac033..abb08f5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -260,8 +260,7 @@
         } else if (id == R.id.menu_settings) {
             final RootInfo root = getCurrentRoot();
             final Intent intent = new Intent(DocumentsContract.ACTION_DOCUMENT_ROOT_SETTINGS);
-            intent.setDataAndType(DocumentsContract.buildRootUri(root.authority, root.rootId),
-                    DocumentsContract.Root.MIME_TYPE_ITEM);
+            intent.setDataAndType(root.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
             startActivity(intent);
             return true;
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index ae5644d..4caa891 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -23,8 +23,10 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.text.TextUtils;
 
@@ -195,6 +197,10 @@
         }
     }
 
+    public Uri getUri() {
+        return DocumentsContract.buildRootUri(authority, rootId);
+    }
+
     public boolean isRecents() {
         return authority == null && rootId == null;
     }
@@ -238,11 +244,6 @@
                 || derivedType == TYPE_RECENTS || derivedType == TYPE_DOWNLOADS;
     }
 
-    @Override
-    public String toString() {
-        return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
-    }
-
     public Drawable loadIcon(Context context) {
         if (derivedIcon != 0) {
             return context.getDrawable(derivedIcon);
@@ -283,6 +284,11 @@
         return Objects.hash(authority, rootId);
     }
 
+    @Override
+    public String toString() {
+        return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
+    }
+
     public String getDirectoryString() {
         return !TextUtils.isEmpty(summary) ? summary : title;
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
new file mode 100644
index 0000000..737a8b6
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 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.documentsui;
+
+import static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+
+import android.app.Instrumentation;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.DocumentsContract;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.documentsui.model.RootInfo;
+
+@LargeTest
+public class DownloadsActivityUiTest extends InstrumentationTestCase {
+
+    private static final int TIMEOUT = 5000;
+    private static final String TAG = "DownloadsActivityUiTest";
+    private static final String TARGET_PKG = "com.android.documentsui";
+    private static final String LAUNCHER_PKG = "com.android.launcher";
+
+    private UiBot mBot;
+    private UiDevice mDevice;
+    private Context mContext;
+    private ContentResolver mResolver;
+    private DocumentsProviderHelper mDocsHelper;
+    private ContentProviderClient mClient;
+    private RootInfo mRoot;
+
+    public void setUp() throws Exception {
+        // Initialize UiDevice instance.
+        Instrumentation instrumentation = getInstrumentation();
+
+        mDevice = UiDevice.getInstance(instrumentation);
+
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
+
+        // Start from the home screen.
+        mDevice.pressHome();
+        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), TIMEOUT);
+
+        // NOTE: Must be the "target" context, else security checks in content provider will fail.
+        mContext = instrumentation.getTargetContext();
+        mResolver = mContext.getContentResolver();
+
+        mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
+        mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
+
+        mRoot = mDocsHelper.getRoot(ROOT_0_ID);
+
+        // Open the Downloads activity on our stub provider root.
+        Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_ROOT);
+        intent.setDataAndType(mRoot.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        mContext.startActivity(intent);
+
+        // Wait for the app to appear.
+        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
+        mDevice.waitForIdle();
+
+        mBot = new UiBot(mDevice, TIMEOUT);
+
+        resetStorage();  // Just in case a test failed and tearDown didn't happen.
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Need to kill off the task we started.
+        super.tearDown();
+        Log.d(TAG, "Resetting storage from setUp");
+        resetStorage();
+        mClient.release();
+    }
+
+    private void resetStorage() throws RemoteException {
+        mClient.call("clear", null, null);
+        // TODO: Would be nice to have an event to wait on here.
+        mDevice.waitForIdle();
+    }
+
+    private void initTestFiles() throws RemoteException {
+        mDocsHelper.createDocument(mRoot, "text/plain", "file0.log");
+        mDocsHelper.createDocument(mRoot, "image/png", "file1.png");
+        mDocsHelper.createDocument(mRoot, "text/csv", "file2.csv");
+    }
+
+    public void testWindowTitle() throws Exception {
+        initTestFiles();
+
+        mBot.assertWindowTitle(ROOT_0_ID);
+    }
+
+    public void testFilesListed() throws Exception {
+        initTestFiles();
+
+        mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
+    }
+
+    public void testFilesList_LiveUpdate() throws Exception {
+        initTestFiles();
+
+        mDocsHelper.createDocument(mRoot, "yummers/sandwich", "Ham & Cheese.sandwich");
+        mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
+    }
+
+    public void testDeleteDocument() throws Exception {
+        initTestFiles();
+
+        mBot.clickDocument("file1.png");
+        mDevice.waitForIdle();
+        mBot.menuDelete().click();
+
+        mBot.waitForDeleteSnackbar();
+        assertFalse(mBot.hasDocuments("file1.png"));
+
+        mBot.waitForDeleteSnackbarGone();
+        assertFalse(mBot.hasDocuments("file1.png"));
+    }
+
+    public void testSupportsShare() throws Exception {
+        initTestFiles();
+
+        mBot.clickDocument("file1.png");
+        mDevice.waitForIdle();
+        assertNotNull(mBot.menuShare());
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index d23cdeb..7a75503 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -226,6 +226,12 @@
     }
 
     @Override
+    public Cursor queryChildDocumentsForManage(String parentDocumentId, String[] projection,
+            String sortOrder) throws FileNotFoundException {
+        return queryChildDocuments(parentDocumentId, projection, sortOrder);
+    }
+
+    @Override
     public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
         final StubDocument parentDocument = mStorage.get(parentDocumentId);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
index ecad061..68cdf12 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
@@ -179,6 +179,10 @@
         return find(By.res("com.android.documentsui:id/menu_delete"));
     }
 
+    UiObject2 menuShare() {
+        return find(By.res("com.android.documentsui:id/menu_share"));
+    }
+
     private UiObject2 find(BySelector selector) {
         mDevice.wait(Until.findObject(selector), mTimeout);
         return mDevice.findObject(selector);
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index f9a222f..5bcaa6e 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -81,6 +81,12 @@
     public abstract boolean isEmpty();
 
     /**
+     * Invalidate this object.  The location area code and the cell id are set to -1.
+     * @hide
+     */
+    public abstract void setStateInvalid();
+
+    /**
      * Return a new CellLocation object representing an unknown
      * location, or null for unknown/none phone radio types.
      *
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 6cfae6a..7c10569 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -123,6 +123,7 @@
     /**
      * Invalidate this object.  The cell location data is set to invalid values.
      */
+    @Override
     public void setStateInvalid() {
         this.mBaseStationId = -1;
         this.mBaseStationLatitude = INVALID_LAT_LONG;
@@ -134,7 +135,7 @@
     /**
      * Set the cell location data.
      */
-     public void setCellLocationData(int baseStationId, int baseStationLatitude,
+    public void setCellLocationData(int baseStationId, int baseStationLatitude,
          int baseStationLongitude) {
          // The following values have to be written in the correct sequence
          this.mBaseStationId = baseStationId;
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index a3889b2..1717802 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -72,6 +72,7 @@
     /**
      * Invalidate this object.  The location area code and the cell id are set to -1.
      */
+    @Override
     public void setStateInvalid() {
         mLac = -1;
         mCid = -1;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
index 7628c5c..63fa3f9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
@@ -25,7 +25,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.view.DisplayListCanvas;
-import android.view.HardwareRenderer;
+import android.view.ThreadedRenderer;
 import android.view.RenderNode;
 import android.view.ThreadedRenderer;
 import android.view.View;
@@ -120,7 +120,7 @@
             if (view == null) {
                 view.postDelayed(mSetup, 50);
             }
-            HardwareRenderer renderer = view.getHardwareRenderer();
+            ThreadedRenderer renderer = view.getHardwareRenderer();
             if (renderer == null || view.getWidth() == 0) {
                 view.postDelayed(mSetup, 50);
             }
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index fc5426c..ee4c834 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -6,7 +6,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
-import android.view.HardwareRenderer;
 import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.widget.AdapterView;