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