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