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