Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.NonNull;
     21 import android.app.ActivityManager;
     22 import android.content.Context;
     23 import android.content.res.TypedArray;
     24 import android.graphics.Bitmap;
     25 import android.graphics.Point;
     26 import android.graphics.Rect;
     27 import android.graphics.drawable.AnimatedVectorDrawable;
     28 import android.os.IBinder;
     29 import android.os.ParcelFileDescriptor;
     30 import android.os.RemoteException;
     31 import android.os.ServiceManager;
     32 import android.os.Trace;
     33 import android.util.Log;
     34 import android.view.Surface.OutOfResourcesException;
     35 import android.view.View.AttachInfo;
     36 
     37 import com.android.internal.R;
     38 import com.android.internal.util.VirtualRefBasePtr;
     39 
     40 import java.io.File;
     41 import java.io.FileDescriptor;
     42 import java.io.PrintWriter;
     43 import java.lang.annotation.Retention;
     44 import java.lang.annotation.RetentionPolicy;
     45 
     46 /**
     47  * Threaded renderer that proxies the rendering to a render thread. Most calls
     48  * are currently synchronous.
     49  *
     50  * The UI thread can block on the RenderThread, but RenderThread must never
     51  * block on the UI thread.
     52  *
     53  * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
     54  * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
     55  * by the lifecycle of the RenderProxy.
     56  *
     57  * Note that although currently the EGL context & surfaces are created & managed
     58  * by the render thread, the goal is to move that into a shared structure that can
     59  * be managed by both threads. EGLSurface creation & deletion should ideally be
     60  * done on the UI thread and not the RenderThread to avoid stalling the
     61  * RenderThread with surface buffer allocation.
     62  *
     63  * @hide
     64  */
     65 public final class ThreadedRenderer {
     66     private static final String LOG_TAG = "ThreadedRenderer";
     67 
     68     /**
     69      * Name of the file that holds the shaders cache.
     70      */
     71     private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
     72 
     73     /**
     74      * System property used to enable or disable threaded rendering profiling.
     75      * The default value of this property is assumed to be false.
     76      *
     77      * When profiling is enabled, the adb shell dumpsys gfxinfo command will
     78      * output extra information about the time taken to execute by the last
     79      * frames.
     80      *
     81      * Possible values:
     82      * "true", to enable profiling
     83      * "visual_bars", to enable profiling and visualize the results on screen
     84      * "false", to disable profiling
     85      *
     86      * @see #PROFILE_PROPERTY_VISUALIZE_BARS
     87      *
     88      * @hide
     89      */
     90     public static final String PROFILE_PROPERTY = "debug.hwui.profile";
     91 
     92     /**
     93      * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
     94      * value, profiling data will be visualized on screen as a bar chart.
     95      *
     96      * @hide
     97      */
     98     public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
     99 
    100     /**
    101      * System property used to specify the number of frames to be used
    102      * when doing threaded rendering profiling.
    103      * The default value of this property is #PROFILE_MAX_FRAMES.
    104      *
    105      * When profiling is enabled, the adb shell dumpsys gfxinfo command will
    106      * output extra information about the time taken to execute by the last
    107      * frames.
    108      *
    109      * Possible values:
    110      * "60", to set the limit of frames to 60
    111      */
    112     static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
    113 
    114     /**
    115      * System property used to debug EGL configuration choice.
    116      *
    117      * Possible values:
    118      * "choice", print the chosen configuration only
    119      * "all", print all possible configurations
    120      */
    121     static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
    122 
    123     /**
    124      * Turn on to draw dirty regions every other frame.
    125      *
    126      * Possible values:
    127      * "true", to enable dirty regions debugging
    128      * "false", to disable dirty regions debugging
    129      *
    130      * @hide
    131      */
    132     public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
    133 
    134     /**
    135      * Turn on to flash hardware layers when they update.
    136      *
    137      * Possible values:
    138      * "true", to enable hardware layers updates debugging
    139      * "false", to disable hardware layers updates debugging
    140      *
    141      * @hide
    142      */
    143     public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
    144             "debug.hwui.show_layers_updates";
    145 
    146     /**
    147      * Controls overdraw debugging.
    148      *
    149      * Possible values:
    150      * "false", to disable overdraw debugging
    151      * "show", to show overdraw areas on screen
    152      * "count", to display an overdraw counter
    153      *
    154      * @hide
    155      */
    156     public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
    157 
    158     /**
    159      * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
    160      * value, overdraw will be shown on screen by coloring pixels.
    161      *
    162      * @hide
    163      */
    164     public static final String OVERDRAW_PROPERTY_SHOW = "show";
    165 
    166     /**
    167      * Defines the rendering pipeline to be used by the ThreadedRenderer.
    168      *
    169      * Possible values:
    170      * "opengl", will use the existing OpenGL renderer
    171      * "skiagl", will use Skia's OpenGL renderer
    172      * "skiavk", will use Skia's Vulkan renderer
    173      *
    174      * @hide
    175      */
    176     public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
    177 
    178     /**
    179      * Turn on to debug non-rectangular clip operations.
    180      *
    181      * Possible values:
    182      * "hide", to disable this debug mode
    183      * "highlight", highlight drawing commands tested against a non-rectangular clip
    184      * "stencil", renders the clip region on screen when set
    185      *
    186      * @hide
    187      */
    188     public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
    189             "debug.hwui.show_non_rect_clip";
    190 
    191     /**
    192      * A process can set this flag to false to prevent the use of threaded
    193      * rendering.
    194      *
    195      * @hide
    196      */
    197     public static boolean sRendererDisabled = false;
    198 
    199     /**
    200      * Further threaded renderer disabling for the system process.
    201      *
    202      * @hide
    203      */
    204     public static boolean sSystemRendererDisabled = false;
    205 
    206     /**
    207      * Invoke this method to disable threaded rendering in the current process.
    208      *
    209      * @hide
    210      */
    211     public static void disable(boolean system) {
    212         sRendererDisabled = true;
    213         if (system) {
    214             sSystemRendererDisabled = true;
    215         }
    216     }
    217 
    218     public static boolean sTrimForeground = false;
    219 
    220     /**
    221      * Controls whether or not the renderer should aggressively trim
    222      * memory. Note that this must not be set for any process that uses
    223      * WebView! This should be only used by system_process or similar
    224      * that do not go into the background.
    225      */
    226     public static void enableForegroundTrimming() {
    227         sTrimForeground = true;
    228     }
    229 
    230     private static native boolean nSupportsOpenGL();
    231     private static boolean sSupportsOpenGL = nSupportsOpenGL();
    232 
    233     /**
    234      * Indicates whether threaded rendering is available under any form for
    235      * the view hierarchy.
    236      *
    237      * @return True if the view hierarchy can potentially be defer rendered,
    238      *         false otherwise
    239      */
    240     public static boolean isAvailable() {
    241         return sSupportsOpenGL;
    242     }
    243 
    244     /**
    245      * Sets the directory to use as a persistent storage for threaded rendering
    246      * resources.
    247      *
    248      * @param cacheDir A directory the current process can write to
    249      *
    250      * @hide
    251      */
    252     public static void setupDiskCache(File cacheDir) {
    253         ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
    254     }
    255 
    256     /**
    257      * Creates a threaded renderer using OpenGL.
    258      *
    259      * @param translucent True if the surface is translucent, false otherwise
    260      *
    261      * @return A threaded renderer backed by OpenGL.
    262      */
    263     public static ThreadedRenderer create(Context context, boolean translucent, String name) {
    264         ThreadedRenderer renderer = null;
    265         if (isAvailable()) {
    266             renderer = new ThreadedRenderer(context, translucent, name);
    267         }
    268         return renderer;
    269     }
    270 
    271     /**
    272      * Invoke this method when the system is running out of memory. This
    273      * method will attempt to recover as much memory as possible, based on
    274      * the specified hint.
    275      *
    276      * @param level Hint about the amount of memory that should be trimmed,
    277      *              see {@link android.content.ComponentCallbacks}
    278      */
    279     public static void trimMemory(int level) {
    280         nTrimMemory(level);
    281     }
    282 
    283     public static void overrideProperty(@NonNull String name, @NonNull String value) {
    284         if (name == null || value == null) {
    285             throw new IllegalArgumentException("name and value must be non-null");
    286         }
    287         nOverrideProperty(name, value);
    288     }
    289 
    290     // Keep in sync with DrawFrameTask.h SYNC_* flags
    291     // Nothing interesting to report
    292     private static final int SYNC_OK = 0;
    293     // Needs a ViewRoot invalidate
    294     private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
    295     // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
    296     private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
    297     // setStopped is true, drawing is false
    298     // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
    299     // This flag isn't really used as there's nothing that we care to do
    300     // in response, so it really just exists to differentiate from LOST_SURFACE
    301     // but possibly both can just be deleted.
    302     private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
    303 
    304     private static final String[] VISUALIZERS = {
    305         PROFILE_PROPERTY_VISUALIZE_BARS,
    306     };
    307 
    308     private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
    309     private static final int FLAG_DUMP_RESET        = 1 << 1;
    310 
    311     @IntDef(flag = true, value = {
    312             FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET })
    313     @Retention(RetentionPolicy.SOURCE)
    314     public @interface DumpFlags {}
    315 
    316     // Size of the rendered content.
    317     private int mWidth, mHeight;
    318 
    319     // Actual size of the drawing surface.
    320     private int mSurfaceWidth, mSurfaceHeight;
    321 
    322     // Insets between the drawing surface and rendered content. These are
    323     // applied as translation when updating the root render node.
    324     private int mInsetTop, mInsetLeft;
    325 
    326     // Whether the surface has insets. Used to protect opacity.
    327     private boolean mHasInsets;
    328 
    329     // Light and shadow properties specified by the theme.
    330     private final float mLightY;
    331     private final float mLightZ;
    332     private final float mLightRadius;
    333     private final int mAmbientShadowAlpha;
    334     private final int mSpotShadowAlpha;
    335 
    336     private long mNativeProxy;
    337     private boolean mInitialized = false;
    338     private RenderNode mRootNode;
    339     private Choreographer mChoreographer;
    340     private boolean mRootNodeNeedsUpdate;
    341 
    342     private boolean mEnabled;
    343     private boolean mRequested = true;
    344     private boolean mIsOpaque = false;
    345 
    346     ThreadedRenderer(Context context, boolean translucent, String name) {
    347         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
    348         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
    349         mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
    350         mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
    351         mAmbientShadowAlpha =
    352                 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
    353         mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
    354         a.recycle();
    355 
    356         long rootNodePtr = nCreateRootRenderNode();
    357         mRootNode = RenderNode.adopt(rootNodePtr);
    358         mRootNode.setClipToBounds(false);
    359         mIsOpaque = !translucent;
    360         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
    361         nSetName(mNativeProxy, name);
    362 
    363         ProcessInitializer.sInstance.init(context, mNativeProxy);
    364 
    365         loadSystemProperties();
    366     }
    367 
    368     /**
    369      * Destroys the threaded rendering context.
    370      */
    371     void destroy() {
    372         mInitialized = false;
    373         updateEnabledState(null);
    374         nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
    375     }
    376 
    377     /**
    378      * Indicates whether threaded rendering is currently enabled.
    379      *
    380      * @return True if threaded rendering  is in use, false otherwise.
    381      */
    382     boolean isEnabled() {
    383         return mEnabled;
    384     }
    385 
    386     /**
    387      * Indicates whether threaded rendering  is currently enabled.
    388      *
    389      * @param enabled True if the threaded renderer is in use, false otherwise.
    390      */
    391     void setEnabled(boolean enabled) {
    392         mEnabled = enabled;
    393     }
    394 
    395     /**
    396      * Indicates whether threaded rendering is currently request but not
    397      * necessarily enabled yet.
    398      *
    399      * @return True if requested, false otherwise.
    400      */
    401     boolean isRequested() {
    402         return mRequested;
    403     }
    404 
    405     /**
    406      * Indicates whether threaded rendering is currently requested but not
    407      * necessarily enabled yet.
    408      *
    409      * @return True to request threaded rendering, false otherwise.
    410      */
    411     void setRequested(boolean requested) {
    412         mRequested = requested;
    413     }
    414 
    415     private void updateEnabledState(Surface surface) {
    416         if (surface == null || !surface.isValid()) {
    417             setEnabled(false);
    418         } else {
    419             setEnabled(mInitialized);
    420         }
    421     }
    422 
    423     /**
    424      * Initializes the threaded renderer for the specified surface.
    425      *
    426      * @param surface The surface to render
    427      *
    428      * @return True if the initialization was successful, false otherwise.
    429      */
    430     boolean initialize(Surface surface) throws OutOfResourcesException {
    431         boolean status = !mInitialized;
    432         mInitialized = true;
    433         updateEnabledState(surface);
    434         nInitialize(mNativeProxy, surface);
    435         return status;
    436     }
    437 
    438     /**
    439      * Initializes the threaded renderer for the specified surface and setup the
    440      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
    441      * potentially lost the threaded renderer. The threaded renderer should be
    442      * reinitialized and setup when the render {@link #isRequested()} and
    443      * {@link #isEnabled()}.
    444      *
    445      * @param width The width of the drawing surface.
    446      * @param height The height of the drawing surface.
    447      * @param attachInfo Information about the window.
    448      * @param surface The surface to render
    449      * @param surfaceInsets The drawing surface insets to apply
    450      *
    451      * @return true if the surface was initialized, false otherwise. Returning
    452      *         false might mean that the surface was already initialized.
    453      */
    454     boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
    455             Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
    456         if (isRequested()) {
    457             // We lost the gl context, so recreate it.
    458             if (!isEnabled()) {
    459                 if (initialize(surface)) {
    460                     setup(width, height, attachInfo, surfaceInsets);
    461                     return true;
    462                 }
    463             }
    464         }
    465         return false;
    466     }
    467 
    468     /**
    469      * Updates the threaded renderer for the specified surface.
    470      *
    471      * @param surface The surface to render
    472      */
    473     void updateSurface(Surface surface) throws OutOfResourcesException {
    474         updateEnabledState(surface);
    475         nUpdateSurface(mNativeProxy, surface);
    476     }
    477 
    478     /**
    479      * Halts any current rendering into the surface. Use this if it is unclear whether
    480      * or not the surface used by the ThreadedRenderer will be changing. It
    481      * Suspends any rendering into the surface, but will not do any destruction.
    482      *
    483      * Any subsequent draws will override the pause, resuming normal operation.
    484      */
    485     boolean pauseSurface(Surface surface) {
    486         return nPauseSurface(mNativeProxy, surface);
    487     }
    488 
    489     /**
    490      * Hard stops or resumes rendering into the surface. This flag is used to
    491      * determine whether or not it is safe to use the given surface *at all*
    492      */
    493     void setStopped(boolean stopped) {
    494         nSetStopped(mNativeProxy, stopped);
    495     }
    496 
    497     /**
    498      * Destroys all hardware rendering resources associated with the specified
    499      * view hierarchy.
    500      *
    501      * @param view The root of the view hierarchy
    502      */
    503     void destroyHardwareResources(View view) {
    504         destroyResources(view);
    505         nDestroyHardwareResources(mNativeProxy);
    506     }
    507 
    508     private static void destroyResources(View view) {
    509         view.destroyHardwareResources();
    510     }
    511 
    512     /**
    513      * Detaches the layer's surface texture from the GL context and releases
    514      * the texture id
    515      */
    516     void detachSurfaceTexture(long hardwareLayer) {
    517         nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
    518     }
    519 
    520     /**
    521      * Sets up the renderer for drawing.
    522      *
    523      * @param width The width of the drawing surface.
    524      * @param height The height of the drawing surface.
    525      * @param attachInfo Information about the window.
    526      * @param surfaceInsets The drawing surface insets to apply
    527      */
    528     void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
    529         mWidth = width;
    530         mHeight = height;
    531 
    532         if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
    533                 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
    534             mHasInsets = true;
    535             mInsetLeft = surfaceInsets.left;
    536             mInsetTop = surfaceInsets.top;
    537             mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
    538             mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
    539 
    540             // If the surface has insets, it can't be opaque.
    541             setOpaque(false);
    542         } else {
    543             mHasInsets = false;
    544             mInsetLeft = 0;
    545             mInsetTop = 0;
    546             mSurfaceWidth = width;
    547             mSurfaceHeight = height;
    548         }
    549 
    550         mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
    551         nSetup(mNativeProxy, mLightRadius,
    552                 mAmbientShadowAlpha, mSpotShadowAlpha);
    553 
    554         setLightCenter(attachInfo);
    555     }
    556 
    557     /**
    558      * Updates the light position based on the position of the window.
    559      *
    560      * @param attachInfo Information about the window.
    561      */
    562     void setLightCenter(AttachInfo attachInfo) {
    563         // Adjust light position for window offsets.
    564         final Point displaySize = attachInfo.mPoint;
    565         attachInfo.mDisplay.getRealSize(displaySize);
    566         final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
    567         final float lightY = mLightY - attachInfo.mWindowTop;
    568 
    569         nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
    570     }
    571 
    572     /**
    573      * Change the ThreadedRenderer's opacity
    574      */
    575     void setOpaque(boolean opaque) {
    576         mIsOpaque = opaque && !mHasInsets;
    577         nSetOpaque(mNativeProxy, mIsOpaque);
    578     }
    579 
    580     boolean isOpaque() {
    581         return mIsOpaque;
    582     }
    583 
    584     /**
    585      * Gets the current width of the surface. This is the width that the surface
    586      * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
    587      *
    588      * @return the current width of the surface
    589      */
    590     int getWidth() {
    591         return mWidth;
    592     }
    593 
    594     /**
    595      * Gets the current height of the surface. This is the height that the surface
    596      * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
    597      *
    598      * @return the current width of the surface
    599      */
    600     int getHeight() {
    601         return mHeight;
    602     }
    603 
    604     /**
    605      * Outputs extra debugging information in the specified file descriptor.
    606      */
    607     void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
    608         pw.flush();
    609         int flags = 0;
    610         for (int i = 0; i < args.length; i++) {
    611             switch (args[i]) {
    612                 case "framestats":
    613                     flags |= FLAG_DUMP_FRAMESTATS;
    614                     break;
    615                 case "reset":
    616                     flags |= FLAG_DUMP_RESET;
    617                     break;
    618             }
    619         }
    620         nDumpProfileInfo(mNativeProxy, fd, flags);
    621     }
    622 
    623     /**
    624      * Loads system properties used by the renderer. This method is invoked
    625      * whenever system properties are modified. Implementations can use this
    626      * to trigger live updates of the renderer based on properties.
    627      *
    628      * @return True if a property has changed.
    629      */
    630     boolean loadSystemProperties() {
    631         boolean changed = nLoadSystemProperties(mNativeProxy);
    632         if (changed) {
    633             invalidateRoot();
    634         }
    635         return changed;
    636     }
    637 
    638     private void updateViewTreeDisplayList(View view) {
    639         view.mPrivateFlags |= View.PFLAG_DRAWN;
    640         view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
    641                 == View.PFLAG_INVALIDATED;
    642         view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
    643         view.updateDisplayListIfDirty();
    644         view.mRecreateDisplayList = false;
    645     }
    646 
    647     private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
    648         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
    649         updateViewTreeDisplayList(view);
    650 
    651         if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
    652             DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
    653             try {
    654                 final int saveCount = canvas.save();
    655                 canvas.translate(mInsetLeft, mInsetTop);
    656                 callbacks.onPreDraw(canvas);
    657 
    658                 canvas.insertReorderBarrier();
    659                 canvas.drawRenderNode(view.updateDisplayListIfDirty());
    660                 canvas.insertInorderBarrier();
    661 
    662                 callbacks.onPostDraw(canvas);
    663                 canvas.restoreToCount(saveCount);
    664                 mRootNodeNeedsUpdate = false;
    665             } finally {
    666                 mRootNode.end(canvas);
    667             }
    668         }
    669         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    670     }
    671 
    672     /**
    673      * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
    674      * rendernode of the UI thread.
    675      * @param node The node to add.
    676      * @param placeFront If true, the render node will be placed in front of the content node,
    677      *                   otherwise behind the content node.
    678      */
    679     public void addRenderNode(RenderNode node, boolean placeFront) {
    680         nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
    681     }
    682 
    683     /**
    684      * Only especially added render nodes can be removed.
    685      * @param node The node which was added via addRenderNode which should get removed again.
    686      */
    687     public void removeRenderNode(RenderNode node) {
    688         nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
    689     }
    690 
    691     /**
    692      * Draws a particular render node. If the node is not the content node, only the additional
    693      * nodes will get drawn and the content remains untouched.
    694      * @param node The node to be drawn.
    695      */
    696     public void drawRenderNode(RenderNode node) {
    697         nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
    698     }
    699 
    700     /**
    701      * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
    702      * will be prevented to overdraw this area. It will be synchronized with the draw call.
    703      * This should be updated in the content view's draw call.
    704      * @param left The left side of the protected bounds.
    705      * @param top The top side of the protected bounds.
    706      * @param right The right side of the protected bounds.
    707      * @param bottom The bottom side of the protected bounds.
    708      */
    709     public void setContentDrawBounds(int left, int top, int right, int bottom) {
    710         nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
    711     }
    712 
    713     /**
    714      * Interface used to receive callbacks whenever a view is drawn by
    715      * a threaded renderer instance.
    716      */
    717     interface DrawCallbacks {
    718         /**
    719          * Invoked before a view is drawn by a threaded renderer.
    720          * This method can be used to apply transformations to the
    721          * canvas but no drawing command should be issued.
    722          *
    723          * @param canvas The Canvas used to render the view.
    724          */
    725         void onPreDraw(DisplayListCanvas canvas);
    726 
    727         /**
    728          * Invoked after a view is drawn by a threaded renderer.
    729          * It is safe to invoke drawing commands from this method.
    730          *
    731          * @param canvas The Canvas used to render the view.
    732          */
    733         void onPostDraw(DisplayListCanvas canvas);
    734     }
    735 
    736     /**
    737      *  Indicates that the content drawn by DrawCallbacks needs to
    738      *  be updated, which will be done by the next call to draw()
    739      */
    740     void invalidateRoot() {
    741         mRootNodeNeedsUpdate = true;
    742     }
    743 
    744     /**
    745      * Draws the specified view.
    746      *
    747      * @param view The view to draw.
    748      * @param attachInfo AttachInfo tied to the specified view.
    749      * @param callbacks Callbacks invoked when drawing happens.
    750      */
    751     void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
    752         attachInfo.mIgnoreDirtyState = true;
    753 
    754         final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
    755         choreographer.mFrameInfo.markDrawStart();
    756 
    757         updateRootDisplayList(view, callbacks);
    758 
    759         attachInfo.mIgnoreDirtyState = false;
    760 
    761         // register animating rendernodes which started animating prior to renderer
    762         // creation, which is typical for animators started prior to first draw
    763         if (attachInfo.mPendingAnimatingRenderNodes != null) {
    764             final int count = attachInfo.mPendingAnimatingRenderNodes.size();
    765             for (int i = 0; i < count; i++) {
    766                 registerAnimatingRenderNode(
    767                         attachInfo.mPendingAnimatingRenderNodes.get(i));
    768             }
    769             attachInfo.mPendingAnimatingRenderNodes.clear();
    770             // We don't need this anymore as subsequent calls to
    771             // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
    772             attachInfo.mPendingAnimatingRenderNodes = null;
    773         }
    774 
    775         final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
    776         int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
    777         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
    778             setEnabled(false);
    779             attachInfo.mViewRootImpl.mSurface.release();
    780             // Invalidate since we failed to draw. This should fetch a Surface
    781             // if it is still needed or do nothing if we are no longer drawing
    782             attachInfo.mViewRootImpl.invalidate();
    783         }
    784         if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
    785             attachInfo.mViewRootImpl.invalidate();
    786         }
    787     }
    788 
    789     static void invokeFunctor(long functor, boolean waitForCompletion) {
    790         nInvokeFunctor(functor, waitForCompletion);
    791     }
    792 
    793     /**
    794      * Creates a new hardware layer. A hardware layer built by calling this
    795      * method will be treated as a texture layer, instead of as a render target.
    796      *
    797      * @return A hardware layer
    798      */
    799     HardwareLayer createTextureLayer() {
    800         long layer = nCreateTextureLayer(mNativeProxy);
    801         return HardwareLayer.adoptTextureLayer(this, layer);
    802     }
    803 
    804 
    805     void buildLayer(RenderNode node) {
    806         nBuildLayer(mNativeProxy, node.getNativeDisplayList());
    807     }
    808 
    809 
    810     boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
    811         return nCopyLayerInto(mNativeProxy,
    812                 layer.getDeferredLayerUpdater(), bitmap);
    813     }
    814 
    815     /**
    816      * Indicates that the specified hardware layer needs to be updated
    817      * as soon as possible.
    818      *
    819      * @param layer The hardware layer that needs an update
    820      */
    821     void pushLayerUpdate(HardwareLayer layer) {
    822         nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
    823     }
    824 
    825     /**
    826      * Tells the HardwareRenderer that the layer is destroyed. The renderer
    827      * should remove the layer from any update queues.
    828      */
    829     void onLayerDestroyed(HardwareLayer layer) {
    830         nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
    831     }
    832 
    833     /**
    834      * Blocks until all previously queued work has completed.
    835      */
    836     void fence() {
    837         nFence(mNativeProxy);
    838     }
    839 
    840     /**
    841      * Prevents any further drawing until draw() is called. This is a signal
    842      * that the contents of the RenderNode tree are no longer safe to play back.
    843      * In practice this usually means that there are Functor pointers in the
    844      * display list that are no longer valid.
    845      */
    846     void stopDrawing() {
    847         nStopDrawing(mNativeProxy);
    848     }
    849 
    850     /**
    851      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
    852      */
    853     public void notifyFramePending() {
    854         nNotifyFramePending(mNativeProxy);
    855     }
    856 
    857 
    858     void registerAnimatingRenderNode(RenderNode animator) {
    859         nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
    860     }
    861 
    862     void registerVectorDrawableAnimator(
    863         AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
    864         nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
    865                 animator.getAnimatorNativePtr());
    866     }
    867 
    868     public void serializeDisplayListTree() {
    869         nSerializeDisplayListTree(mNativeProxy);
    870     }
    871 
    872     public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
    873         if (srcRect == null) {
    874             // Empty rect means entire surface
    875             return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
    876         } else {
    877             return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
    878                     srcRect.right, srcRect.bottom, bitmap);
    879         }
    880     }
    881 
    882     /**
    883      * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
    884      * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
    885      * not the RenderNode from a View.
    886      **/
    887     public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
    888         return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height);
    889     }
    890 
    891     @Override
    892     protected void finalize() throws Throwable {
    893         try {
    894             nDeleteProxy(mNativeProxy);
    895             mNativeProxy = 0;
    896         } finally {
    897             super.finalize();
    898         }
    899     }
    900 
    901     private static class ProcessInitializer {
    902         static ProcessInitializer sInstance = new ProcessInitializer();
    903 
    904         private boolean mInitialized = false;
    905 
    906         private Context mAppContext;
    907         private IGraphicsStats mGraphicsStatsService;
    908         private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
    909             @Override
    910             public void onRotateGraphicsStatsBuffer() throws RemoteException {
    911                 rotateBuffer();
    912             }
    913         };
    914 
    915         private ProcessInitializer() {}
    916 
    917         synchronized void init(Context context, long renderProxy) {
    918             if (mInitialized) return;
    919             mInitialized = true;
    920             mAppContext = context.getApplicationContext();
    921             initSched(context, renderProxy);
    922             initGraphicsStats();
    923         }
    924 
    925         private void initSched(Context context, long renderProxy) {
    926             try {
    927                 int tid = nGetRenderThreadTid(renderProxy);
    928                 ActivityManager.getService().setRenderThread(tid);
    929             } catch (Throwable t) {
    930                 Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
    931             }
    932         }
    933 
    934         private void initGraphicsStats() {
    935             try {
    936                 IBinder binder = ServiceManager.getService("graphicsstats");
    937                 if (binder == null) return;
    938                 mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
    939                 requestBuffer();
    940             } catch (Throwable t) {
    941                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
    942             }
    943         }
    944 
    945         private void rotateBuffer() {
    946             nRotateProcessStatsBuffer();
    947             requestBuffer();
    948         }
    949 
    950         private void requestBuffer() {
    951             try {
    952                 final String pkg = mAppContext.getApplicationInfo().packageName;
    953                 ParcelFileDescriptor pfd = mGraphicsStatsService
    954                         .requestBufferForProcess(pkg, mGraphicsStatsCallback);
    955                 nSetProcessStatsBuffer(pfd.getFd());
    956                 pfd.close();
    957             } catch (Throwable t) {
    958                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
    959             }
    960         }
    961     }
    962 
    963     void addFrameMetricsObserver(FrameMetricsObserver observer) {
    964         long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
    965         observer.mNative = new VirtualRefBasePtr(nativeObserver);
    966     }
    967 
    968     void removeFrameMetricsObserver(FrameMetricsObserver observer) {
    969         nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
    970         observer.mNative = null;
    971     }
    972 
    973     /** Not actually public - internal use only. This doc to make lint happy */
    974     public static native void disableVsync();
    975 
    976     static native void setupShadersDiskCache(String cacheFile);
    977 
    978     private static native void nRotateProcessStatsBuffer();
    979     private static native void nSetProcessStatsBuffer(int fd);
    980     private static native int nGetRenderThreadTid(long nativeProxy);
    981 
    982     private static native long nCreateRootRenderNode();
    983     private static native long nCreateProxy(boolean translucent, long rootRenderNode);
    984     private static native void nDeleteProxy(long nativeProxy);
    985 
    986     private static native boolean nLoadSystemProperties(long nativeProxy);
    987     private static native void nSetName(long nativeProxy, String name);
    988 
    989     private static native void nInitialize(long nativeProxy, Surface window);
    990     private static native void nUpdateSurface(long nativeProxy, Surface window);
    991     private static native boolean nPauseSurface(long nativeProxy, Surface window);
    992     private static native void nSetStopped(long nativeProxy, boolean stopped);
    993     private static native void nSetup(long nativeProxy,
    994             float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
    995     private static native void nSetLightCenter(long nativeProxy,
    996             float lightX, float lightY, float lightZ);
    997     private static native void nSetOpaque(long nativeProxy, boolean opaque);
    998     private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
    999     private static native void nDestroy(long nativeProxy, long rootRenderNode);
   1000     private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
   1001     private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
   1002 
   1003     private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
   1004 
   1005     private static native long nCreateTextureLayer(long nativeProxy);
   1006     private static native void nBuildLayer(long nativeProxy, long node);
   1007     private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
   1008     private static native void nPushLayerUpdate(long nativeProxy, long layer);
   1009     private static native void nCancelLayerUpdate(long nativeProxy, long layer);
   1010     private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
   1011 
   1012     private static native void nDestroyHardwareResources(long nativeProxy);
   1013     private static native void nTrimMemory(int level);
   1014     private static native void nOverrideProperty(String name, String value);
   1015 
   1016     private static native void nFence(long nativeProxy);
   1017     private static native void nStopDrawing(long nativeProxy);
   1018     private static native void nNotifyFramePending(long nativeProxy);
   1019 
   1020     private static native void nSerializeDisplayListTree(long nativeProxy);
   1021 
   1022     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
   1023             @DumpFlags int dumpFlags);
   1024 
   1025     private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
   1026              boolean placeFront);
   1027     private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
   1028     private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
   1029     private static native void nSetContentDrawBounds(long nativeProxy, int left,
   1030              int top, int right, int bottom);
   1031 
   1032     private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
   1033     private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
   1034 
   1035     private static native int nCopySurfaceInto(Surface surface,
   1036             int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
   1037 
   1038     private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
   1039 }
   1040