1 /*
2  * Copyright (C) 2018 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.graphics;
18 
19 import android.annotation.FloatRange;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.app.Activity;
24 import android.app.ActivityManager;
25 import android.content.Context;
26 import android.content.pm.ActivityInfo;
27 import android.content.res.Configuration;
28 import android.hardware.OverlayProperties;
29 import android.hardware.display.DisplayManager;
30 import android.os.IBinder;
31 import android.os.ParcelFileDescriptor;
32 import android.os.RemoteException;
33 import android.os.ServiceManager;
34 import android.util.Log;
35 import android.util.TimeUtils;
36 import android.view.Display;
37 import android.view.Display.Mode;
38 import android.view.IGraphicsStats;
39 import android.view.IGraphicsStatsCallback;
40 import android.view.NativeVectorDrawableAnimator;
41 import android.view.PixelCopy;
42 import android.view.Surface;
43 import android.view.SurfaceControl;
44 import android.view.SurfaceHolder;
45 import android.view.animation.AnimationUtils;
46 
47 import java.io.File;
48 import java.io.FileDescriptor;
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 import java.util.concurrent.Executor;
52 
53 import sun.misc.Cleaner;
54 
55 /**
56  * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
57  * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
58  * HardwareRenderer instances as desired.</p>
59  *
60  * <h3>Resources & lifecycle</h3>
61  *
62  * <p>All HardwareRenderer instances share a common render thread. The render thread contains
63  * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
64  * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
65  * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
66  * is to have a HardwareRenderer instance for every active {@link Surface}. For example
67  * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
68  * of which may be drawing at the same time.</p>
69  *
70  * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
71  * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
72  * consumers such as {@link android.view.SurfaceView},
73  * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
74  * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
75  * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
76  * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
77  * Failure to do so will cause the render thread to stall on that surface, blocking all
78  * HardwareRenderer instances.</p>
79  */
80 public class HardwareRenderer {
81     private static final String LOG_TAG = "HardwareRenderer";
82 
83     // Keep in sync with DrawFrameTask.h SYNC_* flags
84     /**
85      * Nothing interesting to report. Sync & draw kicked off
86      */
87     public static final int SYNC_OK = 0;
88 
89     /**
90      * The renderer is requesting a redraw. This can occur if there's an animation that's running
91      * in the RenderNode tree and the hardware renderer is unable to self-animate.
92      *
93      * <p>If this is returned from syncAndDraw the expectation is that syncAndDraw
94      * will be called again on the next vsync signal.
95      */
96     public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
97 
98     /**
99      * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
100      * This can happen if {@link Surface#release()} was called. The user should no longer
101      * attempt to call syncAndDraw until a new surface has been provided by calling
102      * setSurface.
103      *
104      * <p>Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
105      */
106     public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
107 
108     /**
109      * The hardware renderer has been set to a "stopped" state. If this is returned then the
110      * rendering content has been synced, however a frame was not produced.
111      */
112     public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
113 
114     /**
115      * The content was synced but the renderer has declined to produce a frame in this vsync
116      * interval. This can happen if a frame was already drawn in this vsync or if the renderer
117      * is outrunning the frame consumer. The renderer will internally re-schedule itself
118      * to render a frame in the next vsync signal, so the caller does not need to do anything
119      * in response to this signal.
120      */
121     public static final int SYNC_FRAME_DROPPED = 1 << 3;
122 
123     /** @hide */
124     @IntDef(value = {
125             SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
126             SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
127     @Retention(RetentionPolicy.SOURCE)
128     public @interface SyncAndDrawResult {
129     }
130 
131     /** @hide */
132     public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
133     /** @hide */
134     public static final int FLAG_DUMP_RESET = 1 << 1;
135     /** @hide */
136     public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
137 
138     /** @hide */
139     @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
140             FLAG_DUMP_FRAMESTATS,
141             FLAG_DUMP_RESET
142     })
143     @Retention(RetentionPolicy.SOURCE)
144     public @interface DumpFlags {
145     }
146 
147 
148     /**
149      * Trims all Skia caches.
150      * @hide
151      */
152     public static final int CACHE_TRIM_ALL = 0;
153     /**
154      * Trims Skia font caches.
155      * @hide
156      */
157     public static final int CACHE_TRIM_FONT = 1;
158     /**
159      * Trims Skia resource caches.
160      * @hide
161      */
162     public static final int CACHE_TRIM_RESOURCES = 2;
163 
164     /** @hide */
165     @IntDef(prefix = {"CACHE_TRIM_"}, value = {
166             CACHE_TRIM_ALL,
167             CACHE_TRIM_FONT,
168             CACHE_TRIM_RESOURCES
169     })
170     @Retention(RetentionPolicy.SOURCE)
171     public @interface CacheTrimLevel {}
172 
173     /**
174      * Name of the file that holds the shaders cache.
175      */
176     private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
177     private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
178 
179     private static int sDensityDpi = 0;
180 
181     private final long mNativeProxy;
182     /** @hide */
183     protected RenderNode mRootNode;
184     private boolean mOpaque = true;
185     private boolean mForceDark = false;
186     private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT;
187     private float mDesiredSdrHdrRatio = 1f;
188 
189     /**
190      * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
191      * to opaque with no light source configured.
192      */
HardwareRenderer()193     public HardwareRenderer() {
194         ProcessInitializer.sInstance.initUsingContext();
195         mRootNode = RenderNode.adopt(nCreateRootRenderNode());
196         mRootNode.setClipToBounds(false);
197         mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
198         if (mNativeProxy == 0) {
199             throw new OutOfMemoryError("Unable to create hardware renderer");
200         }
201         Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
202         ProcessInitializer.sInstance.init(mNativeProxy);
203     }
204 
205     /**
206      * Destroys the rendering context of this HardwareRenderer. This destroys the resources
207      * associated with this renderer and releases the currently set {@link Surface}. This must
208      * be called when this HardwareRenderer is no longer needed.
209      *
210      * <p>The renderer may be restored from this state by setting a new {@link Surface}, setting
211      * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
212      * rendering by issuing a new {@link FrameRenderRequest}.
213      *
214      * <p>It is recommended to call this in response to callbacks such as
215      * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
216      *
217      * <p>Note that if there are any outstanding frame commit callbacks they may never being
218      * invoked if the frame was deferred to a later vsync.
219      */
destroy()220     public void destroy() {
221         nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
222     }
223 
224     /**
225      * Sets a name for this renderer. This is used to identify this renderer instance
226      * when reporting debug information such as the per-window frame time metrics
227      * reported by 'adb shell dumpsys gfxinfo [package] framestats'
228      *
229      * @param name The debug name to use for this HardwareRenderer instance
230      */
setName(@onNull String name)231     public void setName(@NonNull String name) {
232         nSetName(mNativeProxy, name);
233     }
234 
235     /**
236      * Sets the center of the light source. The light source point controls the directionality
237      * and shape of shadows rendered by RenderNode Z & elevation.
238      *
239      * <p>The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
240      * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
241      *
242      * <p>The light source should be setup both as part of initial configuration, and whenever
243      * the window moves to ensure the light source stays anchored in display space instead
244      * of in window space.
245      *
246      * <p>This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
247      * before shadows will work.
248      *
249      * @param lightX      The X position of the light source
250      * @param lightY      The Y position of the light source
251      * @param lightZ      The Z position of the light source. Must be >= 0.
252      * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
253      *                    larger radius will have softer shadows.
254      */
setLightSourceGeometry(float lightX, float lightY, float lightZ, float lightRadius)255     public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
256             float lightRadius) {
257         validateFinite(lightX, "lightX");
258         validateFinite(lightY, "lightY");
259         validatePositive(lightZ, "lightZ");
260         validatePositive(lightRadius, "lightRadius");
261         nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
262     }
263 
264     /**
265      * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
266      * has max alpha, and ramps down from the values provided to zero.
267      *
268      * <p>These values are typically provided by the current theme, see
269      * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
270      *
271      * <p>This must be set at least once along with
272      * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
273      *
274      * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
275      *                           is 0.039f.
276      * @param spotShadowAlpha    The alpha for the spot shadow. If unsure, a reasonable default is
277      *                           0.19f.
278      */
setLightSourceAlpha(@loatRangefrom = 0.0f, to = 1.0f) float ambientShadowAlpha, @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha)279     public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
280             @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
281         validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
282         validateAlpha(spotShadowAlpha, "spotShadowAlpha");
283         nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
284     }
285 
286     /**
287      * Sets the content root to render. It is not necessary to call this whenever the content
288      * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
289      * contained within the content node, will be applied whenever a new {@link FrameRenderRequest}
290      * is issued via {@link #createRenderRequest()} and {@link FrameRenderRequest#syncAndDraw()}.
291      *
292      * @param content The content to set as the root RenderNode. If null the content root is removed
293      *                and the renderer will draw nothing.
294      */
setContentRoot(@ullable RenderNode content)295     public void setContentRoot(@Nullable RenderNode content) {
296         RecordingCanvas canvas = mRootNode.beginRecording();
297         if (content != null) {
298             canvas.drawRenderNode(content);
299         }
300         mRootNode.endRecording();
301     }
302 
303     /**
304      * <p>The surface to render into. The surface is assumed to be associated with the display and
305      * as such is still driven by vsync signals such as those from
306      * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
307      * the display's (typically 60hz).</p>
308      *
309      * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
310      * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
311      * consumers such as {@link android.view.SurfaceView},
312      * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
313      * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
314      * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
315      * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
316      * Failure to do so will cause the render thread to stall on that surface, blocking all
317      * HardwareRenderer instances.</p>
318      *
319      * @param surface The surface to render into. If null then rendering will be stopped. If
320      *                non-null then {@link Surface#isValid()} must be true.
321      */
setSurface(@ullable Surface surface)322     public void setSurface(@Nullable Surface surface) {
323         setSurface(surface, false);
324     }
325 
326     /**
327      * See {@link #setSurface(Surface)}
328      *
329      * @hide
330      * @param discardBuffer determines whether the surface will attempt to preserve its contents
331      *                      between frames.  If set to true the renderer will attempt to preserve
332      *                      the contents of the buffer between frames if the implementation allows
333      *                      it.  If set to false no attempt will be made to preserve the buffer's
334      *                      contents between frames.
335      */
setSurface(@ullable Surface surface, boolean discardBuffer)336     public void setSurface(@Nullable Surface surface, boolean discardBuffer) {
337         if (surface != null && !surface.isValid()) {
338             throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
339         }
340         nSetSurface(mNativeProxy, surface, discardBuffer);
341     }
342 
343     /**
344      * Sets the SurfaceControl to be used internally inside render thread
345      * @hide
346      * @param surfaceControl The surface control to pass to render thread in hwui.
347      *        If null, any previous references held in render thread will be discarded.
348     */
setSurfaceControl(@ullable SurfaceControl surfaceControl, @Nullable BLASTBufferQueue blastBufferQueue)349     public void setSurfaceControl(@Nullable SurfaceControl surfaceControl,
350             @Nullable BLASTBufferQueue blastBufferQueue) {
351         nSetSurfaceControl(mNativeProxy, surfaceControl != null ? surfaceControl.mNativeObject : 0);
352     }
353 
354     /**
355      * Sets the parameters that can be used to control a render request for a
356      * {@link HardwareRenderer}. This is not thread-safe and must not be held on to for longer
357      * than a single frame request.
358      */
359     public final class FrameRenderRequest {
360         private FrameInfo mFrameInfo = new FrameInfo();
361         private boolean mWaitForPresent;
362 
FrameRenderRequest()363         private FrameRenderRequest() { }
364 
reset()365         private void reset() {
366             mWaitForPresent = false;
367             // Default to the animation time which, if choreographer is in play, will default to the
368             // current vsync time. Otherwise it will be 'now'.
369             mRenderRequest.setVsyncTime(
370                     AnimationUtils.currentAnimationTimeMillis() * TimeUtils.NANOS_PER_MS);
371         }
372 
373         /** @hide */
setFrameInfo(FrameInfo info)374         public void setFrameInfo(FrameInfo info) {
375             System.arraycopy(info.frameInfo, 0, mFrameInfo.frameInfo, 0, info.frameInfo.length);
376         }
377 
378         /**
379          * Sets the vsync time that represents the start point of this frame. Typically this
380          * comes from {@link android.view.Choreographer.FrameCallback}. Other compatible time
381          * sources include {@link System#nanoTime()}, however if the result is being displayed
382          * on-screen then using {@link android.view.Choreographer} is strongly recommended to
383          * ensure smooth animations.
384          *
385          * <p>If the clock source is not from a CLOCK_MONOTONIC source then any animations driven
386          * directly by RenderThread will not be synchronized properly with the current frame.
387          *
388          * @param vsyncTime The vsync timestamp for this frame. The timestamp is in nanoseconds
389          *                  and should come from a CLOCK_MONOTONIC source.
390          *
391          * @return this instance
392          */
setVsyncTime(long vsyncTime)393         public @NonNull FrameRenderRequest setVsyncTime(long vsyncTime) {
394             // TODO(b/168552873): populate vsync Id once available to Choreographer public API
395             mFrameInfo.setVsync(vsyncTime, vsyncTime, FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE,
396                     vsyncTime, -1);
397             mFrameInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
398             return this;
399         }
400 
401         /**
402          * Adds a frame commit callback. This callback will be invoked when the current rendering
403          * content has been rendered into a frame and submitted to the swap chain. The frame may
404          * not currently be visible on the display when this is invoked, but it has been submitted.
405          * This callback is useful in combination with {@link PixelCopy} to capture the current
406          * rendered content of the UI reliably.
407          *
408          * @param executor The executor to run the callback on. It is strongly recommended that
409          *                 this executor post to a different thread, as the calling thread is
410          *                 highly sensitive to being blocked.
411          * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
412          *                            Will be invoked on the given {@link Executor}.
413          *
414          * @return this instance
415          */
setFrameCommitCallback(@onNull Executor executor, @NonNull Runnable frameCommitCallback)416         public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
417                 @NonNull Runnable frameCommitCallback) {
418             nSetFrameCommitCallback(mNativeProxy,
419                     didProduceBuffer -> executor.execute(frameCommitCallback));
420             return this;
421         }
422 
423         /**
424          * Sets whether or not {@link #syncAndDraw()} should block until the frame has been
425          * presented. If this is true and {@link #syncAndDraw()} does not return
426          * {@link #SYNC_FRAME_DROPPED} or an error then when {@link #syncAndDraw()} has returned
427          * the frame has been submitted to the {@link Surface}. The default and typically
428          * recommended value is false, as blocking for present will prevent pipelining from
429          * happening, reducing overall throughput. This is useful for situations such as
430          * {@link SurfaceHolder.Callback2#surfaceRedrawNeeded(SurfaceHolder)} where it is desired
431          * to block until a frame has been presented to ensure first-frame consistency with
432          * other Surfaces.
433          *
434          * @param shouldWait If true the next call to {@link #syncAndDraw()} will block until
435          *                   completion.
436          * @return this instance
437          */
setWaitForPresent(boolean shouldWait)438         public @NonNull FrameRenderRequest setWaitForPresent(boolean shouldWait) {
439             mWaitForPresent = shouldWait;
440             return this;
441         }
442 
443         /**
444          * Syncs the RenderNode tree to the render thread and requests a frame to be drawn. This
445          * {@link FrameRenderRequest} instance should no longer be used after calling this method.
446          * The system internally may reuse instances of {@link FrameRenderRequest} to reduce
447          * allocation churn.
448          *
449          * @return The result of the sync operation.
450          */
451         @SyncAndDrawResult
syncAndDraw()452         public int syncAndDraw() {
453             int syncResult = syncAndDrawFrame(mFrameInfo);
454             if (mWaitForPresent && (syncResult & SYNC_FRAME_DROPPED) == 0) {
455                 fence();
456             }
457             return syncResult;
458         }
459     }
460 
461     private FrameRenderRequest mRenderRequest = new FrameRenderRequest();
462 
463     /**
464      * Returns a {@link FrameRenderRequest} that can be used to render a new frame. This is used
465      * to synchronize the RenderNode content provided by {@link #setContentRoot(RenderNode)} with
466      * the RenderThread and then renders a single frame to the Surface set with
467      * {@link #setSurface(Surface)}.
468      *
469      * @return An instance of {@link FrameRenderRequest}. The instance may be reused for every
470      * frame, so the caller should not hold onto it for longer than a single render request.
471      */
createRenderRequest()472     public @NonNull FrameRenderRequest createRenderRequest() {
473         mRenderRequest.reset();
474         return mRenderRequest;
475     }
476 
477     /**
478      * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
479      *
480      * @hide
481      */
482     @SyncAndDrawResult
syncAndDrawFrame(@onNull FrameInfo frameInfo)483     public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
484         return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
485     }
486 
487     /**
488      * Suspends any current rendering into the surface but do not do any destruction. This
489      * is useful to temporarily suspend using the active Surface in order to do any Surface
490      * mutations necessary.
491      *
492      * <p>Any subsequent draws will override the pause, resuming normal operation.
493      *
494      * @return true if there was an outstanding render request, false otherwise. If this is true
495      * the caller should ensure that {@link #createRenderRequest()}
496      * and {@link FrameRenderRequest#syncAndDraw()} is called at the soonest
497      * possible time to resume normal operation.
498      *
499      * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
500      * Surface before getting a new one. However things like SurfaceView will ensure that
501      * the old surface remains un-destroyed until after a new frame has been produced with
502      * the new surface.
503      * @hide
504      */
pause()505     public boolean pause() {
506         return nPause(mNativeProxy);
507     }
508 
509     /**
510      * Hard stops rendering into the surface. If the renderer is stopped it will
511      * block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
512      * still sync over the latest rendering content, however they will not render and instead
513      * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
514      *
515      * <p>If false is passed then rendering will resume as normal. Any pending rendering requests
516      * will produce a new frame at the next vsync signal.
517      *
518      * <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}
519      * and {@link Activity#onStart()}.
520      *
521      * @param stopped true to stop all rendering, false to resume
522      * @hide
523      */
setStopped(boolean stopped)524     public void setStopped(boolean stopped) {
525         nSetStopped(mNativeProxy, stopped);
526     }
527 
528     /**
529      * Hard stops rendering into the surface. If the renderer is stopped it will
530      * block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
531      * still sync over the latest rendering content, however they will not render and instead
532      * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
533      *
534      * <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}.
535      * See {@link #start()} for resuming rendering.
536      */
stop()537     public void stop() {
538         nSetStopped(mNativeProxy, true);
539     }
540 
541     /**
542      * Resumes rendering into the surface. Any pending rendering requests
543      * will produce a new frame at the next vsync signal.
544      *
545      * <p>This is useful in combination with lifecycle events such as {@link Activity#onStart()}.
546      * See {@link #stop()} for stopping rendering.
547      */
start()548     public void start() {
549         nSetStopped(mNativeProxy, false);
550     }
551 
552     /**
553      * Destroys all the display lists associated with the current rendering content.
554      * This includes releasing a reference to the current content root RenderNode. It will
555      * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
556      * rendering after calling this, along with re-recording the display lists for the
557      * RenderNode tree.
558      *
559      * <p>It is recommended, but not necessary, to use this in combination with lifecycle events
560      * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
561      * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
562      * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
563      *
564      * See also {@link #stop()}.
565      */
clearContent()566     public void clearContent() {
567         nDestroyHardwareResources(mNativeProxy);
568     }
569 
570     /**
571      * Whether or not the force-dark feature should be used for this renderer.
572      * @hide
573      */
setForceDark(boolean enable)574     public boolean setForceDark(boolean enable) {
575         if (mForceDark != enable) {
576             mForceDark = enable;
577             nSetForceDark(mNativeProxy, enable);
578             return true;
579         }
580         return false;
581     }
582 
583     /**
584      * Allocate buffers ahead of time to avoid allocation delays during rendering.
585      *
586      * <p>Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
587      * memory usage of Surfaces that render rarely or never hit triple buffering. However
588      * for UI it can result in a slight bit of jank on first launch. This hint will
589      * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
590      * necessary for typical rendering.
591      *
592      * <p>Must be called after a {@link Surface} has been set.
593      *
594      * TODO: Figure out if we even need/want this. Should HWUI just be doing this in response
595      * to setSurface anyway? Vulkan swapchain makes this murky, so delay making it public
596      * @hide
597      */
allocateBuffers()598     public void allocateBuffers() {
599         nAllocateBuffers(mNativeProxy);
600     }
601 
602     /**
603      * Notifies the hardware renderer that a call to {@link FrameRenderRequest#syncAndDraw()} will
604      * be coming soon. This is used to help schedule when RenderThread-driven animations will
605      * happen as the renderer wants to avoid producing more than one frame per vsync signal.
606      */
notifyFramePending()607     public void notifyFramePending() {
608         nNotifyFramePending(mNativeProxy);
609     }
610 
611     /**
612      * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
613      *
614      * <p>If the renderer is set to opaque it is the app's responsibility to ensure that the
615      * content renders to every pixel of the Surface, otherwise corruption may result. Note that
616      * this includes ensuring that the first draw of any given pixel does not attempt to blend
617      * against the destination. If this is false then the hardware renderer will clear to
618      * transparent at the start of every frame.
619      *
620      * @param opaque true if the content rendered is opaque, false if the renderer should clear
621      *               to transparent before rendering
622      */
setOpaque(boolean opaque)623     public void setOpaque(boolean opaque) {
624         if (mOpaque != opaque) {
625             mOpaque = opaque;
626             nSetOpaque(mNativeProxy, mOpaque);
627         }
628     }
629 
630     /**
631      * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
632      *
633      * @return true if the renderer is opaque, false otherwise
634      */
isOpaque()635     public boolean isOpaque() {
636         return mOpaque;
637     }
638 
639     /** @hide */
setFrameCommitCallback(FrameCommitCallback callback)640     public void setFrameCommitCallback(FrameCommitCallback callback) {
641         nSetFrameCommitCallback(mNativeProxy, callback);
642     }
643 
644     /** @hide */
setFrameCompleteCallback(FrameCompleteCallback callback)645     public void setFrameCompleteCallback(FrameCompleteCallback callback) {
646         nSetFrameCompleteCallback(mNativeProxy, callback);
647     }
648 
649     /**
650      * TODO: Public API this?
651      *
652      * @hide
653      */
addObserver(HardwareRendererObserver observer)654     public void addObserver(HardwareRendererObserver observer) {
655         nAddObserver(mNativeProxy, observer.getNativeInstance());
656     }
657 
658     /**
659      * TODO: Public API this?
660      *
661      * @hide
662      */
removeObserver(HardwareRendererObserver observer)663     public void removeObserver(HardwareRendererObserver observer) {
664         nRemoveObserver(mNativeProxy, observer.getNativeInstance());
665     }
666 
667     /**
668      * Sets the desired color mode on this renderer. Whether or not the actual rendering
669      * will use the requested colorMode depends on the hardware support for such rendering.
670      *
671      * @param colorMode The @{@link ActivityInfo.ColorMode} to request
672      * @hide
673      */
setColorMode(@ctivityInfo.ColorMode int colorMode)674     public float setColorMode(@ActivityInfo.ColorMode int colorMode) {
675         if (mColorMode != colorMode) {
676             mColorMode = colorMode;
677             mDesiredSdrHdrRatio = nSetColorMode(mNativeProxy, colorMode);
678         }
679         return mDesiredSdrHdrRatio;
680     }
681 
682     /**
683      * Sets the colormode with the desired SDR white point.
684      *
685      * The white point only applies if the color mode is an HDR mode
686      *
687      * @hide
688      */
setColorMode(@ctivityInfo.ColorMode int colorMode, float whitePoint)689     public void setColorMode(@ActivityInfo.ColorMode int colorMode, float whitePoint) {
690         nSetSdrWhitePoint(mNativeProxy, whitePoint);
691         mColorMode = colorMode;
692         nSetColorMode(mNativeProxy, colorMode);
693     }
694 
695     /** @hide */
setTargetHdrSdrRatio(float ratio)696     public void setTargetHdrSdrRatio(float ratio) {
697         if (ratio < 1.f || !Float.isFinite(ratio)) ratio = 1.f;
698         nSetTargetSdrHdrRatio(mNativeProxy, ratio);
699     }
700 
701     /**
702      * Blocks until all previously queued work has completed.
703      *
704      * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
705      * better
706      *
707      * @hide
708      */
fence()709     public void fence() {
710         nFence(mNativeProxy);
711     }
712 
713     /** @hide */
registerAnimatingRenderNode(RenderNode animator)714     public void registerAnimatingRenderNode(RenderNode animator) {
715         nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
716     }
717 
718     /** @hide */
registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator)719     public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
720         nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
721                 animator.getAnimatorNativePtr());
722     }
723 
724     /**
725      * Prevents any further drawing until {@link FrameRenderRequest#syncAndDraw()} is called.
726      * This is a signal that the contents of the RenderNode tree are no longer safe to play back.
727      * In practice this usually means that there are Functor pointers in the
728      * display list that are no longer valid.
729      *
730      * TODO: Can we get webview off of this?
731      *
732      * @hide
733      */
stopDrawing()734     public void stopDrawing() {
735         nStopDrawing(mNativeProxy);
736     }
737 
738     /**
739      * Creates a new hardware layer. A hardware layer built by calling this
740      * method will be treated as a texture layer, instead of as a render target.
741      *
742      * @return A hardware layer
743      * @hide
744      */
createTextureLayer()745     public TextureLayer createTextureLayer() {
746         long layer = nCreateTextureLayer(mNativeProxy);
747         return TextureLayer.adoptTextureLayer(this, layer);
748     }
749 
750     /**
751      * Detaches the layer's surface texture from the GL context and releases
752      * the texture id
753      *
754      * @hide
755      */
detachSurfaceTexture(long hardwareLayer)756     public void detachSurfaceTexture(long hardwareLayer) {
757         nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
758     }
759 
760 
761     /** @hide */
buildLayer(RenderNode node)762     public void buildLayer(RenderNode node) {
763         if (node.hasDisplayList()) {
764             nBuildLayer(mNativeProxy, node.mNativeRenderNode);
765         }
766     }
767 
768     /** @hide */
copyLayerInto(final TextureLayer layer, final Bitmap bitmap)769     public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
770         return nCopyLayerInto(mNativeProxy, layer.getDeferredLayerUpdater(),
771             bitmap.getNativeInstance());
772     }
773 
774     /**
775      * Indicates that the specified hardware layer needs to be updated
776      * as soon as possible.
777      *
778      * @param layer The hardware layer that needs an update
779      * @hide
780      */
pushLayerUpdate(TextureLayer layer)781     public void pushLayerUpdate(TextureLayer layer) {
782         nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
783     }
784 
785     /**
786      * Tells the HardwareRenderer that the layer is destroyed. The renderer
787      * should remove the layer from any update queues.
788      *
789      * @hide
790      */
onLayerDestroyed(TextureLayer layer)791     public void onLayerDestroyed(TextureLayer layer) {
792         nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
793     }
794 
795     /** @hide */
setASurfaceTransactionCallback(ASurfaceTransactionCallback callback)796     protected void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) {
797         nSetASurfaceTransactionCallback(mNativeProxy, callback);
798     }
799 
800     /** @hide */
setPrepareSurfaceControlForWebviewCallback( PrepareSurfaceControlForWebviewCallback callback)801     protected void setPrepareSurfaceControlForWebviewCallback(
802             PrepareSurfaceControlForWebviewCallback callback) {
803         nSetPrepareSurfaceControlForWebviewCallback(mNativeProxy, callback);
804     }
805 
806     /** @hide */
setFrameCallback(FrameDrawingCallback callback)807     public void setFrameCallback(FrameDrawingCallback callback) {
808         nSetFrameCallback(mNativeProxy, callback);
809     }
810 
811     /**
812      * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
813      * rendernode of the UI thread.
814      *
815      * @param node       The node to add.
816      * @param placeFront If true, the render node will be placed in front of the content node,
817      *                   otherwise behind the content node.
818      * @hide
819      */
addRenderNode(RenderNode node, boolean placeFront)820     public void addRenderNode(RenderNode node, boolean placeFront) {
821         nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
822     }
823 
824     /**
825      * Only especially added render nodes can be removed.
826      *
827      * @param node The node which was added via addRenderNode which should get removed again.
828      * @hide
829      */
removeRenderNode(RenderNode node)830     public void removeRenderNode(RenderNode node) {
831         nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
832     }
833 
834     /**
835      * Draws a particular render node. If the node is not the content node, only the additional
836      * nodes will get drawn and the content remains untouched.
837      *
838      * @param node The node to be drawn.
839      * @hide
840      */
drawRenderNode(RenderNode node)841     public void drawRenderNode(RenderNode node) {
842         nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
843     }
844 
845     /**
846      * Loads system properties used by the renderer. This method is invoked
847      * whenever system properties are modified. Implementations can use this
848      * to trigger live updates of the renderer based on properties.
849      *
850      * @return True if a property has changed.
851      * @hide
852      */
loadSystemProperties()853     public boolean loadSystemProperties() {
854         return nLoadSystemProperties(mNativeProxy);
855     }
856 
857     /**
858      * @hide
859      */
dumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags)860     public static void dumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
861         nDumpGlobalProfileInfo(fd, dumpFlags);
862     }
863 
864     /**
865      * @hide
866      */
dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags)867     public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
868         nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
869     }
870 
871     /**
872      * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
873      * will be prevented to overdraw this area. It will be synchronized with the draw call.
874      * This should be updated in the content view's draw call.
875      *
876      * @param left   The left side of the protected bounds.
877      * @param top    The top side of the protected bounds.
878      * @param right  The right side of the protected bounds.
879      * @param bottom The bottom side of the protected bounds.
880      * @hide
881      */
setContentDrawBounds(int left, int top, int right, int bottom)882     public void setContentDrawBounds(int left, int top, int right, int bottom) {
883         nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
884     }
885 
886     /**
887      * Force the new frame to draw, ensuring the UI draw request will attempt a draw this vsync.
888      * @hide
889      */
forceDrawNextFrame()890     public void forceDrawNextFrame() {
891         nForceDrawNextFrame(mNativeProxy);
892     }
893 
894     /** @hide */
setPictureCaptureCallback(@ullable PictureCapturedCallback callback)895     public void setPictureCaptureCallback(@Nullable PictureCapturedCallback callback) {
896         nSetPictureCaptureCallback(mNativeProxy, callback);
897     }
898 
899     /** called by native */
invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback)900     static void invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback) {
901         Picture picture = new Picture(picturePtr);
902         callback.onPictureCaptured(picture);
903     }
904 
905    /**
906      * Interface used to receive callbacks when Webview requests a surface control.
907      *
908      * @hide
909      */
910     public interface PrepareSurfaceControlForWebviewCallback {
911         /**
912          * Invoked when Webview calls to get a surface control.
913          *
914          */
prepare()915         void prepare();
916     }
917 
918     /**
919      * Interface used to receive callbacks when a transaction needs to be merged.
920      *
921      * @hide
922      */
923     public interface ASurfaceTransactionCallback {
924         /**
925          * Invoked during a frame drawing.
926          *
927          * @param aSurfaceTranactionNativeObj the ASurfaceTransaction native object handle
928          * @param aSurfaceControlNativeObj ASurfaceControl native object handle
929          * @param frame The id of the frame being drawn.
930          */
onMergeTransaction(long aSurfaceTranactionNativeObj, long aSurfaceControlNativeObj, long frame)931         boolean onMergeTransaction(long aSurfaceTranactionNativeObj,
932                                 long aSurfaceControlNativeObj, long frame);
933     }
934 
935     /**
936      * Interface used to receive callbacks when a frame is being drawn.
937      *
938      * @hide
939      */
940     public interface FrameDrawingCallback {
941         /**
942          * Invoked during a frame drawing.
943          *
944          * @param frame The id of the frame being drawn.
945          */
onFrameDraw(long frame)946         void onFrameDraw(long frame);
947 
948         /**
949          * Invoked during a frame drawing.
950          *
951          * @param syncResult The result of the draw. Should be a value or a combination of values
952          *                   from {@link SyncAndDrawResult}
953          * @param frame The id of the frame being drawn.
954          *
955          * @return A {@link FrameCommitCallback} that will report back if the current vsync draws.
956          */
onFrameDraw(@yncAndDrawResult int syncResult, long frame)957         default FrameCommitCallback onFrameDraw(@SyncAndDrawResult int syncResult, long frame) {
958             onFrameDraw(frame);
959             return null;
960         }
961     }
962 
963     /**
964      * Interface used to be notified when a frame has finished rendering
965      *
966      * @hide
967      */
968     public interface FrameCommitCallback {
969         /**
970          * Invoked after a new frame was drawn
971          *
972          * @param didProduceBuffer The draw successfully produced a new buffer.
973          */
onFrameCommit(boolean didProduceBuffer)974         void onFrameCommit(boolean didProduceBuffer);
975     }
976 
977     /**
978      * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't
979      * mean a new frame has drawn, specifically if there's nothing new to draw, but only that
980      * RenderThread had a chance to draw a frame.
981      *
982      * @hide
983      */
984     public interface FrameCompleteCallback {
985         /**
986          * Invoked after a frame draw was attempted.
987          */
onFrameComplete()988         void onFrameComplete();
989     }
990 
991     /**
992      * Interface for listening to picture captures
993      * @hide
994      */
995     public interface PictureCapturedCallback {
996         /** @hide */
onPictureCaptured(Picture picture)997         void onPictureCaptured(Picture picture);
998     }
999 
validateAlpha(float alpha, String argumentName)1000     private static void validateAlpha(float alpha, String argumentName) {
1001         if (!(alpha >= 0.0f && alpha <= 1.0f)) {
1002             throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
1003                     + alpha + " is not in the range of 0.0f to 1.0f");
1004         }
1005     }
1006 
validatePositive(float f, String argumentName)1007     private static void validatePositive(float f, String argumentName) {
1008         if (!(Float.isFinite(f) && f >= 0.0f)) {
1009             throw new IllegalArgumentException(argumentName
1010                     + " must be a finite positive, given=" + f);
1011         }
1012     }
1013 
validateFinite(float f, String argumentName)1014     private static void validateFinite(float f, String argumentName) {
1015         if (!Float.isFinite(f)) {
1016             throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
1017         }
1018     }
1019 
1020     /**
1021      * Notifies the hardware renderer about pending choreographer callbacks.
1022      *
1023      * @hide
1024      */
notifyCallbackPending()1025     public void notifyCallbackPending() {
1026         nNotifyCallbackPending(mNativeProxy);
1027     }
1028 
1029     /**
1030      * Notifies the hardware renderer about upcoming expensive frames.
1031      *
1032      * @hide
1033      */
notifyExpensiveFrame()1034     public void notifyExpensiveFrame() {
1035         nNotifyExpensiveFrame(mNativeProxy);
1036     }
1037 
1038     /**
1039      * b/68769804, b/66945974: For low FPS experiments.
1040      *
1041      * @hide
1042      */
setFPSDivisor(int divisor)1043     public static void setFPSDivisor(int divisor) {
1044         nSetRtAnimationsEnabled(divisor <= 1);
1045     }
1046 
1047     /**
1048      * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
1049      * called before any OpenGL context is created.
1050      *
1051      * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
1052      * @hide
1053      */
setContextPriority(int priority)1054     public static void setContextPriority(int priority) {
1055         nSetContextPriority(priority);
1056     }
1057 
1058     /**
1059      * Sets whether or not high contrast text rendering is enabled. The setting is global
1060      * but only affects content rendered after the change is made.
1061      *
1062      * @hide
1063      */
setHighContrastText(boolean highContrastText)1064     public static void setHighContrastText(boolean highContrastText) {
1065         nSetHighContrastText(highContrastText);
1066     }
1067 
1068     /**
1069      * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
1070      *
1071      * @hide
1072      */
setIsolatedProcess(boolean isIsolated)1073     public static void setIsolatedProcess(boolean isIsolated) {
1074         nSetIsolatedProcess(isIsolated);
1075         ProcessInitializer.sInstance.setIsolated(isIsolated);
1076     }
1077 
1078     /**
1079      * Sends device configuration changes to the render thread, for rendering profiling views.
1080      *
1081      * @hide
1082      */
sendDeviceConfigurationForDebugging(Configuration config)1083     public static void sendDeviceConfigurationForDebugging(Configuration config) {
1084         if (config.densityDpi != Configuration.DENSITY_DPI_UNDEFINED
1085                 && config.densityDpi != sDensityDpi) {
1086             sDensityDpi = config.densityDpi;
1087             nSetDisplayDensityDpi(config.densityDpi);
1088         }
1089     }
1090 
1091     /**
1092      * If set extra graphics debugging abilities will be enabled such as dumping skp
1093      *
1094      * @hide
1095      */
setDebuggingEnabled(boolean enable)1096     public static void setDebuggingEnabled(boolean enable) {
1097         nSetDebuggingEnabled(enable);
1098     }
1099 
1100     /** @hide */
1101     public abstract static class CopyRequest {
1102         protected Bitmap mDestinationBitmap;
1103         final Rect mSrcRect;
1104 
CopyRequest(Rect srcRect, Bitmap destinationBitmap)1105         protected CopyRequest(Rect srcRect, Bitmap destinationBitmap) {
1106             mDestinationBitmap = destinationBitmap;
1107             if (srcRect != null) {
1108                 mSrcRect = srcRect;
1109             } else {
1110                 mSrcRect = new Rect();
1111             }
1112         }
1113 
1114         /**
1115          * Retrieve the bitmap in which to store the result of the copy request
1116          */
getDestinationBitmap(int srcWidth, int srcHeight)1117         public long getDestinationBitmap(int srcWidth, int srcHeight) {
1118             if (mDestinationBitmap == null) {
1119                 mDestinationBitmap =
1120                         Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
1121             }
1122             return mDestinationBitmap.getNativeInstance();
1123         }
1124 
1125         /** Called when the copy is completed */
onCopyFinished(int result)1126         public abstract void onCopyFinished(int result);
1127     }
1128 
1129     /** @hide */
copySurfaceInto(Surface surface, CopyRequest copyRequest)1130     public static void copySurfaceInto(Surface surface, CopyRequest copyRequest) {
1131         final Rect srcRect = copyRequest.mSrcRect;
1132         nCopySurfaceInto(surface, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
1133                 copyRequest);
1134     }
1135 
1136     /**
1137      * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
1138      * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
1139      * not the RenderNode from a View.
1140      *
1141      * @hide
1142      **/
createHardwareBitmap(RenderNode node, int width, int height)1143     public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
1144         return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
1145     }
1146 
1147     /**
1148      * Invoke this method when the system is running out of memory. This
1149      * method will attempt to recover as much memory as possible, based on
1150      * the specified hint.
1151      *
1152      * @param level Hint about the amount of memory that should be trimmed,
1153      *              see {@link android.content.ComponentCallbacks}
1154      * @hide
1155      */
trimMemory(int level)1156     public static void trimMemory(int level) {
1157         nTrimMemory(level);
1158     }
1159 
1160     /**
1161      * Invoke this when all font caches should be flushed. This can cause jank on next render
1162      * commands so use it only after expensive font allocation operations which would
1163      * allocate large amount of temporary memory.
1164      *
1165      * @param level Hint about which caches to trim. See {@link #CACHE_TRIM_ALL},
1166      *              {@link #CACHE_TRIM_FONT}, {@link #CACHE_TRIM_RESOURCES}
1167      *
1168      * @hide
1169      */
trimCaches(@acheTrimLevel int level)1170     public static void trimCaches(@CacheTrimLevel int level) {
1171         nTrimCaches(level);
1172     }
1173 
1174     /** @hide */
overrideProperty(@onNull String name, @NonNull String value)1175     public static void overrideProperty(@NonNull String name, @NonNull String value) {
1176         if (name == null || value == null) {
1177             throw new IllegalArgumentException("name and value must be non-null");
1178         }
1179         nOverrideProperty(name, value);
1180     }
1181 
1182     /**
1183      * Sets the directory to use as a persistent storage for threaded rendering
1184      * resources.
1185      *
1186      * @param cacheDir A directory the current process can write to
1187      * @hide
1188      */
setupDiskCache(File cacheDir)1189     public static void setupDiskCache(File cacheDir) {
1190         setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
1191                 new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
1192     }
1193 
1194     /** @hide */
setPackageName(String packageName)1195     public static void setPackageName(String packageName) {
1196         ProcessInitializer.sInstance.setPackageName(packageName);
1197     }
1198 
1199     /**
1200      * Gets a context for process initialization
1201      *
1202      * TODO: Remove this once there is a static method for retrieving an application's context.
1203      *
1204      * @hide
1205      */
setContextForInit(Context context)1206     public static void setContextForInit(Context context) {
1207         ProcessInitializer.sInstance.setContext(context);
1208     }
1209 
1210     /**
1211      * Sets whether or not the current process is a system or persistent process. Used to influence
1212      * the chosen memory usage policy.
1213      *
1214      * @hide
1215      **/
setIsSystemOrPersistent()1216     public static void setIsSystemOrPersistent() {
1217         nSetIsSystemOrPersistent(true);
1218     }
1219 
1220     /**
1221      * Returns true if HardwareRender will produce output.
1222      *
1223      * This value is global to the process and affects all uses of HardwareRenderer,
1224      * including
1225      * those created by the system such as those used by the View tree when using hardware
1226      * accelerated rendering.
1227      *
1228      * Default is true in all production environments, but may be false in testing-focused
1229      * emulators or if {@link #setDrawingEnabled(boolean)} is used.
1230      */
isDrawingEnabled()1231     public static boolean isDrawingEnabled() {
1232         return nIsDrawingEnabled();
1233     }
1234 
1235     /**
1236      * Toggles whether or not HardwareRenderer will produce drawing output globally in the current
1237      * process.
1238      *
1239      * This applies to all HardwareRenderer instances, including those created by the platform such
1240      * as those used by the system for hardware accelerated View rendering.
1241      *
1242      * The capability to disable drawing output is intended for test environments, primarily
1243      * headless ones. By setting this to false, tests that launch activities or interact with Views
1244      * can be quicker with less RAM usage by skipping the final step of View drawing. All View
1245      * lifecycle events will occur as normal, only the final step of rendering on the GPU to the
1246      * display will be skipped.
1247      *
1248      * This can be toggled on and off at will, so screenshot tests can also run in this same
1249      * environment by toggling drawing back on and forcing a frame to be drawn such as by calling
1250      * view#invalidate(). Once drawn and the screenshot captured, this can then be turned back off.
1251      */
1252     // TODO(b/194195794): Add link to androidx's Screenshot library for help with this
setDrawingEnabled(boolean drawingEnabled)1253     public static void setDrawingEnabled(boolean drawingEnabled) {
1254         nSetDrawingEnabled(drawingEnabled);
1255     }
1256 
1257     /**
1258      * Disable RenderThread animations that schedule draws directly from RenderThread. This is used
1259      * when we don't want to de-schedule draw requests that come from the UI thread.
1260      *
1261      * @hide
1262      */
setRtAnimationsEnabled(boolean enabled)1263     public static void setRtAnimationsEnabled(boolean enabled) {
1264         nSetRtAnimationsEnabled(enabled);
1265     }
1266 
1267     private static final class DestroyContextRunnable implements Runnable {
1268         private final long mNativeInstance;
1269 
DestroyContextRunnable(long nativeInstance)1270         DestroyContextRunnable(long nativeInstance) {
1271             mNativeInstance = nativeInstance;
1272         }
1273 
1274         @Override
run()1275         public void run() {
1276             nDeleteProxy(mNativeInstance);
1277         }
1278     }
1279 
1280     private static class ProcessInitializer {
1281         static ProcessInitializer sInstance = new ProcessInitializer();
1282 
1283         private boolean mInitialized = false;
1284         private boolean mDisplayInitialized = false;
1285 
1286         private boolean mIsolated = false;
1287         private Context mContext;
1288         private String mPackageName;
1289         private IGraphicsStats mGraphicsStatsService;
1290         private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
1291             @Override
1292             public void onRotateGraphicsStatsBuffer() throws RemoteException {
1293                 rotateBuffer();
1294             }
1295         };
1296 
ProcessInitializer()1297         private ProcessInitializer() {
1298         }
1299 
setPackageName(String name)1300         synchronized void setPackageName(String name) {
1301             if (mInitialized) return;
1302             mPackageName = name;
1303         }
1304 
setIsolated(boolean isolated)1305         synchronized void setIsolated(boolean isolated) {
1306             if (mInitialized) return;
1307             mIsolated = isolated;
1308         }
1309 
setContext(Context context)1310         synchronized void setContext(Context context) {
1311             if (mInitialized) return;
1312             mContext = context;
1313         }
1314 
init(long renderProxy)1315         synchronized void init(long renderProxy) {
1316             if (mInitialized) return;
1317             mInitialized = true;
1318 
1319             initSched(renderProxy);
1320             initGraphicsStats();
1321         }
1322 
initSched(long renderProxy)1323         private void initSched(long renderProxy) {
1324             try {
1325                 int tid = nGetRenderThreadTid(renderProxy);
1326                 ActivityManager.getService().setRenderThread(tid);
1327             } catch (Throwable t) {
1328                 Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
1329             }
1330         }
1331 
initGraphicsStats()1332         private void initGraphicsStats() {
1333             if (mPackageName == null) return;
1334 
1335             try {
1336                 IBinder binder = ServiceManager.getService("graphicsstats");
1337                 if (binder == null) return;
1338                 mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
1339                 requestBuffer();
1340             } catch (Throwable t) {
1341                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
1342             }
1343         }
1344 
initUsingContext()1345         synchronized void initUsingContext() {
1346             if (mContext == null) return;
1347 
1348             initDisplayInfo();
1349 
1350             nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
1351             nSetIsLowRam(ActivityManager.isLowRamDeviceStatic());
1352             // Defensively clear out the context in case we were passed a context that can leak
1353             // if we live longer than it, e.g. an activity context.
1354             mContext = null;
1355         }
1356 
initDisplayInfo()1357         private void initDisplayInfo() {
1358             if (mDisplayInitialized) return;
1359             if (mIsolated) {
1360                 mDisplayInitialized = true;
1361                 return;
1362             }
1363 
1364             DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
1365             if (dm == null) {
1366                 Log.d(LOG_TAG, "Failed to find DisplayManager for display-based configuration");
1367                 return;
1368             }
1369 
1370             final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
1371             if (defaultDisplay == null) {
1372                 Log.d(LOG_TAG, "Failed to find default display for display-based configuration");
1373                 return;
1374             }
1375 
1376             final Display[] allDisplays = dm.getDisplays();
1377             if (allDisplays.length == 0) {
1378                 Log.d(LOG_TAG, "Failed to query displays");
1379                 return;
1380             }
1381 
1382             final Mode activeMode = defaultDisplay.getMode();
1383             final ColorSpace defaultWideColorSpace =
1384                     defaultDisplay.getPreferredWideGamutColorSpace();
1385             int wideColorDataspace = defaultWideColorSpace != null
1386                     ? defaultWideColorSpace.getDataSpace() : 0;
1387             // largest width & height are used to size the default HWUI cache sizes. So find the
1388             // largest display resolution we could encounter & use that as the guidance. The actual
1389             // memory policy in play will interpret these values differently.
1390             int largestWidth = activeMode.getPhysicalWidth();
1391             int largestHeight = activeMode.getPhysicalHeight();
1392             final OverlayProperties overlayProperties = defaultDisplay.getOverlaySupport();
1393             boolean supportFp16ForHdr = overlayProperties != null
1394                     ? overlayProperties.supportFp16ForHdr() : false;
1395             boolean supportMixedColorSpaces = overlayProperties != null
1396                     ? overlayProperties.supportMixedColorSpaces() : false;
1397 
1398             for (int i = 0; i < allDisplays.length; i++) {
1399                 final Display display = allDisplays[i];
1400                 // Take the first wide gamut dataspace as the source of truth
1401                 // Possibly should do per-HardwareRenderer wide gamut dataspace so we can use the
1402                 // target display's ideal instead
1403                 if (wideColorDataspace == 0) {
1404                     ColorSpace cs = display.getPreferredWideGamutColorSpace();
1405                     if (cs != null) {
1406                         wideColorDataspace = cs.getDataSpace();
1407                     }
1408                 }
1409                 Mode[] modes = display.getSupportedModes();
1410                 for (int j = 0; j < modes.length; j++) {
1411                     Mode mode = modes[j];
1412                     int width = mode.getPhysicalWidth();
1413                     int height = mode.getPhysicalHeight();
1414                     if ((width * height) > (largestWidth * largestHeight)) {
1415                         largestWidth = width;
1416                         largestHeight = height;
1417                     }
1418                 }
1419             }
1420 
1421             nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(),
1422                     wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(),
1423                     defaultDisplay.getPresentationDeadlineNanos(),
1424                     supportFp16ForHdr, supportMixedColorSpaces);
1425 
1426             mDisplayInitialized = true;
1427         }
1428 
rotateBuffer()1429         private void rotateBuffer() {
1430             nRotateProcessStatsBuffer();
1431             requestBuffer();
1432         }
1433 
requestBuffer()1434         private void requestBuffer() {
1435             try {
1436                 ParcelFileDescriptor pfd = mGraphicsStatsService
1437                         .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
1438                 nSetProcessStatsBuffer(pfd.getFd());
1439                 pfd.close();
1440             } catch (Throwable t) {
1441                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
1442             }
1443         }
1444     }
1445 
1446     /**
1447      * @hide
1448      */
disableVsync()1449     public static native void disableVsync();
1450 
1451     /**
1452      * Start render thread and initialize EGL or Vulkan.
1453      *
1454      * Initializing EGL involves loading and initializing the graphics driver. Some drivers take
1455      * several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
1456      * its first frame adds directly to user-visible app launch latency.
1457      *
1458      * Should only be called after GraphicsEnvironment.chooseDriver().
1459      * @hide
1460      */
preload()1461     public static native void preload();
1462 
1463     /**
1464      * @hide
1465      */
isWebViewOverlaysEnabled()1466     protected static native boolean isWebViewOverlaysEnabled();
1467 
1468     /** @hide */
setupShadersDiskCache(String cacheFile, String skiaCacheFile)1469     protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
1470 
nRotateProcessStatsBuffer()1471     private static native void nRotateProcessStatsBuffer();
1472 
nSetProcessStatsBuffer(int fd)1473     private static native void nSetProcessStatsBuffer(int fd);
1474 
nGetRenderThreadTid(long nativeProxy)1475     private static native int nGetRenderThreadTid(long nativeProxy);
1476 
nCreateRootRenderNode()1477     private static native long nCreateRootRenderNode();
1478 
nCreateProxy(boolean translucent, long rootRenderNode)1479     private static native long nCreateProxy(boolean translucent, long rootRenderNode);
1480 
nDeleteProxy(long nativeProxy)1481     private static native void nDeleteProxy(long nativeProxy);
1482 
nLoadSystemProperties(long nativeProxy)1483     private static native boolean nLoadSystemProperties(long nativeProxy);
1484 
nSetName(long nativeProxy, String name)1485     private static native void nSetName(long nativeProxy, String name);
1486 
nSetSurface(long nativeProxy, Surface window, boolean discardBuffer)1487     private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer);
1488 
nSetSurfaceControl(long nativeProxy, long nativeSurfaceControl)1489     private static native void nSetSurfaceControl(long nativeProxy, long nativeSurfaceControl);
1490 
nPause(long nativeProxy)1491     private static native boolean nPause(long nativeProxy);
1492 
nSetStopped(long nativeProxy, boolean stopped)1493     private static native void nSetStopped(long nativeProxy, boolean stopped);
1494 
nSetLightGeometry(long nativeProxy, float lightX, float lightY, float lightZ, float lightRadius)1495     private static native void nSetLightGeometry(long nativeProxy,
1496             float lightX, float lightY, float lightZ, float lightRadius);
1497 
nSetLightAlpha(long nativeProxy, float ambientShadowAlpha, float spotShadowAlpha)1498     private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
1499             float spotShadowAlpha);
1500 
nSetOpaque(long nativeProxy, boolean opaque)1501     private static native void nSetOpaque(long nativeProxy, boolean opaque);
1502 
nSetColorMode(long nativeProxy, int colorMode)1503     private static native float nSetColorMode(long nativeProxy, int colorMode);
1504 
nSetTargetSdrHdrRatio(long nativeProxy, float ratio)1505     private static native void nSetTargetSdrHdrRatio(long nativeProxy, float ratio);
1506 
nSetSdrWhitePoint(long nativeProxy, float whitePoint)1507     private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
1508 
nSetIsHighEndGfx(boolean isHighEndGfx)1509     private static native void nSetIsHighEndGfx(boolean isHighEndGfx);
1510 
nSetIsLowRam(boolean isLowRam)1511     private static native void nSetIsLowRam(boolean isLowRam);
1512 
nSetIsSystemOrPersistent(boolean isSystemOrPersistent)1513     private static native void nSetIsSystemOrPersistent(boolean isSystemOrPersistent);
1514 
nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size)1515     private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
1516 
nDestroy(long nativeProxy, long rootRenderNode)1517     private static native void nDestroy(long nativeProxy, long rootRenderNode);
1518 
nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode)1519     private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
1520             long animatingNode);
1521 
nRegisterVectorDrawableAnimator(long rootRenderNode, long animator)1522     private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
1523 
nCreateTextureLayer(long nativeProxy)1524     private static native long nCreateTextureLayer(long nativeProxy);
1525 
nBuildLayer(long nativeProxy, long node)1526     private static native void nBuildLayer(long nativeProxy, long node);
1527 
nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle)1528     private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle);
1529 
nPushLayerUpdate(long nativeProxy, long layer)1530     private static native void nPushLayerUpdate(long nativeProxy, long layer);
1531 
nCancelLayerUpdate(long nativeProxy, long layer)1532     private static native void nCancelLayerUpdate(long nativeProxy, long layer);
1533 
nDetachSurfaceTexture(long nativeProxy, long layer)1534     private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
1535 
nDestroyHardwareResources(long nativeProxy)1536     private static native void nDestroyHardwareResources(long nativeProxy);
1537 
nTrimMemory(int level)1538     private static native void nTrimMemory(int level);
1539 
nTrimCaches(int level)1540     private static native void nTrimCaches(int level);
1541 
nOverrideProperty(String name, String value)1542     private static native void nOverrideProperty(String name, String value);
1543 
nFence(long nativeProxy)1544     private static native void nFence(long nativeProxy);
1545 
nStopDrawing(long nativeProxy)1546     private static native void nStopDrawing(long nativeProxy);
1547 
nNotifyFramePending(long nativeProxy)1548     private static native void nNotifyFramePending(long nativeProxy);
1549 
nDumpProfileInfo(long nativeProxy, FileDescriptor fd, @DumpFlags int dumpFlags)1550     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
1551             @DumpFlags int dumpFlags);
1552 
nDumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags)1553     private static native void nDumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags);
1554 
nAddRenderNode(long nativeProxy, long rootRenderNode, boolean placeFront)1555     private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
1556             boolean placeFront);
1557 
nRemoveRenderNode(long nativeProxy, long rootRenderNode)1558     private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
1559 
nDrawRenderNode(long nativeProxy, long rootRenderNode)1560     private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
1561 
nSetContentDrawBounds(long nativeProxy, int left, int top, int right, int bottom)1562     private static native void nSetContentDrawBounds(long nativeProxy, int left,
1563             int top, int right, int bottom);
1564 
nForceDrawNextFrame(long nativeProxy)1565     private static native void nForceDrawNextFrame(long nativeProxy);
1566 
nSetPictureCaptureCallback(long nativeProxy, PictureCapturedCallback callback)1567     private static native void nSetPictureCaptureCallback(long nativeProxy,
1568             PictureCapturedCallback callback);
1569 
nSetASurfaceTransactionCallback(long nativeProxy, ASurfaceTransactionCallback callback)1570     private static native void nSetASurfaceTransactionCallback(long nativeProxy,
1571             ASurfaceTransactionCallback callback);
1572 
nSetPrepareSurfaceControlForWebviewCallback(long nativeProxy, PrepareSurfaceControlForWebviewCallback callback)1573     private static native void nSetPrepareSurfaceControlForWebviewCallback(long nativeProxy,
1574             PrepareSurfaceControlForWebviewCallback callback);
1575 
nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback)1576     private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
1577 
nSetFrameCommitCallback(long nativeProxy, FrameCommitCallback callback)1578     private static native void nSetFrameCommitCallback(long nativeProxy,
1579             FrameCommitCallback callback);
1580 
nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback)1581     private static native void nSetFrameCompleteCallback(long nativeProxy,
1582             FrameCompleteCallback callback);
1583 
nAddObserver(long nativeProxy, long nativeObserver)1584     private static native void nAddObserver(long nativeProxy, long nativeObserver);
1585 
nRemoveObserver(long nativeProxy, long nativeObserver)1586     private static native void nRemoveObserver(long nativeProxy, long nativeObserver);
1587 
nCopySurfaceInto(Surface surface, int srcLeft, int srcTop, int srcRight, int srcBottom, CopyRequest request)1588     private static native void nCopySurfaceInto(Surface surface,
1589             int srcLeft, int srcTop, int srcRight, int srcBottom, CopyRequest request);
1590 
nCreateHardwareBitmap(long renderNode, int width, int height)1591     private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
1592 
nSetHighContrastText(boolean enabled)1593     private static native void nSetHighContrastText(boolean enabled);
1594 
nSetDebuggingEnabled(boolean enabled)1595     private static native void nSetDebuggingEnabled(boolean enabled);
1596 
nSetIsolatedProcess(boolean enabled)1597     private static native void nSetIsolatedProcess(boolean enabled);
1598 
nSetContextPriority(int priority)1599     private static native void nSetContextPriority(int priority);
1600 
nAllocateBuffers(long nativeProxy)1601     private static native void nAllocateBuffers(long nativeProxy);
1602 
nSetForceDark(long nativeProxy, boolean enabled)1603     private static native void nSetForceDark(long nativeProxy, boolean enabled);
1604 
nSetDisplayDensityDpi(int densityDpi)1605     private static native void nSetDisplayDensityDpi(int densityDpi);
1606 
nInitDisplayInfo(int width, int height, float refreshRate, int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos, boolean supportsFp16ForHdr, boolean nInitDisplayInfo)1607     private static native void nInitDisplayInfo(int width, int height, float refreshRate,
1608             int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos,
1609             boolean supportsFp16ForHdr, boolean nInitDisplayInfo);
1610 
nSetDrawingEnabled(boolean drawingEnabled)1611     private static native void nSetDrawingEnabled(boolean drawingEnabled);
1612 
nIsDrawingEnabled()1613     private static native boolean nIsDrawingEnabled();
1614 
nSetRtAnimationsEnabled(boolean rtAnimationsEnabled)1615     private static native void nSetRtAnimationsEnabled(boolean rtAnimationsEnabled);
1616 
nNotifyCallbackPending(long nativeProxy)1617     private static native void nNotifyCallbackPending(long nativeProxy);
1618 
nNotifyExpensiveFrame(long nativeProxy)1619     private static native void nNotifyExpensiveFrame(long nativeProxy);
1620 }
1621