Refactors and a potential public API for rendering

Split out the View/ViewRootImpl bits from the
hardware rendering bits.

Create a potential public API surface for
hardware rendering

Bug: 112709971
Test: builds & boots

Change-Id: I9e6f44b07a170574a905f42338282c4bb7e95f56
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b6bff9c..22fc5e8 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3240,7 +3240,7 @@
 android.view.FocusFinder$FocusSorter
 android.view.FocusFinder$UserSpecifiedFocusComparator
 android.view.FocusFinder$UserSpecifiedFocusComparator$NextFocusGetter
-android.view.FrameInfo
+android.graphics.FrameInfo
 android.view.FrameMetrics
 android.view.FrameMetricsObserver
 android.view.FrameStats
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9079f1a..805fb68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -72,6 +72,7 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.HardwareRenderer;
 import android.graphics.ImageDecoder;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.ConnectivityManager;
@@ -5652,7 +5653,7 @@
                     int uid = Process.myUid();
                     String[] packages = getPackageManager().getPackagesForUid(uid);
                     if (packages != null) {
-                        ThreadedRenderer.setupDiskCache(codeCacheDir);
+                        HardwareRenderer.setupDiskCache(codeCacheDir);
                         RenderScriptCacheDir.setupDiskCache(codeCacheDir);
                     }
                 } catch (RemoteException e) {
@@ -5887,7 +5888,8 @@
 
         // Allow renderer debugging features if we're debuggable.
         boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-        ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setPackageName(data.appInfo.packageName);
 
         /**
          * Initialize the default http proxy in this process for the reasons we set the time zone.
@@ -5954,7 +5956,7 @@
                 StrictMode.setThreadPolicyMask(oldMask);
             }
         } else {
-            ThreadedRenderer.setIsolatedProcess(true);
+            HardwareRenderer.setIsolatedProcess(true);
         }
 
         // If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a872776..96ef8ba 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -21,6 +21,7 @@
 
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.FrameInfo;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Build;
 import android.os.Handler;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 597089b..0f38e84 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -40,8 +40,9 @@
     @UnsupportedAppUsage
     private FrameMetrics mFrameMetrics;
 
-    /* package */ Window.OnFrameMetricsAvailableListener mListener;
-    /* package */ VirtualRefBasePtr mNative;
+    /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
+    /** @hide */
+    public VirtualRefBasePtr mNative;
 
     /**
      * Creates a FrameMetricsObserver
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index d89d634..46dd436 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.SurfaceTexture;
@@ -32,10 +33,10 @@
  * @hide
  */
 public final class TextureLayer {
-    private ThreadedRenderer mRenderer;
+    private HardwareRenderer mRenderer;
     private VirtualRefBasePtr mFinalizer;
 
-    private TextureLayer(ThreadedRenderer renderer, long deferredUpdater) {
+    private TextureLayer(HardwareRenderer renderer, long deferredUpdater) {
         if (renderer == null || deferredUpdater == 0) {
             throw new IllegalArgumentException("Either hardware renderer: " + renderer
                     + " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -139,7 +140,8 @@
         mRenderer.pushLayerUpdate(this);
     }
 
-    static TextureLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
+    /** @hide */
+    public static TextureLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
         return new TextureLayer(renderer, layer);
     }
 
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f0f4c1c..bac0154 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,36 +16,24 @@
 
 package android.view;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Point;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RenderNode;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
 
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 
 /**
  * Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -66,15 +54,7 @@
  *
  * @hide
  */
-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";
-    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
-
+public final class ThreadedRenderer extends HardwareRenderer {
     /**
      * System property used to enable or disable threaded rendering profiling.
      * The default value of this property is assumed to be false.
@@ -271,21 +251,6 @@
     }
 
     /**
-     * Sets the directory to use as a persistent storage for threaded rendering
-     * resources.
-     *
-     * @param cacheDir A directory the current process can write to
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static void setupDiskCache(File cacheDir) {
-        ThreadedRenderer.setupShadersDiskCache(
-                new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
-                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
-    }
-
-    /**
      * Creates a threaded renderer using OpenGL.
      *
      * @param translucent True if the surface is translucent, false otherwise
@@ -300,55 +265,10 @@
         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);
-    }
-
-    // Keep in sync with DrawFrameTask.h SYNC_* flags
-    // Nothing interesting to report
-    private static final int SYNC_OK = 0;
-    // Needs a ViewRoot invalidate
-    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
-    // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
-    private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
-    // setStopped is true, drawing is false
-    // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
-    // This flag isn't really used as there's nothing that we care to do
-    // in response, so it really just exists to differentiate from LOST_SURFACE
-    // but possibly both can just be deleted.
-    private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
-    private static final int SYNC_FRAME_DROPPED = 1 << 3;
-
     private static final String[] VISUALIZERS = {
         PROFILE_PROPERTY_VISUALIZE_BARS,
     };
 
-    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
-    private static final int FLAG_DUMP_RESET        = 1 << 1;
-    private static final int FLAG_DUMP_ALL          = FLAG_DUMP_FRAMESTATS;
-
-    @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
-            FLAG_DUMP_FRAMESTATS,
-            FLAG_DUMP_RESET
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DumpFlags {}
-
     // Size of the rendered content.
     private int mWidth, mHeight;
 
@@ -362,51 +282,37 @@
     // Whether the surface has insets. Used to protect opacity.
     private boolean mHasInsets;
 
-    // Light and shadow properties specified by the theme.
+    // Light properties specified by the theme.
     private final float mLightY;
     private final float mLightZ;
     private final float mLightRadius;
-    private final int mAmbientShadowAlpha;
-    private final int mSpotShadowAlpha;
 
-    private long mNativeProxy;
     private boolean mInitialized = false;
-    private RenderNode mRootNode;
     private boolean mRootNodeNeedsUpdate;
 
     private boolean mEnabled;
     private boolean mRequested = true;
-    private boolean mIsOpaque = false;
 
     ThreadedRenderer(Context context, boolean translucent, String name) {
+        super();
+        setName(name);
+        setOpaque(!translucent);
+
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
         mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
         mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
-        mAmbientShadowAlpha =
-                (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
-        mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+        float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+        float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
         a.recycle();
-
-        long rootNodePtr = nCreateRootRenderNode();
-        mRootNode = RenderNode.adopt(rootNodePtr);
-        mRootNode.setClipToBounds(false);
-        mIsOpaque = !translucent;
-        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
-        nSetName(mNativeProxy, name);
-
-        ProcessInitializer.sInstance.init(context, mNativeProxy);
-
-        loadSystemProperties();
+        setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
     }
 
-    /**
-     * Destroys the threaded rendering context.
-     */
-    void destroy() {
+    @Override
+    public void destroy() {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+        super.destroy();
     }
 
     /**
@@ -464,7 +370,7 @@
         boolean status = !mInitialized;
         mInitialized = true;
         updateEnabledState(surface);
-        nInitialize(mNativeProxy, surface);
+        setSurface(surface);
         return status;
     }
 
@@ -505,26 +411,18 @@
      */
     void updateSurface(Surface surface) throws OutOfResourcesException {
         updateEnabledState(surface);
-        nUpdateSurface(mNativeProxy, surface);
+        setSurface(surface);
     }
 
-    /**
-     * Halts any current rendering into the surface. Use this if it is unclear whether
-     * or not the surface used by the ThreadedRenderer will be changing. It
-     * Suspends any rendering into the surface, but will not do any destruction.
-     *
-     * Any subsequent draws will override the pause, resuming normal operation.
-     */
-    boolean pauseSurface(Surface surface) {
-        return nPauseSurface(mNativeProxy, surface);
-    }
-
-    /**
-     * Hard stops or resumes rendering into the surface. This flag is used to
-     * determine whether or not it is safe to use the given surface *at all*
-     */
-    void setStopped(boolean stopped) {
-        nSetStopped(mNativeProxy, stopped);
+    @Override
+    public void setSurface(Surface surface) {
+        // TODO: Do we ever pass a non-null but isValid() = false surface?
+        // This is here to be super conservative for ViewRootImpl
+        if (surface != null && surface.isValid()) {
+            super.setSurface(surface);
+        } else {
+            super.setSurface(null);
+        }
     }
 
     /**
@@ -535,7 +433,7 @@
      */
     void destroyHardwareResources(View view) {
         destroyResources(view);
-        nDestroyHardwareResources(mNativeProxy);
+        destroyHardwareResources();
     }
 
     private static void destroyResources(View view) {
@@ -543,14 +441,6 @@
     }
 
     /**
-     * Detaches the layer's surface texture from the GL context and releases
-     * the texture id
-     */
-    void detachSurfaceTexture(long hardwareLayer) {
-        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
-    }
-
-    /**
      * Sets up the renderer for drawing.
      *
      * @param width The width of the drawing surface.
@@ -581,8 +471,6 @@
         }
 
         mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
-        nSetup(mNativeProxy, mLightRadius,
-                mAmbientShadowAlpha, mSpotShadowAlpha);
 
         setLightCenter(attachInfo);
     }
@@ -598,27 +486,7 @@
         attachInfo.mDisplay.getRealSize(displaySize);
         final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
         final float lightY = mLightY - attachInfo.mWindowTop;
-
-        nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
-    }
-
-    /**
-     * Change the ThreadedRenderer's opacity
-     */
-    void setOpaque(boolean opaque) {
-        mIsOpaque = opaque && !mHasInsets;
-        nSetOpaque(mNativeProxy, mIsOpaque);
-    }
-
-    boolean isOpaque() {
-        return mIsOpaque;
-    }
-
-    /**
-     * Enable/disable wide gamut rendering on this renderer.
-     */
-    void setWideGamut(boolean wideGamut) {
-        nSetWideGamut(mNativeProxy, wideGamut);
+        setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
     }
 
     /**
@@ -663,18 +531,12 @@
                     break;
             }
         }
-        nDumpProfileInfo(mNativeProxy, fd, flags);
+        dumpProfileInfo(fd, flags);
     }
 
-    /**
-     * 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);
+    @Override
+    public boolean loadSystemProperties() {
+        boolean changed = super.loadSystemProperties();
         if (changed) {
             invalidateRoot();
         }
@@ -695,72 +557,27 @@
         updateViewTreeDisplayList(view);
 
         if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
-            RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+            RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
             try {
                 final int saveCount = canvas.save();
                 canvas.translate(mInsetLeft, mInsetTop);
                 callbacks.onPreDraw(canvas);
 
-                canvas.insertReorderBarrier();
+                canvas.enableZ();
                 canvas.drawRenderNode(view.updateDisplayListIfDirty());
-                canvas.insertInorderBarrier();
+                canvas.disableZ();
 
                 callbacks.onPostDraw(canvas);
                 canvas.restoreToCount(saveCount);
                 mRootNodeNeedsUpdate = false;
             } finally {
-                mRootNode.end(canvas);
+                mRootNode.endRecording();
             }
         }
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
     }
 
     /**
-     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
-     * rendernode of the UI thread.
-     * @param node The node to add.
-     * @param placeFront If true, the render node will be placed in front of the content node,
-     *                   otherwise behind the content node.
-     */
-    @UnsupportedAppUsage
-    public void addRenderNode(RenderNode node, boolean placeFront) {
-        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
-    }
-
-    /**
-     * Only especially added render nodes can be removed.
-     * @param node The node which was added via addRenderNode which should get removed again.
-     */
-    @UnsupportedAppUsage
-    public void removeRenderNode(RenderNode node) {
-        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * Draws a particular render node. If the node is not the content node, only the additional
-     * nodes will get drawn and the content remains untouched.
-     * @param node The node to be drawn.
-     */
-    @UnsupportedAppUsage
-    public void drawRenderNode(RenderNode node) {
-        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
-     * will be prevented to overdraw this area. It will be synchronized with the draw call.
-     * This should be updated in the content view's draw call.
-     * @param left The left side of the protected bounds.
-     * @param top The top side of the protected bounds.
-     * @param right The right side of the protected bounds.
-     * @param bottom The bottom side of the protected bounds.
-     */
-    @UnsupportedAppUsage
-    public void setContentDrawBounds(int left, int top, int right, int bottom) {
-        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
-    }
-
-    /**
      * Interface used to receive callbacks whenever a view is drawn by
      * a threaded renderer instance.
      */
@@ -819,11 +636,10 @@
             attachInfo.mPendingAnimatingRenderNodes = null;
         }
 
-        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
         if (frameDrawingCallback != null) {
-            nSetFrameCallback(mNativeProxy, frameDrawingCallback);
+            setFrameCallback(frameDrawingCallback);
         }
-        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+        int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
             setEnabled(false);
             attachInfo.mViewRootImpl.mSurface.release();
@@ -831,207 +647,40 @@
             // if it is still needed or do nothing if we are no longer drawing
             attachInfo.mViewRootImpl.invalidate();
         }
-        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+        if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
             attachInfo.mViewRootImpl.invalidate();
         }
     }
 
-    void setFrameCompleteCallback(FrameCompleteCallback callback) {
-        nSetFrameCompleteCallback(mNativeProxy, callback);
-    }
-
-    static void invokeFunctor(long functor, boolean waitForCompletion) {
-        nInvokeFunctor(functor, waitForCompletion);
-    }
-
-    /**
-     * 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
-     */
-    TextureLayer createTextureLayer() {
-        long layer = nCreateTextureLayer(mNativeProxy);
-        return TextureLayer.adoptTextureLayer(this, layer);
-    }
-
-
-    void buildLayer(RenderNode node) {
-        if (node.hasDisplayList()) {
-            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
-        }
-    }
-
-
-    boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
-        return nCopyLayerInto(mNativeProxy,
-                layer.getDeferredLayerUpdater(), bitmap);
-    }
-
-    /**
-     * 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(TextureLayer layer) {
-        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Tells the HardwareRenderer that the layer is destroyed. The renderer
-     * should remove the layer from any update queues.
-     */
-    void onLayerDestroyed(TextureLayer layer) {
-        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Blocks until all previously queued work has completed.
-     */
-    void fence() {
-        nFence(mNativeProxy);
-    }
-
-    /**
-     * 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);
-    }
-
-    /**
-     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
-     */
-    public void notifyFramePending() {
-        nNotifyFramePending(mNativeProxy);
-    }
-
-
-    void registerAnimatingRenderNode(RenderNode animator) {
-        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
-    }
-
-    void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
-        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
-                animator.getAnimatorNativePtr());
-    }
-
-    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
-        if (srcRect == null) {
-            // Empty rect means entire surface
-            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
-        } else {
-            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
-                    srcRect.right, srcRect.bottom, bitmap);
-        }
-    }
-
-    /**
-     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
-     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
-     * not the RenderNode from a View.
-     **/
-    @UnsupportedAppUsage
-    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
-        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
-    }
-
-    /**
-     * Sets whether or not high contrast text rendering is enabled. The setting is global
-     * but only affects content rendered after the change is made.
-     */
-    public static void setHighContrastText(boolean highContrastText) {
-        nSetHighContrastText(highContrastText);
-    }
-
-    /**
-     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
-     */
-    public static void setIsolatedProcess(boolean isIsolated) {
-        nSetIsolatedProcess(isIsolated);
-    }
-
-    /**
-     * If set extra graphics debugging abilities will be enabled such as dumping skp
-     */
-    public static void setDebuggingEnabled(boolean enable) {
-        nSetDebuggingEnabled(enable);
-    }
-
-    void allocateBuffers(Surface surface) {
-        nAllocateBuffers(mNativeProxy, surface);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            nDeleteProxy(mNativeProxy);
-            mNativeProxy = 0;
-        } finally {
-            super.finalize();
-        }
-    }
-
     /** The root of everything */
     public @NonNull RenderNode getRootNode() {
         return mRootNode;
     }
 
