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