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