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