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