-    private boolean mForceDark = false;
-
-    /**
-     * Whether or not the force-dark feature should be used for this renderer.
-     */
-    public boolean setForceDark(boolean enable) {
-        if (mForceDark != enable) {
-            mForceDark = enable;
-            nSetForceDark(mNativeProxy, enable);
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
      * TODO: deduplicate against ThreadedRenderer.
      *
      * @hide
      */
-    public static class SimpleRenderer {
-        private final RenderNode mRootNode;
-        private long mNativeProxy;
-        private final float mLightY, mLightZ;
-        private Surface mSurface;
-        private final FrameInfo mFrameInfo = new FrameInfo();
+    public static class SimpleRenderer extends HardwareRenderer {
+        private final float mLightY, mLightZ, mLightRadius;
 
         public SimpleRenderer(final Context context, final String name, final Surface surface) {
+            super();
+            setName(name);
+            setOpaque(false);
+            setSurface(surface);
             final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
             mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
             mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
-            final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+            mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
             final int ambientShadowAlpha =
                     (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
             final int spotShadowAlpha =
                     (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
             a.recycle();
-
-            final long rootNodePtr = nCreateRootRenderNode();
-            mRootNode = RenderNode.adopt(rootNodePtr);
-            mRootNode.setClipToBounds(false);
-            mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
-            nSetName(mNativeProxy, name);
-
-            ProcessInitializer.sInstance.init(context, mNativeProxy);
-            nLoadSystemProperties(mNativeProxy);
-
-            nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
-
-            mSurface = surface;
-            nUpdateSurface(mNativeProxy, surface);
+            setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
         }
 
         /**
@@ -1045,7 +694,7 @@
             final float lightX = displaySize.x / 2f - windowLeft;
             final float lightY = mLightY - windowTop;
 
-            nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
+            setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
         }
 
         public RenderNode getRootNode() {
@@ -1057,222 +706,10 @@
          */
         public void draw(final FrameDrawingCallback callback) {
             final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
-            mFrameInfo.setVsync(vsync, vsync);
-            mFrameInfo.addFlags(1 << 2 /* VSYNC */);
             if (callback != null) {
-                nSetFrameCallback(mNativeProxy, callback);
+                setFrameCallback(callback);
             }
-            nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
-        }
-
-        /**
-         * Destroy the renderer.
-         */
-        public void destroy() {
-            mSurface = null;
-            nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                nDeleteProxy(mNativeProxy);
-                mNativeProxy = 0;
-            } finally {
-                super.finalize();
-            }
+            syncAndDrawFrame(vsync);
         }
     }
-
-    /**
-     * Interface used to receive callbacks when a frame is being drawn.
-     */
-    public interface FrameDrawingCallback {
-        /**
-         * Invoked during a frame drawing.
-         *
-         * @param frame The id of the frame being drawn.
-         */
-        void onFrameDraw(long frame);
-    }
-
-    /**
-     * Interface used to be notified when a frame has finished rendering
-     */
-    public interface FrameCompleteCallback {
-        /**
-         * Invoked after a frame draw
-         *
-         * @param frameNr The id of the frame that was drawn.
-         */
-        void onFrameComplete(long frameNr);
-    }
-
-    private static class ProcessInitializer {
-        static ProcessInitializer sInstance = new ProcessInitializer();
-
-        private boolean mInitialized = false;
-
-        private Context mAppContext;
-        private IGraphicsStats mGraphicsStatsService;
-        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
-            @Override
-            public void onRotateGraphicsStatsBuffer() throws RemoteException {
-                rotateBuffer();
-            }
-        };
-
-        private ProcessInitializer() {}
-
-        synchronized void init(Context context, long renderProxy) {
-            if (mInitialized) return;
-            mInitialized = true;
-            mAppContext = context.getApplicationContext();
-
-            initSched(renderProxy);
-
-            if (mAppContext != null) {
-                initGraphicsStats();
-            }
-        }
-
-        private void initSched(long renderProxy) {
-            try {
-                int tid = nGetRenderThreadTid(renderProxy);
-                ActivityManager.getService().setRenderThread(tid);
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
-            }
-        }
-
-        private void initGraphicsStats() {
-            try {
-                IBinder binder = ServiceManager.getService("graphicsstats");
-                if (binder == null) return;
-                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
-                requestBuffer();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-
-        private void rotateBuffer() {
-            nRotateProcessStatsBuffer();
-            requestBuffer();
-        }
-
-        private void requestBuffer() {
-            try {
-                final String pkg = mAppContext.getApplicationInfo().packageName;
-                ParcelFileDescriptor pfd = mGraphicsStatsService
-                        .requestBufferForProcess(pkg, mGraphicsStatsCallback);
-                nSetProcessStatsBuffer(pfd.getFd());
-                pfd.close();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-    }
-
-    void addFrameMetricsObserver(FrameMetricsObserver observer) {
-        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
-        observer.mNative = new VirtualRefBasePtr(nativeObserver);
-    }
-
-    void removeFrameMetricsObserver(FrameMetricsObserver observer) {
-        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
-        observer.mNative = null;
-    }
-
-    /** b/68769804: For low FPS experiments. */
-    public static void setFPSDivisor(int divisor) {
-        nHackySetRTAnimationsEnabled(divisor <= 1);
-    }
-
-    /**
-     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
-     * called before any OpenGL context is created.
-     *
-     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
-     */
-    public static void setContextPriority(int priority) {
-        nSetContextPriority(priority);
-    }
-
-    /** Not actually public - internal use only. This doc to make lint happy */
-    public static native void disableVsync();
-
-    static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
-
-    private static native void nRotateProcessStatsBuffer();
-    private static native void nSetProcessStatsBuffer(int fd);
-    private static native int nGetRenderThreadTid(long nativeProxy);
-
-    private static native long nCreateRootRenderNode();
-    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
-    private static native void nDeleteProxy(long nativeProxy);
-
-    private static native boolean nLoadSystemProperties(long nativeProxy);
-    private static native void nSetName(long nativeProxy, String name);
-
-    private static native void nInitialize(long nativeProxy, Surface window);
-    private static native void nUpdateSurface(long nativeProxy, Surface window);
-    private static native boolean nPauseSurface(long nativeProxy, Surface window);
-    private static native void nSetStopped(long nativeProxy, boolean stopped);
-    private static native void nSetup(long nativeProxy,
-            float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
-    private static native void nSetLightCenter(long nativeProxy,
-            float lightX, float lightY, float lightZ);
-    private static native void nSetOpaque(long nativeProxy, boolean opaque);
-    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
-    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
-    private static native void nDestroy(long nativeProxy, long rootRenderNode);
-    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
-    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
-
-    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
-
-    private static native long nCreateTextureLayer(long nativeProxy);
-    private static native void nBuildLayer(long nativeProxy, long node);
-    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
-    private static native void nPushLayerUpdate(long nativeProxy, long layer);
-    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
-    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
-
-    private static native void nDestroyHardwareResources(long nativeProxy);
-    private static native void nTrimMemory(int level);
-    private static native void nOverrideProperty(String name, String value);
-
-    private static native void nFence(long nativeProxy);
-    private static native void nStopDrawing(long nativeProxy);
-    private static native void nNotifyFramePending(long nativeProxy);
-
-    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
-            @DumpFlags int dumpFlags);
-
-    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
-             boolean placeFront);
-    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nSetContentDrawBounds(long nativeProxy, int left,
-             int top, int right, int bottom);
-    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
-    private static native void nSetFrameCompleteCallback(long nativeProxy,
-            FrameCompleteCallback callback);
-
-    private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
-    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
-
-    private static native int nCopySurfaceInto(Surface surface,
-            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
-
-    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
-    private static native void nSetHighContrastText(boolean enabled);
-    // For temporary experimentation b/66945974
-    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
-    private static native void nSetDebuggingEnabled(boolean enabled);
-    private static native void nSetIsolatedProcess(boolean enabled);
-    private static native void nSetContextPriority(int priority);
-    private static native void nAllocateBuffers(long nativeProxy, Surface window);
-    private static native void nSetForceDark(long nativeProxy, boolean enabled);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1f640..a23d68b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,8 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer.FrameDrawingCallback;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -84,7 +86,6 @@
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl.Transaction;
-import android.view.ThreadedRenderer.FrameDrawingCallback;
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
@@ -2148,7 +2149,7 @@
                     // relayoutWindow may decide to destroy mSurface. As that decision
                     // happens in WindowManager service, we need to be defensive here
                     // and stop using the surface in case it gets destroyed.
-                    if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
+                    if (mAttachInfo.mThreadedRenderer.pause()) {
                         // Animations were running so we need to push a frame
                         // to resume them
                         mDirty.set(0, 0, mWidth, mHeight);
@@ -2266,7 +2267,7 @@
                                         & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                     // Don't pre-allocate if transparent regions
                                     // are requested as they may not be needed
-                                    mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
+                                    mAttachInfo.mThreadedRenderer.allocateBuffers();
                                 }
                             } catch (OutOfResourcesException e) {
                                 handleOutOfResourcesException(e);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f512ce4..b8139a7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -556,18 +556,18 @@
         proxy->setWideGamut(true);
     }
     proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     // Shadows can't be used via this interface, so just set the light source
     // to all 0s.
-    proxy->setup(0, 0, 0);
-    proxy->setLightCenter((Vector3){0, 0, 0});
+    proxy->setLightAlpha(0, 0);
+    proxy->setLightGeometry((Vector3){0, 0, 0}, 0);
     return (jlong) proxy;
 }
 
 static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
     sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7a5b604..702741e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -686,31 +686,20 @@
     env->ReleaseStringUTFChars(jname, name);
 }
 
-static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->initialize(surface);
-}
-
-static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     sp<Surface> surface;
     if (jsurface) {
         surface = android_view_Surface_getSurface(env, jsurface);
     }
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
-static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface;
-    if (jsurface) {
-        surface = android_view_Surface_getSurface(env, jsurface);
-    }
-    return proxy->pauseSurface(surface);
+    return proxy->pause();
 }
 
 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
@@ -719,16 +708,16 @@
     proxy->setStopped(stopped);
 }
 
-static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
-        jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
+static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
+        jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
+    proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
 }
 
