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