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