-static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
+static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
+    proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
 }
 
 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -990,13 +979,12 @@
     {
         ContextFactory factory;
         RenderProxy proxy{true, renderNode, &factory};
-        proxy.loadSystemProperties();
         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-        proxy.initialize(surface);
+        proxy.setSurface(surface);
         // Shadows can't be used via this interface, so just set the light source
         // to all 0s.
-        proxy.setup(0, 0, 0);
-        proxy.setLightCenter((Vector3){0, 0, 0});
+        proxy.setLightAlpha(0, 0);
+        proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
         UiFrameInfoBuilder(proxy.frameInfo())
                 .setVsync(vsync, vsync)
@@ -1058,10 +1046,9 @@
 }
 
 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->allocateBuffers(surface);
+    proxy->allocateBuffers();
 }
 
 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
@@ -1118,7 +1105,7 @@
 // JNI Glue
 // ----------------------------------------------------------------------------
 
-const char* const kClassPathName = "android/view/ThreadedRenderer";
+const char* const kClassPathName = "android/graphics/HardwareRenderer";
 
 static const JNINativeMethod gMethods[] = {
     { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
@@ -1129,12 +1116,11 @@
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
     { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
-    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
-    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
-    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+    { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface },
+    { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause },
     { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
-    { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
+    { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha },
+    { "nSetLightGeometry", "(JFFFF)V", (void*) android_view_ThreadedRenderer_setLightGeometry },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
@@ -1161,9 +1147,9 @@
     { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
     { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
     { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
-    { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
+    { "nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCallback},
-    { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+    { "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
     { "nAddFrameMetricsObserver",
             "(JLandroid/view/FrameMetricsObserver;)J",
@@ -1182,7 +1168,7 @@
     { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
     { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
     { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
-    { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
+    { "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
     { "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
 };
 
@@ -1215,12 +1201,12 @@
             env, metricsClass, "mTimingData", "[J");
 
     jclass frameCallbackClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameDrawingCallback");
+            "android/graphics/HardwareRenderer$FrameDrawingCallback");
     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
             "onFrameDraw", "(J)V");
 
     jclass frameCompleteClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameCompleteCallback");
+            "android/graphics/HardwareRenderer$FrameCompleteCallback");
     gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
             "onFrameComplete", "(J)V");
 
diff --git a/core/java/android/view/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
similarity index 70%
rename from core/java/android/view/FrameInfo.java
rename to graphics/java/android/graphics/FrameInfo.java
index 6c5e048..42a5cc4 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.graphics;
 
 import android.annotation.LongDef;
 
@@ -33,14 +33,14 @@
  * long layout & measure took it's displayListRecordStart - performTraversalsStart.
  *
  * These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * used for indexing into AttachInfo's frameInfo long[], which is intended
  * to be quick to pass down to native via JNI, hence a pre-packed format
  *
  * @hide
  */
-final class FrameInfo {
+public final class FrameInfo {
 
-    long[] mFrameInfo = new long[9];
+    public long[] frameInfo = new long[9];
 
     // Various flags set to provide extra metadata about the current frame
     private static final int FLAGS = 0;
@@ -48,8 +48,11 @@
     // Is this the first-draw following a window layout?
     public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
 
+    // A renderer associated with just a Surface, not with a ViewRootImpl instance.
+    public static final long FLAG_SURFACE_CANVAS = 1 << 2;
+
     @LongDef(flag = true, value = {
-            FLAG_WINDOW_LAYOUT_CHANGED })
+            FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrameInfoFlags {}
 
@@ -78,41 +81,48 @@
     // When View:draw() started
     private static final int DRAW_START = 8;
 
+    /** checkstyle */
     public void setVsync(long intendedVsync, long usedVsync) {
-        mFrameInfo[INTENDED_VSYNC] = intendedVsync;
-        mFrameInfo[VSYNC] = usedVsync;
-        mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
-        mFrameInfo[NEWEST_INPUT_EVENT] = 0;
-        mFrameInfo[FLAGS] = 0;
+        frameInfo[INTENDED_VSYNC] = intendedVsync;
+        frameInfo[VSYNC] = usedVsync;
+        frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+        frameInfo[NEWEST_INPUT_EVENT] = 0;
+        frameInfo[FLAGS] = 0;
     }
 
+    /** checkstyle */
     public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
-        if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
-            mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+        if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
+            frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
         }
-        if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
-            mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+        if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
+            frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
         }
     }
 
+    /** checkstyle */
     public void markInputHandlingStart() {
-        mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+        frameInfo[HANDLE_INPUT_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markAnimationsStart() {
-        mFrameInfo[ANIMATION_START] = System.nanoTime();
+        frameInfo[ANIMATION_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markPerformTraversalsStart() {
-        mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+        frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markDrawStart() {
-        mFrameInfo[DRAW_START] = System.nanoTime();
+        frameInfo[DRAW_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void addFlags(@FrameInfoFlags long flags) {
-        mFrameInfo[FLAGS] |= flags;
+        frameInfo[FLAGS] |= flags;
     }
 
 }
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
new file mode 100644
index 0000000..e402055
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2018 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.graphics;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.FrameMetricsObserver;
+import android.view.IGraphicsStats;
+import android.view.IGraphicsStatsCallback;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureLayer;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import sun.misc.Cleaner;
+
+/**
+ * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
+ * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
+ * HardwareRenderer instances as desired.</p>
+ *
+ * <h3>Threading</h3>
+ * <p>HardwareRenderer is not thread safe. An instance of a HardwareRenderer must only be
+ * created & used from a single thread. It does not matter what thread is used, however
+ * it must have a {@link android.os.Looper}. Multiple instances do not have to share the same
+ * thread, although they can.</p>
+ *
+ * <h3>Resources & lifecycle</h3>
+ * <p>All HardwareRenderer instances share a common render thread. The render thread contains
+ * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
+ * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
+ * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
+ * is to have a HardwareRenderer instance for every active {@link Surface}. For example
+ * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
+ * of which may be drawing at the same time.</p>
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @hide
+ */
+public class HardwareRenderer {
+    private static final String LOG_TAG = "HardwareRenderer";
+
+    // Keep in sync with DrawFrameTask.h SYNC_* flags
+    /**
+     * Nothing interesting to report. Sync & draw kicked off
+     */
+    public static final int SYNC_OK = 0;
+
+    /**
+     * The renderer is requesting a redraw. This can occur if there's an animation that's running
+     * in the RenderNode tree and the hardware renderer is unable to self-animate.
+     *
+     * If this is returned from syncAndDrawFrame the expectation is that syncAndDrawFrame
+     * will be called again on the next vsync signal.
+     */
+    public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
+
+    /**
+     * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
+     * This can happen if {@link Surface#destroy()} was called. The user should no longer
+     * attempt to call syncAndDrawFrame until a new surface has been provided by calling
+     * setSurface.
+     *
+     * Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+     */
+    public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
+
+    /**
+     * The hardware renderer has been set to a "stopped" state. If this is returned then the
+     * rendering content has been synced, however a frame was not produced.
+     */
+    public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+
+    /**
+     * The content was synced but the renderer has declined to produce a frame in this vsync
+     * interval. This can happen if a frame was already drawn in this vsync or if the renderer
+     * is outrunning the frame consumer. The renderer will internally re-schedule itself
+     * to render a frame in the next vsync signal, so the caller does not need to do anything
+     * in response to this signal.
+     */
+    public static final int SYNC_FRAME_DROPPED = 1 << 3;
+
+    @IntDef(value = {
+            SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
+            SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SyncAndDrawResult {
+    }
+
+    /** @hide */
+    public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+    /** @hide */
+    public static final int FLAG_DUMP_RESET = 1 << 1;
+    /** @hide */
+    public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
+            FLAG_DUMP_FRAMESTATS,
+            FLAG_DUMP_RESET
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DumpFlags {
+    }
+
+    /**
+     * Name of the file that holds the shaders cache.
+     */
+    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
+
+    private final long mNativeProxy;
+    /** @hide */
+    protected RenderNode mRootNode;
+    private boolean mOpaque = true;
+    private boolean mForceDark = false;
+    private FrameInfo mScratchInfo;
+
+    /**
+     * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
+     * to opaque with no light source configured.
+     */
+    public HardwareRenderer() {
+        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
+        mRootNode.setClipToBounds(false);
+        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
+        if (mNativeProxy == 0) {
+            throw new OutOfMemoryError("Unable to create hardware renderer");
+        }
+        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
+        ProcessInitializer.sInstance.init(mNativeProxy);
+    }
+
+    /**
+     * Destroys the rendering context of this HardwareRenderer. This destroys the resources
+     * associated with this renderer and releases the currently set {@link Surface}.
+     *
+     * The renderer may be restored from this state by setting a new {@link Surface}, setting
+     * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
+     * rendering with {@link #syncAndDrawFrame(long)}.
+     *
+     * It is suggested to call this in response to callbacks such as
+     * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
+     *
+     * Note that if there are any outstanding frame commit callbacks they may end up never being
+     * invoked if the frame was deferred to a later vsync.
+     */
+    public void destroy() {
+        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+    }
+
+    /**
+     * Sets a name for this renderer. This is used to identify this renderer instance
+     * when reporting debug information such as the per-window frame time metrics
+     * reported by 'adb shell dumpsys gfxinfo [package] framestats'
+     *
+     * @param name The debug name to use for this HardwareRenderer instance
+     */
+    public void setName(String name) {
+        nSetName(mNativeProxy, name);
+    }
+
+    /**
+     * Sets the center of the light source. The light source point controls the directionality
+     * and shape of shadows rendered by RenderNode Z & elevation.
+     *
+     * The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
+     * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
+     *
+     * The light source should be setup both as part of initial configuration, and whenever
+     * the window moves to ensure the light source stays anchored in display space instead
+     * of in window space.
+     *
+     * This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
+     * before shadows will work.
+     *
+     * @param lightX      The X position of the light source
+     * @param lightY      The Y position of the light source
+     * @param lightZ      The Z position of the light source. Must be >= 0.
+     * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
+     *                    larger radius will have softer shadows.
+     */
+    public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
+            float lightRadius) {
+        validateFinite(lightX, "lightX");
+        validateFinite(lightY, "lightY");
+        validatePositive(lightZ, "lightZ");
+        validatePositive(lightRadius, "lightRadius");
+        nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
+    }
+
+    /**
+     * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
+     * has max alpha, and ramps down from the values provided to zero.
+     *
+     * These values are typically provided by the current theme, see
+     * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
+     *
+     * This must be set at least once along with
+     * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
+     *
+     * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
+     *                           is 0.039f.
+     * @param spotShadowAlpha    The alpha for the spot shadow. If unsure, a reasonable default is
+     *                           0.19f.
+     */
+    public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
+            @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
+        validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
+        validateAlpha(spotShadowAlpha, "spotShadowAlpha");
+        nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
+    }
+
+    /**
+     * Sets the content root to render. It is not necessary to call this whenever the content
+     * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
+     * contained within the content node, will be applied whenever {@link #syncAndDrawFrame(long)}
+     * is called.
+     *
+     * @param content The content to set as the root RenderNode. If null the content root is removed
+     *                and the renderer will draw nothing.
+     */
+    public void setContentRoot(@Nullable RenderNode content) {
+        RecordingCanvas canvas = mRootNode.startRecording();
+        if (content != null) {
+            canvas.drawRenderNode(content);
+        }
+        mRootNode.endRecording();
+    }
+
+    /**
+     * <p>The surface to render into. The surface is assumed to be associated with the display and
+     * as such is still driven by vsync signals such as those from
+     * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
+     * the display's (typically 60hz).</p>
+     *
+     * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+     * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+     * consumers such as {@link android.view.SurfaceView},
+     * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+     * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+     * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+     * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+     * Failure to do so will cause the render thread to stall on that surface, blocking all
+     * HardwareRenderer instances.</p>
+     *
+     * @param surface The surface to render into. If null then rendering will be stopped. If
+     *                non-null then {@link Surface#isValid()} must be true.
+     */
+    public void setSurface(@Nullable Surface surface) {
+        if (surface != null && !surface.isValid()) {
+            throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
+        }
+        nSetSurface(mNativeProxy, surface);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @hide
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
+        return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+     *                  {@link android.view.Choreographer.FrameCallback}. Must be set and be valid
+     *                  as the renderer uses this time internally to drive animations.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime) {
+        if (mScratchInfo == null) {
+            mScratchInfo = new FrameInfo();
+        }
+        mScratchInfo.setVsync(vsyncTime, vsyncTime);
+        mScratchInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
+        return syncAndDrawFrame(mScratchInfo);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     * frameCommitCallback callback will be invoked when the current rendering content has been
+     * rendered into a frame and submitted to the swap chain.
+     *
+     * @param vsyncTime           The vsync timestamp for this frame. Typically this comes from
+     *                            {@link android.view.Choreographer.FrameCallback}. Must be set and
+     *                            be valid as the renderer uses this time internally to drive
+     *                            animations.
+     * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
+     *                            Will be invoked on the current {@link android.os.Looper} thread.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime,
+            @Nullable Runnable frameCommitCallback) {
+        if (frameCommitCallback != null) {
+            setFrameCompleteCallback(frameNr -> frameCommitCallback.run());
+        }
+        return syncAndDrawFrame(vsyncTime);
+    }
+
+    /**
+     * Suspends any current rendering into the surface but do not do any destruction. This
+     * is useful to temporarily suspend using the active Surface in order to do any Surface
+     * mutations necessary.
+     *
+     * Any subsequent draws will override the pause, resuming normal operation.
+     *
+     * @return true if there was an outstanding render request, false otherwise. If this is true
+     * the caller should ensure that {@link #syncAndDrawFrame(long)} is called at the soonest
+     * possible time to resume normal operation.
+     *
+     * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
+     * Surface before getting a new one. However things like SurfaceView will ensure that
+     * the old surface remains un-destroyed until after a new frame has been produced with
+     * the new surface.
+     * @hide
+     */
+    public boolean pause() {
+        return nPause(mNativeProxy);
+    }
+
+    /**
+     * Hard stops rendering into the surface. If the renderer is stopped it will
+     * block any attempt to render. Calls to {@link #syncAndDrawFrame(long)} will still
+     * sync over the latest rendering content, however they will not render and instead
+     * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
+     *
+     * If false is passed then rendering will resume as normal. Any pending rendering requests
+     * will produce a new frame at the next vsync signal.
+     *
+     * This is useful in combination with lifecycle events such as {@link Activity#onStop()}
+     * and {@link Activity#onStart()}.
+     *
+     * @param stopped true to stop all rendering, false to resume
+     */
+    public void setStopped(boolean stopped) {
+        nSetStopped(mNativeProxy, stopped);
+    }
+
+    /**
+     * Destroys all hardware rendering resources associated with the current rendering content.
+     * This includes releasing a reference to the current content root RenderNode. It will
+     * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
+     * rendering after calling this.
+     *
+     * It is recommended, but not necessary, to use this in combination with lifecycle events
+     * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
+     * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
+     * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
+     *
+     * See also {@link #setStopped(boolean)}
+     */
+    public void destroyHardwareResources() {
+        nDestroyHardwareResources(mNativeProxy);
+    }
+
+    /**
+     * Whether or not the force-dark feature should be used for this renderer.
+     */
+    public boolean setForceDark(boolean enable) {
+        if (mForceDark != enable) {
+            mForceDark = enable;
+            nSetForceDark(mNativeProxy, enable);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Allocate buffers ahead of time to avoid allocation delays during rendering.
+     *
+     * Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
+     * memory usage of Surfaces that render rarely or never hit triple buffering. However
+     * for UI it can result in a slight bit of jank on first launch. This hint will
+     * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
+     * necessary for typical rendering.
+     *
+     * Must be called after a {@link Surface} has been set.
+     */
+    public void allocateBuffers() {
+        nAllocateBuffers(mNativeProxy);
+    }
+
+    /**
+     * Notifies the hardware renderer that a call to {@link #syncAndDrawFrame(long)} will
+     * be coming soon. This is used to help schedule when RenderThread-driven animations will
+     * happen as the renderer wants to avoid producing more than one frame per vsync signal.
+     */
+    public void notifyFramePending() {
+        nNotifyFramePending(mNativeProxy);
+    }
+
+    /**
+     * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
+     *
+     * If the renderer is set to opaque it is the app's responsibility to ensure that the
+     * content renders to every pixel of the Surface, otherwise corruption may result. Note that
+     * this includes ensuring that the first draw of any given pixel does not attempt to blend
+     * against the destination. If this is false then the hardware renderer will clear to
+     * transparent at the start of every frame.
+     *
+     * @param opaque true if the content rendered is opaque, false if the renderer should clear
+     *               to transparent before rendering
+     */
+    public void setOpaque(boolean opaque) {
+        if (mOpaque != opaque) {
+            mOpaque = opaque;
+            nSetOpaque(mNativeProxy, mOpaque);
+        }
+    }
+
+    /**
+     * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
+     *
+     * @return true if the renderer is opaque, false otherwise
+     */
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /** @hide */
+    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
+        nSetFrameCompleteCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void addFrameMetricsObserver(FrameMetricsObserver observer) {
+        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+        observer.mNative = new VirtualRefBasePtr(nativeObserver);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+        observer.mNative = null;
+    }
+
+    /**
+     * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
+     * will be wide gamut depends on the hardware support for such rendering.
+     *
+     * @param wideGamut true if this renderer should render in wide gamut, false if it should
+     *                  render in sRGB
+     *                  TODO: Figure out color...
+     * @hide
+     */
+    public void setWideGamut(boolean wideGamut) {
+        nSetWideGamut(mNativeProxy, wideGamut);
+    }
+
+    /**
+     * Blocks until all previously queued work has completed.
+     *
+     * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
+     * better
+     *
+     * @hide
+     */
+    public void fence() {
+        nFence(mNativeProxy);
+    }
+
+    /** @hide */
+    public void registerAnimatingRenderNode(RenderNode animator) {
+        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+    }
+
+    /** @hide */
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
+                animator.getAnimatorNativePtr());
+    }
+
+    /**
+     * Prevents any further drawing until {@link #syncAndDrawFrame(long)} 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.
+     *
+     * TODO: Can we get webview off of this?
+     *
+     * @hide
+     */
+    public void stopDrawing() {
+        nStopDrawing(mNativeProxy);
+    }
+
+    /**
+     * 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
+     * @hide
+     */
+    public TextureLayer createTextureLayer() {
+        long layer = nCreateTextureLayer(mNativeProxy);
+        return TextureLayer.adoptTextureLayer(this, layer);
+    }
+
+    /**
+     * Detaches the layer's surface texture from the GL context and releases
+     * the texture id
+     *
+     * @hide
+     */
+    public void detachSurfaceTexture(long hardwareLayer) {
+        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
+    }
+
+
+    /** @hide */
+    public void buildLayer(RenderNode node) {
+        if (node.hasDisplayList()) {
+            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
+        }
+    }
+
+    /** @hide */
+    public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
+        return nCopyLayerInto(mNativeProxy,
+                layer.getDeferredLayerUpdater(), bitmap);
+    }
+
+    /**
+     * Indicates that the specified hardware layer needs to be updated
+     * as soon as possible.
+     *
+     * @param layer The hardware layer that needs an update
+     * @hide
+     */
+    public void pushLayerUpdate(TextureLayer layer) {
+        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /**
+     * Tells the HardwareRenderer that the layer is destroyed. The renderer
+     * should remove the layer from any update queues.
+     *
+     * @hide
+     */
+    public void onLayerDestroyed(TextureLayer layer) {
+        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /** @hide */
+    public void setFrameCallback(FrameDrawingCallback callback) {
+        nSetFrameCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+     * rendernode of the UI thread.
+     *
+     * @param node       The node to add.
+     * @param placeFront If true, the render node will be placed in front of the content node,
+     *                   otherwise behind the content node.
+     * @hide
+     */
+    public void addRenderNode(RenderNode node, boolean placeFront) {
+        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+    }
+
+    /**
+     * Only especially added render nodes can be removed.
+     *
+     * @param node The node which was added via addRenderNode which should get removed again.
+     * @hide
+     */
+    public void removeRenderNode(RenderNode node) {
+        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Draws a particular render node. If the node is not the content node, only the additional
+     * nodes will get drawn and the content remains untouched.
+     *
+     * @param node The node to be drawn.
+     * @hide
+     */
+    public void drawRenderNode(RenderNode node) {
+        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * 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.
+     * @hide
+     */
+    public boolean loadSystemProperties() {
+        return nLoadSystemProperties(mNativeProxy);
+    }
+
+    /**
+     * @hide
+     */
+    public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
+        nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
+    }
+
+    /**
+     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+     * will be prevented to overdraw this area. It will be synchronized with the draw call.
+     * This should be updated in the content view's draw call.
+     *
+     * @param left   The left side of the protected bounds.
+     * @param top    The top side of the protected bounds.
+     * @param right  The right side of the protected bounds.
+     * @param bottom The bottom side of the protected bounds.
+     * @hide
+     */
+    public void setContentDrawBounds(int left, int top, int right, int bottom) {
+        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
+    }
+
+    /**
+     * Interface used to receive callbacks when a frame is being drawn.
+     *
+     * @hide
+     */
+    public interface FrameDrawingCallback {
+        /**
+         * Invoked during a frame drawing.
+         *
+         * @param frame The id of the frame being drawn.
+         */
+        void onFrameDraw(long frame);
+    }
+
+    /**
+     * Interface used to be notified when a frame has finished rendering
+     *
+     * @hide
+     */
+    public interface FrameCompleteCallback {
+        /**
+         * Invoked after a frame draw
+         *
+         * @param frameNr The id of the frame that was drawn.
+         */
+        void onFrameComplete(long frameNr);
+    }
+
+    private static void validateAlpha(float alpha, String argumentName) {
+        if (!(alpha >= 0.0f && alpha <= 1.0f)) {
+            throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
+                    + alpha + " is not in the range of 0.0f to 1.0f");
+        }
+    }
+
+    private static void validatePositive(float f, String argumentName) {
+        if (!(Float.isFinite(f) && f >= 0.0f)) {
+            throw new IllegalArgumentException(argumentName
+                    + " must be a finite positive, given=" + f);
+        }
+    }
+
+    private static void validateFinite(float f, String argumentName) {
+        if (!Float.isFinite(f)) {
+            throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
+        }
+    }
+
+    /** @hide */
+    public static void invokeFunctor(long functor, boolean waitForCompletion) {
+        nInvokeFunctor(functor, waitForCompletion);
+    }
+
+    /**
+     * b/68769804: For low FPS experiments.
+     *
+     * @hide
+     */
+    public static void setFPSDivisor(int divisor) {
+        nHackySetRTAnimationsEnabled(divisor <= 1);
+    }
+
+    /**
+     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+     * called before any OpenGL context is created.
+     *
+     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+     * @hide
+     */
+    public static void setContextPriority(int priority) {
+        nSetContextPriority(priority);
+    }
+
+    /**
+     * Sets whether or not high contrast text rendering is enabled. The setting is global
+     * but only affects content rendered after the change is made.
+     *
+     * @hide
+     */
+    public static void setHighContrastText(boolean highContrastText) {
+        nSetHighContrastText(highContrastText);
+    }
+
+    /**
+     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+     *
+     * @hide
+     */
+    public static void setIsolatedProcess(boolean isIsolated) {
+        nSetIsolatedProcess(isIsolated);
+    }
+
+    /**
+     * If set extra graphics debugging abilities will be enabled such as dumping skp
+     *
+     * @hide
+     */
+    public static void setDebuggingEnabled(boolean enable) {
+        nSetDebuggingEnabled(enable);
+    }
+
+    /** @hide */
+    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
+        if (srcRect == null) {
+            // Empty rect means entire surface
+            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
+        } else {
+            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
+                    srcRect.right, srcRect.bottom, bitmap);
+        }
+    }
+
+    /**
+     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+     * not the RenderNode from a View.
+     *
+     * @hide
+     **/
+    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
+    }
+
+    /**
+     * 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}
+     * @hide
+     */
+    public static void trimMemory(int level) {
+        nTrimMemory(level);
+    }
+
+    /** @hide */
+    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);
+    }
+
+    /**
+     * Sets the directory to use as a persistent storage for threaded rendering
+     * resources.
+     *
+     * @param cacheDir A directory the current process can write to
+     * @hide
+     */
+    public static void setupDiskCache(File cacheDir) {
+        setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
+                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
+    }
+
+    /** @hide */
+    public static void setPackageName(String packageName) {
+        ProcessInitializer.sInstance.setPackageName(packageName);
+    }
+
+    private static final class DestroyContextRunnable implements Runnable {
+        private final long mNativeInstance;
+
+        DestroyContextRunnable(long nativeInstance) {
+            mNativeInstance = nativeInstance;
+        }
+
+        @Override
+        public void run() {
+            nDeleteProxy(mNativeInstance);
+        }
+    }
+
+    private static class ProcessInitializer {
+        static ProcessInitializer sInstance = new ProcessInitializer();
+
+        private boolean mInitialized = false;
+
+        private String mPackageName;
+        private IGraphicsStats mGraphicsStatsService;
+        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+            @Override
+            public void onRotateGraphicsStatsBuffer() throws RemoteException {
+                rotateBuffer();
+            }
+        };
+
+        private ProcessInitializer() {
+        }
+
+        synchronized void setPackageName(String name) {
+            if (mInitialized) return;
+            mPackageName = name;
+        }
+
+        synchronized void init(long renderProxy) {
+            if (mInitialized) return;
+            mInitialized = true;
+
+            initSched(renderProxy);
+            initGraphicsStats();
+        }
+
+        private void initSched(long renderProxy) {
+            try {
+                int tid = nGetRenderThreadTid(renderProxy);
+                ActivityManager.getService().setRenderThread(tid);
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
+            }
+        }
+
+        private void initGraphicsStats() {
+            if (mPackageName == null) return;
+
+            try {
+                IBinder binder = ServiceManager.getService("graphicsstats");
+                if (binder == null) return;
+                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+                requestBuffer();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+
+        private void rotateBuffer() {
+            nRotateProcessStatsBuffer();
+            requestBuffer();
+        }
+
+        private void requestBuffer() {
+            try {
+                ParcelFileDescriptor pfd = mGraphicsStatsService
+                        .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
+                nSetProcessStatsBuffer(pfd.getFd());
+                pfd.close();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static native void disableVsync();
+
+    /** @hide */
+    protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
+
+    private static native void nRotateProcessStatsBuffer();
+
+    private static native void nSetProcessStatsBuffer(int fd);
+
+    private static native int nGetRenderThreadTid(long nativeProxy);
+
+    private static native long nCreateRootRenderNode();
+
+    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
+
+    private static native void nDeleteProxy(long nativeProxy);
+
+    private static native boolean nLoadSystemProperties(long nativeProxy);
+
+    private static native void nSetName(long nativeProxy, String name);
+
+    private static native void nSetSurface(long nativeProxy, Surface window);
+
+    private static native boolean nPause(long nativeProxy);
+
+    private static native void nSetStopped(long nativeProxy, boolean stopped);
+
+    private static native void nSetLightGeometry(long nativeProxy,
+            float lightX, float lightY, float lightZ, float lightRadius);
+
+    private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
+            float spotShadowAlpha);
+
+    private static native void nSetOpaque(long nativeProxy, boolean opaque);
+
+    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+
+    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+
+    private static native void nDestroy(long nativeProxy, long rootRenderNode);
+
+    private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
+            long animatingNode);
+
+    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
+
+    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
+
+    private static native long nCreateTextureLayer(long nativeProxy);
+
+    private static native void nBuildLayer(long nativeProxy, long node);
+
+    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+
+    private static native void nPushLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
+
+    private static native void nDestroyHardwareResources(long nativeProxy);
+
+    private static native void nTrimMemory(int level);
+
+    private static native void nOverrideProperty(String name, String value);
+
+    private static native void nFence(long nativeProxy);
+
+    private static native void nStopDrawing(long nativeProxy);
+
+    private static native void nNotifyFramePending(long nativeProxy);
+
+    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+            @DumpFlags int dumpFlags);
+
+    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+            boolean placeFront);
+
+    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nSetContentDrawBounds(long nativeProxy, int left,
+            int top, int right, int bottom);
+
+    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+
+    private static native void nSetFrameCompleteCallback(long nativeProxy,
+            FrameCompleteCallback callback);
+
+    private static native long nAddFrameMetricsObserver(long nativeProxy,
+            FrameMetricsObserver observer);
+
+    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+    private static native int nCopySurfaceInto(Surface surface,
+            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
+
+    private static native void nSetHighContrastText(boolean enabled);
+
+    // For temporary experimentation b/66945974
+    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
+
+    private static native void nSetDebuggingEnabled(boolean enabled);
+
+    private static native void nSetIsolatedProcess(boolean enabled);
+
+    private static native void nSetContextPriority(int priority);
+
+    private static native void nAllocateBuffers(long nativeProxy);
+
+    private static native void nSetForceDark(long nativeProxy, boolean enabled);
+}
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 236a6b6..b04c774 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -66,6 +66,7 @@
 
 FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
     setDensity(1);
+    consumeProperties();
 }
 
 FrameInfoVisualizer::~FrameInfoVisualizer() {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 92a749f..f1a522e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -180,14 +180,20 @@
     }
 }
 
-void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
-    mLightGeometry.radius = lightRadius;
+void CanvasContext::allocateBuffers() {
+    if (mNativeSurface) {
+        mNativeSurface->allocateBuffers();
+    }
+}
+
+void CanvasContext::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
     mLightInfo.spotShadowAlpha = spotShadowAlpha;
 }
 
-void CanvasContext::setLightCenter(const Vector3& lightCenter) {
+void CanvasContext::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
     mLightGeometry.center = lightCenter;
+    mLightGeometry.radius = lightRadius;
 }
 
 void CanvasContext::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2307ee4..70be4a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -113,9 +113,10 @@
     bool pauseSurface();
     void setStopped(bool stopped);
     bool hasSurface() { return mNativeSurface.get(); }
+    void allocateBuffers();
 
-    void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    void setLightCenter(const Vector3& lightCenter);
+    void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     void setOpaque(bool opaque);
     void setWideGamut(bool wideGamut);
     bool makeCurrent();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 54219b5..085812a0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -80,22 +80,16 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
-void RenderProxy::initialize(const sp<Surface>& surface) {
+void RenderProxy::setSurface(const sp<Surface>& surface) {
     mRenderThread.queue().post(
             [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
 }
 
-void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ surf = surface ]() mutable { surf->allocateBuffers(); });
+void RenderProxy::allocateBuffers() {
+    mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
 }
 
-void RenderProxy::updateSurface(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
-}
-
-bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
+bool RenderProxy::pause() {
     return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
 }
 
@@ -103,13 +97,13 @@
     mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
 }
 
-void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mRenderThread.queue().post(
-            [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
+            [=]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
 }
 
-void RenderProxy::setLightCenter(const Vector3& lightCenter) {
-    mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
+void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
+    mRenderThread.queue().post([=]() { mContext->setLightGeometry(lightCenter, lightRadius); });
 }
 
 void RenderProxy::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d29fcc4..6668c584 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,13 +69,12 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void initialize(const sp<Surface>& surface);
-    ANDROID_API void allocateBuffers(const sp<Surface>& surface);
-    ANDROID_API void updateSurface(const sp<Surface>& surface);
-    ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+    ANDROID_API void setSurface(const sp<Surface>& surface);
+    ANDROID_API void allocateBuffers();
+    ANDROID_API bool pause();
     ANDROID_API void setStopped(bool stopped);
-    ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    ANDROID_API void setLightCenter(const Vector3& lightCenter);
+    ANDROID_API void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    ANDROID_API void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API void setWideGamut(bool wideGamut);
     ANDROID_API int64_t* frameInfo();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 62f704b..2384f95 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,7 +74,7 @@
     PREVENT_COPY_AND_ASSIGN(RenderThread);
 
 public:
-    // Sets a callback that fires before any RenderThread setup has occured.
+    // Sets a callback that fires before any RenderThread setup has occurred.
     ANDROID_API static void setOnStartHook(void (*onStartHook)());
 
     WorkQueue& queue() { return ThreadBase::queue(); }
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..5fa008b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -132,10 +132,10 @@
     ContextFactory factory;
     std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
     proxy->loadSystemProperties();
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     float lightX = width / 2.0;
-    proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
-    proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+    proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
+    proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
 
     // Do a few cold runs then reset the stats so that the caches are all hot
     int warmupFrameCount = 5;