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