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