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