1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.app.ActivityManager; 22 import android.content.Context; 23 import android.content.res.TypedArray; 24 import android.graphics.Bitmap; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.graphics.drawable.AnimatedVectorDrawable; 28 import android.os.IBinder; 29 import android.os.ParcelFileDescriptor; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.os.SystemProperties; 33 import android.os.Trace; 34 import android.util.Log; 35 import android.view.Surface.OutOfResourcesException; 36 import android.view.View.AttachInfo; 37 import android.view.animation.AnimationUtils; 38 39 import com.android.internal.R; 40 import com.android.internal.util.VirtualRefBasePtr; 41 42 import java.io.File; 43 import java.io.FileDescriptor; 44 import java.io.PrintWriter; 45 import java.lang.annotation.Retention; 46 import java.lang.annotation.RetentionPolicy; 47 48 /** 49 * Threaded renderer that proxies the rendering to a render thread. Most calls 50 * are currently synchronous. 51 * 52 * The UI thread can block on the RenderThread, but RenderThread must never 53 * block on the UI thread. 54 * 55 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates 56 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed 57 * by the lifecycle of the RenderProxy. 58 * 59 * Note that although currently the EGL context & surfaces are created & managed 60 * by the render thread, the goal is to move that into a shared structure that can 61 * be managed by both threads. EGLSurface creation & deletion should ideally be 62 * done on the UI thread and not the RenderThread to avoid stalling the 63 * RenderThread with surface buffer allocation. 64 * 65 * @hide 66 */ 67 public final class ThreadedRenderer { 68 private static final String LOG_TAG = "ThreadedRenderer"; 69 70 /** 71 * Name of the file that holds the shaders cache. 72 */ 73 private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; 74 private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache"; 75 76 /** 77 * System property used to enable or disable threaded rendering profiling. 78 * The default value of this property is assumed to be false. 79 * 80 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 81 * output extra information about the time taken to execute by the last 82 * frames. 83 * 84 * Possible values: 85 * "true", to enable profiling 86 * "visual_bars", to enable profiling and visualize the results on screen 87 * "false", to disable profiling 88 * 89 * @see #PROFILE_PROPERTY_VISUALIZE_BARS 90 * 91 * @hide 92 */ 93 public static final String PROFILE_PROPERTY = "debug.hwui.profile"; 94 95 /** 96 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this 97 * value, profiling data will be visualized on screen as a bar chart. 98 * 99 * @hide 100 */ 101 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars"; 102 103 /** 104 * System property used to specify the number of frames to be used 105 * when doing threaded rendering profiling. 106 * The default value of this property is #PROFILE_MAX_FRAMES. 107 * 108 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 109 * output extra information about the time taken to execute by the last 110 * frames. 111 * 112 * Possible values: 113 * "60", to set the limit of frames to 60 114 */ 115 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes"; 116 117 /** 118 * System property used to debug EGL configuration choice. 119 * 120 * Possible values: 121 * "choice", print the chosen configuration only 122 * "all", print all possible configurations 123 */ 124 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config"; 125 126 /** 127 * Turn on to draw dirty regions every other frame. 128 * 129 * Possible values: 130 * "true", to enable dirty regions debugging 131 * "false", to disable dirty regions debugging 132 * 133 * @hide 134 */ 135 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions"; 136 137 /** 138 * Turn on to flash hardware layers when they update. 139 * 140 * Possible values: 141 * "true", to enable hardware layers updates debugging 142 * "false", to disable hardware layers updates debugging 143 * 144 * @hide 145 */ 146 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY = 147 "debug.hwui.show_layers_updates"; 148 149 /** 150 * Controls overdraw debugging. 151 * 152 * Possible values: 153 * "false", to disable overdraw debugging 154 * "show", to show overdraw areas on screen 155 * "count", to display an overdraw counter 156 * 157 * @hide 158 */ 159 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw"; 160 161 /** 162 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this 163 * value, overdraw will be shown on screen by coloring pixels. 164 * 165 * @hide 166 */ 167 public static final String OVERDRAW_PROPERTY_SHOW = "show"; 168 169 /** 170 * Turn on to debug non-rectangular clip operations. 171 * 172 * Possible values: 173 * "hide", to disable this debug mode 174 * "highlight", highlight drawing commands tested against a non-rectangular clip 175 * "stencil", renders the clip region on screen when set 176 * 177 * @hide 178 */ 179 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY = 180 "debug.hwui.show_non_rect_clip"; 181 182 /** 183 * Sets the FPS devisor to lower the FPS. 184 * 185 * Sets a positive integer as a divisor. 1 (the default value) menas the full FPS, and 2 186 * means half the full FPS. 187 * 188 * 189 * @hide 190 */ 191 public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor"; 192 193 public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101; 194 public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102; 195 public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103; 196 197 static { 198 // Try to check OpenGL support early if possible. isAvailable()199 isAvailable(); 200 } 201 202 /** 203 * A process can set this flag to false to prevent the use of threaded 204 * rendering. 205 * 206 * @hide 207 */ 208 public static boolean sRendererDisabled = false; 209 210 /** 211 * Further threaded renderer disabling for the system process. 212 * 213 * @hide 214 */ 215 public static boolean sSystemRendererDisabled = false; 216 217 /** 218 * Invoke this method to disable threaded rendering in the current process. 219 * 220 * @hide 221 */ disable(boolean system)222 public static void disable(boolean system) { 223 sRendererDisabled = true; 224 if (system) { 225 sSystemRendererDisabled = true; 226 } 227 } 228 229 public static boolean sTrimForeground = false; 230 231 /** 232 * Controls whether or not the renderer should aggressively trim 233 * memory. Note that this must not be set for any process that uses 234 * WebView! This should be only used by system_process or similar 235 * that do not go into the background. 236 */ enableForegroundTrimming()237 public static void enableForegroundTrimming() { 238 sTrimForeground = true; 239 } 240 241 private static Boolean sSupportsOpenGL; 242 243 /** 244 * Indicates whether threaded rendering is available under any form for 245 * the view hierarchy. 246 * 247 * @return True if the view hierarchy can potentially be defer rendered, 248 * false otherwise 249 */ isAvailable()250 public static boolean isAvailable() { 251 if (sSupportsOpenGL != null) { 252 return sSupportsOpenGL.booleanValue(); 253 } 254 if (SystemProperties.getInt("ro.kernel.qemu", 0) == 0) { 255 // Device is not an emulator. 256 sSupportsOpenGL = true; 257 return true; 258 } 259 int qemu_gles = SystemProperties.getInt("qemu.gles", -1); 260 if (qemu_gles == -1) { 261 // In this case, the value of the qemu.gles property is not ready 262 // because the SurfaceFlinger service may not start at this point. 263 return false; 264 } 265 // In the emulator this property will be set > 0 when OpenGL ES 2.0 is 266 // enabled, 0 otherwise. On old emulator versions it will be undefined. 267 sSupportsOpenGL = qemu_gles > 0; 268 return sSupportsOpenGL.booleanValue(); 269 } 270 271 /** 272 * Sets the directory to use as a persistent storage for threaded rendering 273 * resources. 274 * 275 * @param cacheDir A directory the current process can write to 276 * 277 * @hide 278 */ setupDiskCache(File cacheDir)279 public static void setupDiskCache(File cacheDir) { 280 ThreadedRenderer.setupShadersDiskCache( 281 new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(), 282 new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath()); 283 } 284 285 /** 286 * Creates a threaded renderer using OpenGL. 287 * 288 * @param translucent True if the surface is translucent, false otherwise 289 * 290 * @return A threaded renderer backed by OpenGL. 291 */ create(Context context, boolean translucent, String name)292 public static ThreadedRenderer create(Context context, boolean translucent, String name) { 293 ThreadedRenderer renderer = null; 294 if (isAvailable()) { 295 renderer = new ThreadedRenderer(context, translucent, name); 296 } 297 return renderer; 298 } 299 300 /** 301 * Invoke this method when the system is running out of memory. This 302 * method will attempt to recover as much memory as possible, based on 303 * the specified hint. 304 * 305 * @param level Hint about the amount of memory that should be trimmed, 306 * see {@link android.content.ComponentCallbacks} 307 */ trimMemory(int level)308 public static void trimMemory(int level) { 309 nTrimMemory(level); 310 } 311 overrideProperty(@onNull String name, @NonNull String value)312 public static void overrideProperty(@NonNull String name, @NonNull String value) { 313 if (name == null || value == null) { 314 throw new IllegalArgumentException("name and value must be non-null"); 315 } 316 nOverrideProperty(name, value); 317 } 318 319 // Keep in sync with DrawFrameTask.h SYNC_* flags 320 // Nothing interesting to report 321 private static final int SYNC_OK = 0; 322 // Needs a ViewRoot invalidate 323 private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0; 324 // Spoiler: the reward is GPU-accelerated drawing, better find that Surface! 325 private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1; 326 // setStopped is true, drawing is false 327 // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND? 328 // This flag isn't really used as there's nothing that we care to do 329 // in response, so it really just exists to differentiate from LOST_SURFACE 330 // but possibly both can just be deleted. 331 private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2; 332 private static final int SYNC_FRAME_DROPPED = 1 << 3; 333 334 private static final String[] VISUALIZERS = { 335 PROFILE_PROPERTY_VISUALIZE_BARS, 336 }; 337 338 private static final int FLAG_DUMP_FRAMESTATS = 1 << 0; 339 private static final int FLAG_DUMP_RESET = 1 << 1; 340 private static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS; 341 342 @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = { 343 FLAG_DUMP_FRAMESTATS, 344 FLAG_DUMP_RESET 345 }) 346 @Retention(RetentionPolicy.SOURCE) 347 public @interface DumpFlags {} 348 349 // Size of the rendered content. 350 private int mWidth, mHeight; 351 352 // Actual size of the drawing surface. 353 private int mSurfaceWidth, mSurfaceHeight; 354 355 // Insets between the drawing surface and rendered content. These are 356 // applied as translation when updating the root render node. 357 private int mInsetTop, mInsetLeft; 358 359 // Whether the surface has insets. Used to protect opacity. 360 private boolean mHasInsets; 361 362 // Light and shadow properties specified by the theme. 363 private final float mLightY; 364 private final float mLightZ; 365 private final float mLightRadius; 366 private final int mAmbientShadowAlpha; 367 private final int mSpotShadowAlpha; 368 369 private long mNativeProxy; 370 private boolean mInitialized = false; 371 private RenderNode mRootNode; 372 private boolean mRootNodeNeedsUpdate; 373 374 private boolean mEnabled; 375 private boolean mRequested = true; 376 private boolean mIsOpaque = false; 377 ThreadedRenderer(Context context, boolean translucent, String name)378 ThreadedRenderer(Context context, boolean translucent, String name) { 379 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0); 380 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0); 381 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0); 382 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0); 383 mAmbientShadowAlpha = 384 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f); 385 mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f); 386 a.recycle(); 387 388 long rootNodePtr = nCreateRootRenderNode(); 389 mRootNode = RenderNode.adopt(rootNodePtr); 390 mRootNode.setClipToBounds(false); 391 mIsOpaque = !translucent; 392 mNativeProxy = nCreateProxy(translucent, rootNodePtr); 393 nSetName(mNativeProxy, name); 394 395 ProcessInitializer.sInstance.init(context, mNativeProxy); 396 397 loadSystemProperties(); 398 } 399 400 /** 401 * Destroys the threaded rendering context. 402 */ destroy()403 void destroy() { 404 mInitialized = false; 405 updateEnabledState(null); 406 nDestroy(mNativeProxy, mRootNode.mNativeRenderNode); 407 } 408 409 /** 410 * Indicates whether threaded rendering is currently enabled. 411 * 412 * @return True if threaded rendering is in use, false otherwise. 413 */ isEnabled()414 boolean isEnabled() { 415 return mEnabled; 416 } 417 418 /** 419 * Indicates whether threaded rendering is currently enabled. 420 * 421 * @param enabled True if the threaded renderer is in use, false otherwise. 422 */ setEnabled(boolean enabled)423 void setEnabled(boolean enabled) { 424 mEnabled = enabled; 425 } 426 427 /** 428 * Indicates whether threaded rendering is currently request but not 429 * necessarily enabled yet. 430 * 431 * @return True if requested, false otherwise. 432 */ isRequested()433 boolean isRequested() { 434 return mRequested; 435 } 436 437 /** 438 * Indicates whether threaded rendering is currently requested but not 439 * necessarily enabled yet. 440 */ setRequested(boolean requested)441 void setRequested(boolean requested) { 442 mRequested = requested; 443 } 444 updateEnabledState(Surface surface)445 private void updateEnabledState(Surface surface) { 446 if (surface == null || !surface.isValid()) { 447 setEnabled(false); 448 } else { 449 setEnabled(mInitialized); 450 } 451 } 452 453 /** 454 * Initializes the threaded renderer for the specified surface. 455 * 456 * @param surface The surface to render 457 * 458 * @return True if the initialization was successful, false otherwise. 459 */ initialize(Surface surface)460 boolean initialize(Surface surface) throws OutOfResourcesException { 461 boolean status = !mInitialized; 462 mInitialized = true; 463 updateEnabledState(surface); 464 nInitialize(mNativeProxy, surface); 465 return status; 466 } 467 468 /** 469 * Initializes the threaded renderer for the specified surface and setup the 470 * renderer for drawing, if needed. This is invoked when the ViewAncestor has 471 * potentially lost the threaded renderer. The threaded renderer should be 472 * reinitialized and setup when the render {@link #isRequested()} and 473 * {@link #isEnabled()}. 474 * 475 * @param width The width of the drawing surface. 476 * @param height The height of the drawing surface. 477 * @param attachInfo Information about the window. 478 * @param surface The surface to render 479 * @param surfaceInsets The drawing surface insets to apply 480 * 481 * @return true if the surface was initialized, false otherwise. Returning 482 * false might mean that the surface was already initialized. 483 */ initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, Surface surface, Rect surfaceInsets)484 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 485 Surface surface, Rect surfaceInsets) throws OutOfResourcesException { 486 if (isRequested()) { 487 // We lost the gl context, so recreate it. 488 if (!isEnabled()) { 489 if (initialize(surface)) { 490 setup(width, height, attachInfo, surfaceInsets); 491 return true; 492 } 493 } 494 } 495 return false; 496 } 497 498 /** 499 * Updates the threaded renderer for the specified surface. 500 * 501 * @param surface The surface to render 502 */ updateSurface(Surface surface)503 void updateSurface(Surface surface) throws OutOfResourcesException { 504 updateEnabledState(surface); 505 nUpdateSurface(mNativeProxy, surface); 506 } 507 508 /** 509 * Halts any current rendering into the surface. Use this if it is unclear whether 510 * or not the surface used by the ThreadedRenderer will be changing. It 511 * Suspends any rendering into the surface, but will not do any destruction. 512 * 513 * Any subsequent draws will override the pause, resuming normal operation. 514 */ pauseSurface(Surface surface)515 boolean pauseSurface(Surface surface) { 516 return nPauseSurface(mNativeProxy, surface); 517 } 518 519 /** 520 * Hard stops or resumes rendering into the surface. This flag is used to 521 * determine whether or not it is safe to use the given surface *at all* 522 */ setStopped(boolean stopped)523 void setStopped(boolean stopped) { 524 nSetStopped(mNativeProxy, stopped); 525 } 526 527 /** 528 * Destroys all hardware rendering resources associated with the specified 529 * view hierarchy. 530 * 531 * @param view The root of the view hierarchy 532 */ destroyHardwareResources(View view)533 void destroyHardwareResources(View view) { 534 destroyResources(view); 535 nDestroyHardwareResources(mNativeProxy); 536 } 537 destroyResources(View view)538 private static void destroyResources(View view) { 539 view.destroyHardwareResources(); 540 } 541 542 /** 543 * Detaches the layer's surface texture from the GL context and releases 544 * the texture id 545 */ detachSurfaceTexture(long hardwareLayer)546 void detachSurfaceTexture(long hardwareLayer) { 547 nDetachSurfaceTexture(mNativeProxy, hardwareLayer); 548 } 549 550 /** 551 * Sets up the renderer for drawing. 552 * 553 * @param width The width of the drawing surface. 554 * @param height The height of the drawing surface. 555 * @param attachInfo Information about the window. 556 * @param surfaceInsets The drawing surface insets to apply 557 */ setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets)558 void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) { 559 mWidth = width; 560 mHeight = height; 561 562 if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0 563 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) { 564 mHasInsets = true; 565 mInsetLeft = surfaceInsets.left; 566 mInsetTop = surfaceInsets.top; 567 mSurfaceWidth = width + mInsetLeft + surfaceInsets.right; 568 mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom; 569 570 // If the surface has insets, it can't be opaque. 571 setOpaque(false); 572 } else { 573 mHasInsets = false; 574 mInsetLeft = 0; 575 mInsetTop = 0; 576 mSurfaceWidth = width; 577 mSurfaceHeight = height; 578 } 579 580 mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight); 581 nSetup(mNativeProxy, mLightRadius, 582 mAmbientShadowAlpha, mSpotShadowAlpha); 583 584 setLightCenter(attachInfo); 585 } 586 587 /** 588 * Updates the light position based on the position of the window. 589 * 590 * @param attachInfo Information about the window. 591 */ setLightCenter(AttachInfo attachInfo)592 void setLightCenter(AttachInfo attachInfo) { 593 // Adjust light position for window offsets. 594 final Point displaySize = attachInfo.mPoint; 595 attachInfo.mDisplay.getRealSize(displaySize); 596 final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft; 597 final float lightY = mLightY - attachInfo.mWindowTop; 598 599 nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ); 600 } 601 602 /** 603 * Change the ThreadedRenderer's opacity 604 */ setOpaque(boolean opaque)605 void setOpaque(boolean opaque) { 606 mIsOpaque = opaque && !mHasInsets; 607 nSetOpaque(mNativeProxy, mIsOpaque); 608 } 609 isOpaque()610 boolean isOpaque() { 611 return mIsOpaque; 612 } 613 614 /** 615 * Enable/disable wide gamut rendering on this renderer. 616 */ setWideGamut(boolean wideGamut)617 void setWideGamut(boolean wideGamut) { 618 nSetWideGamut(mNativeProxy, wideGamut); 619 } 620 621 /** 622 * Gets the current width of the surface. This is the width that the surface 623 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 624 * 625 * @return the current width of the surface 626 */ getWidth()627 int getWidth() { 628 return mWidth; 629 } 630 631 /** 632 * Gets the current height of the surface. This is the height that the surface 633 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 634 * 635 * @return the current width of the surface 636 */ getHeight()637 int getHeight() { 638 return mHeight; 639 } 640 641 /** 642 * Outputs extra debugging information in the specified file descriptor. 643 */ dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args)644 void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) { 645 pw.flush(); 646 // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything. 647 // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only 648 // dump the summary information 649 int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0; 650 for (int i = 0; i < args.length; i++) { 651 switch (args[i]) { 652 case "framestats": 653 flags |= FLAG_DUMP_FRAMESTATS; 654 break; 655 case "reset": 656 flags |= FLAG_DUMP_RESET; 657 break; 658 case "-a": // magic option passed when dumping a bugreport. 659 flags = FLAG_DUMP_ALL; 660 break; 661 } 662 } 663 nDumpProfileInfo(mNativeProxy, fd, flags); 664 } 665 666 /** 667 * Loads system properties used by the renderer. This method is invoked 668 * whenever system properties are modified. Implementations can use this 669 * to trigger live updates of the renderer based on properties. 670 * 671 * @return True if a property has changed. 672 */ loadSystemProperties()673 boolean loadSystemProperties() { 674 boolean changed = nLoadSystemProperties(mNativeProxy); 675 if (changed) { 676 invalidateRoot(); 677 } 678 return changed; 679 } 680 updateViewTreeDisplayList(View view)681 private void updateViewTreeDisplayList(View view) { 682 view.mPrivateFlags |= View.PFLAG_DRAWN; 683 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) 684 == View.PFLAG_INVALIDATED; 685 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; 686 view.updateDisplayListIfDirty(); 687 view.mRecreateDisplayList = false; 688 } 689 updateRootDisplayList(View view, DrawCallbacks callbacks)690 private void updateRootDisplayList(View view, DrawCallbacks callbacks) { 691 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()"); 692 updateViewTreeDisplayList(view); 693 694 if (mRootNodeNeedsUpdate || !mRootNode.isValid()) { 695 DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight); 696 try { 697 final int saveCount = canvas.save(); 698 canvas.translate(mInsetLeft, mInsetTop); 699 callbacks.onPreDraw(canvas); 700 701 canvas.insertReorderBarrier(); 702 canvas.drawRenderNode(view.updateDisplayListIfDirty()); 703 canvas.insertInorderBarrier(); 704 705 callbacks.onPostDraw(canvas); 706 canvas.restoreToCount(saveCount); 707 mRootNodeNeedsUpdate = false; 708 } finally { 709 mRootNode.end(canvas); 710 } 711 } 712 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 713 } 714 715 /** 716 * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the 717 * rendernode of the UI thread. 718 * @param node The node to add. 719 * @param placeFront If true, the render node will be placed in front of the content node, 720 * otherwise behind the content node. 721 */ addRenderNode(RenderNode node, boolean placeFront)722 public void addRenderNode(RenderNode node, boolean placeFront) { 723 nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront); 724 } 725 726 /** 727 * Only especially added render nodes can be removed. 728 * @param node The node which was added via addRenderNode which should get removed again. 729 */ removeRenderNode(RenderNode node)730 public void removeRenderNode(RenderNode node) { 731 nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode); 732 } 733 734 /** 735 * Draws a particular render node. If the node is not the content node, only the additional 736 * nodes will get drawn and the content remains untouched. 737 * @param node The node to be drawn. 738 */ drawRenderNode(RenderNode node)739 public void drawRenderNode(RenderNode node) { 740 nDrawRenderNode(mNativeProxy, node.mNativeRenderNode); 741 } 742 743 /** 744 * To avoid unnecessary overdrawing of the main content all additionally passed render nodes 745 * will be prevented to overdraw this area. It will be synchronized with the draw call. 746 * This should be updated in the content view's draw call. 747 * @param left The left side of the protected bounds. 748 * @param top The top side of the protected bounds. 749 * @param right The right side of the protected bounds. 750 * @param bottom The bottom side of the protected bounds. 751 */ setContentDrawBounds(int left, int top, int right, int bottom)752 public void setContentDrawBounds(int left, int top, int right, int bottom) { 753 nSetContentDrawBounds(mNativeProxy, left, top, right, bottom); 754 } 755 756 /** 757 * Interface used to receive callbacks whenever a view is drawn by 758 * a threaded renderer instance. 759 */ 760 interface DrawCallbacks { 761 /** 762 * Invoked before a view is drawn by a threaded renderer. 763 * This method can be used to apply transformations to the 764 * canvas but no drawing command should be issued. 765 * 766 * @param canvas The Canvas used to render the view. 767 */ onPreDraw(DisplayListCanvas canvas)768 void onPreDraw(DisplayListCanvas canvas); 769 770 /** 771 * Invoked after a view is drawn by a threaded renderer. 772 * It is safe to invoke drawing commands from this method. 773 * 774 * @param canvas The Canvas used to render the view. 775 */ onPostDraw(DisplayListCanvas canvas)776 void onPostDraw(DisplayListCanvas canvas); 777 } 778 779 /** 780 * Indicates that the content drawn by DrawCallbacks needs to 781 * be updated, which will be done by the next call to draw() 782 */ invalidateRoot()783 void invalidateRoot() { 784 mRootNodeNeedsUpdate = true; 785 } 786 787 /** 788 * Draws the specified view. 789 * 790 * @param view The view to draw. 791 * @param attachInfo AttachInfo tied to the specified view. 792 * @param callbacks Callbacks invoked when drawing happens. 793 */ draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks, FrameDrawingCallback frameDrawingCallback)794 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks, 795 FrameDrawingCallback frameDrawingCallback) { 796 attachInfo.mIgnoreDirtyState = true; 797 798 final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer; 799 choreographer.mFrameInfo.markDrawStart(); 800 801 updateRootDisplayList(view, callbacks); 802 803 attachInfo.mIgnoreDirtyState = false; 804 805 // register animating rendernodes which started animating prior to renderer 806 // creation, which is typical for animators started prior to first draw 807 if (attachInfo.mPendingAnimatingRenderNodes != null) { 808 final int count = attachInfo.mPendingAnimatingRenderNodes.size(); 809 for (int i = 0; i < count; i++) { 810 registerAnimatingRenderNode( 811 attachInfo.mPendingAnimatingRenderNodes.get(i)); 812 } 813 attachInfo.mPendingAnimatingRenderNodes.clear(); 814 // We don't need this anymore as subsequent calls to 815 // ViewRootImpl#attachRenderNodeAnimator will go directly to us. 816 attachInfo.mPendingAnimatingRenderNodes = null; 817 } 818 819 final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo; 820 if (frameDrawingCallback != null) { 821 nSetFrameCallback(mNativeProxy, frameDrawingCallback); 822 } 823 int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length); 824 if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) { 825 setEnabled(false); 826 attachInfo.mViewRootImpl.mSurface.release(); 827 // Invalidate since we failed to draw. This should fetch a Surface 828 // if it is still needed or do nothing if we are no longer drawing 829 attachInfo.mViewRootImpl.invalidate(); 830 } 831 if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) { 832 attachInfo.mViewRootImpl.invalidate(); 833 } 834 } 835 setFrameCompleteCallback(FrameCompleteCallback callback)836 void setFrameCompleteCallback(FrameCompleteCallback callback) { 837 nSetFrameCompleteCallback(mNativeProxy, callback); 838 } 839 invokeFunctor(long functor, boolean waitForCompletion)840 static void invokeFunctor(long functor, boolean waitForCompletion) { 841 nInvokeFunctor(functor, waitForCompletion); 842 } 843 844 /** 845 * Creates a new hardware layer. A hardware layer built by calling this 846 * method will be treated as a texture layer, instead of as a render target. 847 * 848 * @return A hardware layer 849 */ createTextureLayer()850 TextureLayer createTextureLayer() { 851 long layer = nCreateTextureLayer(mNativeProxy); 852 return TextureLayer.adoptTextureLayer(this, layer); 853 } 854 855 buildLayer(RenderNode node)856 void buildLayer(RenderNode node) { 857 nBuildLayer(mNativeProxy, node.getNativeDisplayList()); 858 } 859 860 copyLayerInto(final TextureLayer layer, final Bitmap bitmap)861 boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) { 862 return nCopyLayerInto(mNativeProxy, 863 layer.getDeferredLayerUpdater(), bitmap); 864 } 865 866 /** 867 * Indicates that the specified hardware layer needs to be updated 868 * as soon as possible. 869 * 870 * @param layer The hardware layer that needs an update 871 */ pushLayerUpdate(TextureLayer layer)872 void pushLayerUpdate(TextureLayer layer) { 873 nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); 874 } 875 876 /** 877 * Tells the HardwareRenderer that the layer is destroyed. The renderer 878 * should remove the layer from any update queues. 879 */ onLayerDestroyed(TextureLayer layer)880 void onLayerDestroyed(TextureLayer layer) { 881 nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); 882 } 883 884 /** 885 * Blocks until all previously queued work has completed. 886 */ fence()887 void fence() { 888 nFence(mNativeProxy); 889 } 890 891 /** 892 * Prevents any further drawing until draw() is called. This is a signal 893 * that the contents of the RenderNode tree are no longer safe to play back. 894 * In practice this usually means that there are Functor pointers in the 895 * display list that are no longer valid. 896 */ stopDrawing()897 void stopDrawing() { 898 nStopDrawing(mNativeProxy); 899 } 900 901 /** 902 * Called by {@link ViewRootImpl} when a new performTraverals is scheduled. 903 */ notifyFramePending()904 public void notifyFramePending() { 905 nNotifyFramePending(mNativeProxy); 906 } 907 908 registerAnimatingRenderNode(RenderNode animator)909 void registerAnimatingRenderNode(RenderNode animator) { 910 nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode); 911 } 912 registerVectorDrawableAnimator( AnimatedVectorDrawable.VectorDrawableAnimatorRT animator)913 void registerVectorDrawableAnimator( 914 AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) { 915 nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode, 916 animator.getAnimatorNativePtr()); 917 } 918 serializeDisplayListTree()919 public void serializeDisplayListTree() { 920 nSerializeDisplayListTree(mNativeProxy); 921 } 922 copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap)923 public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) { 924 if (srcRect == null) { 925 // Empty rect means entire surface 926 return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap); 927 } else { 928 return nCopySurfaceInto(surface, srcRect.left, srcRect.top, 929 srcRect.right, srcRect.bottom, bitmap); 930 } 931 } 932 933 /** 934 * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given 935 * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and 936 * not the RenderNode from a View. 937 **/ createHardwareBitmap(RenderNode node, int width, int height)938 public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) { 939 return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height); 940 } 941 942 /** 943 * Sets whether or not high contrast text rendering is enabled. The setting is global 944 * but only affects content rendered after the change is made. 945 */ setHighContrastText(boolean highContrastText)946 public static void setHighContrastText(boolean highContrastText) { 947 nSetHighContrastText(highContrastText); 948 } 949 950 /** 951 * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source 952 */ setIsolatedProcess(boolean isIsolated)953 public static void setIsolatedProcess(boolean isIsolated) { 954 nSetIsolatedProcess(isIsolated); 955 } 956 957 /** 958 * If set extra graphics debugging abilities will be enabled such as dumping skp 959 */ setDebuggingEnabled(boolean enable)960 public static void setDebuggingEnabled(boolean enable) { 961 nSetDebuggingEnabled(enable); 962 } 963 964 @Override finalize()965 protected void finalize() throws Throwable { 966 try { 967 nDeleteProxy(mNativeProxy); 968 mNativeProxy = 0; 969 } finally { 970 super.finalize(); 971 } 972 } 973 974 /** 975 * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care. 976 * TODO: deduplicate against ThreadedRenderer. 977 * 978 * @hide 979 */ 980 public static class SimpleRenderer { 981 private final RenderNode mRootNode; 982 private long mNativeProxy; 983 private final float mLightY, mLightZ; 984 private Surface mSurface; 985 private final FrameInfo mFrameInfo = new FrameInfo(); 986 SimpleRenderer(final Context context, final String name, final Surface surface)987 public SimpleRenderer(final Context context, final String name, final Surface surface) { 988 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0); 989 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0); 990 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0); 991 final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0); 992 final int ambientShadowAlpha = 993 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f); 994 final int spotShadowAlpha = 995 (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f); 996 a.recycle(); 997 998 final long rootNodePtr = nCreateRootRenderNode(); 999 mRootNode = RenderNode.adopt(rootNodePtr); 1000 mRootNode.setClipToBounds(false); 1001 mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr); 1002 nSetName(mNativeProxy, name); 1003 1004 ProcessInitializer.sInstance.init(context, mNativeProxy); 1005 nLoadSystemProperties(mNativeProxy); 1006 1007 nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha); 1008 1009 mSurface = surface; 1010 nUpdateSurface(mNativeProxy, surface); 1011 } 1012 1013 /** 1014 * Set the light center. 1015 */ setLightCenter(final Display display, final int windowLeft, final int windowTop)1016 public void setLightCenter(final Display display, 1017 final int windowLeft, final int windowTop) { 1018 // Adjust light position for window offsets. 1019 final Point displaySize = new Point(); 1020 display.getRealSize(displaySize); 1021 final float lightX = displaySize.x / 2f - windowLeft; 1022 final float lightY = mLightY - windowTop; 1023 1024 nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ); 1025 } 1026 getRootNode()1027 public RenderNode getRootNode() { 1028 return mRootNode; 1029 } 1030 1031 /** 1032 * Draw the surface. 1033 */ draw(final FrameDrawingCallback callback)1034 public void draw(final FrameDrawingCallback callback) { 1035 final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L; 1036 mFrameInfo.setVsync(vsync, vsync); 1037 mFrameInfo.addFlags(1 << 2 /* VSYNC */); 1038 if (callback != null) { 1039 nSetFrameCallback(mNativeProxy, callback); 1040 } 1041 nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length); 1042 } 1043 1044 /** 1045 * Destroy the renderer. 1046 */ destroy()1047 public void destroy() { 1048 mSurface = null; 1049 nDestroy(mNativeProxy, mRootNode.mNativeRenderNode); 1050 } 1051 1052 @Override finalize()1053 protected void finalize() throws Throwable { 1054 try { 1055 nDeleteProxy(mNativeProxy); 1056 mNativeProxy = 0; 1057 } finally { 1058 super.finalize(); 1059 } 1060 } 1061 } 1062 1063 /** 1064 * Interface used to receive callbacks when a frame is being drawn. 1065 */ 1066 public interface FrameDrawingCallback { 1067 /** 1068 * Invoked during a frame drawing. 1069 * 1070 * @param frame The id of the frame being drawn. 1071 */ onFrameDraw(long frame)1072 void onFrameDraw(long frame); 1073 } 1074 1075 /** 1076 * Interface used to be notified when a frame has finished rendering 1077 */ 1078 public interface FrameCompleteCallback { 1079 /** 1080 * Invoked after a frame draw 1081 * 1082 * @param frameNr The id of the frame that was drawn. 1083 */ onFrameComplete(long frameNr)1084 void onFrameComplete(long frameNr); 1085 } 1086 1087 private static class ProcessInitializer { 1088 static ProcessInitializer sInstance = new ProcessInitializer(); 1089 1090 private boolean mInitialized = false; 1091 1092 private Context mAppContext; 1093 private IGraphicsStats mGraphicsStatsService; 1094 private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() { 1095 @Override 1096 public void onRotateGraphicsStatsBuffer() throws RemoteException { 1097 rotateBuffer(); 1098 } 1099 }; 1100 ProcessInitializer()1101 private ProcessInitializer() {} 1102 init(Context context, long renderProxy)1103 synchronized void init(Context context, long renderProxy) { 1104 if (mInitialized) return; 1105 mInitialized = true; 1106 mAppContext = context.getApplicationContext(); 1107 1108 initSched(renderProxy); 1109 1110 if (mAppContext != null) { 1111 initGraphicsStats(); 1112 } 1113 } 1114 initSched(long renderProxy)1115 private void initSched(long renderProxy) { 1116 try { 1117 int tid = nGetRenderThreadTid(renderProxy); 1118 ActivityManager.getService().setRenderThread(tid); 1119 } catch (Throwable t) { 1120 Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t); 1121 } 1122 } 1123 initGraphicsStats()1124 private void initGraphicsStats() { 1125 try { 1126 IBinder binder = ServiceManager.getService("graphicsstats"); 1127 if (binder == null) return; 1128 mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder); 1129 requestBuffer(); 1130 } catch (Throwable t) { 1131 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); 1132 } 1133 } 1134 rotateBuffer()1135 private void rotateBuffer() { 1136 nRotateProcessStatsBuffer(); 1137 requestBuffer(); 1138 } 1139 requestBuffer()1140 private void requestBuffer() { 1141 try { 1142 final String pkg = mAppContext.getApplicationInfo().packageName; 1143 ParcelFileDescriptor pfd = mGraphicsStatsService 1144 .requestBufferForProcess(pkg, mGraphicsStatsCallback); 1145 nSetProcessStatsBuffer(pfd.getFd()); 1146 pfd.close(); 1147 } catch (Throwable t) { 1148 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); 1149 } 1150 } 1151 } 1152 addFrameMetricsObserver(FrameMetricsObserver observer)1153 void addFrameMetricsObserver(FrameMetricsObserver observer) { 1154 long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer); 1155 observer.mNative = new VirtualRefBasePtr(nativeObserver); 1156 } 1157 removeFrameMetricsObserver(FrameMetricsObserver observer)1158 void removeFrameMetricsObserver(FrameMetricsObserver observer) { 1159 nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get()); 1160 observer.mNative = null; 1161 } 1162 1163 /** b/68769804: For low FPS experiments. */ setFPSDivisor(int divisor)1164 public static void setFPSDivisor(int divisor) { 1165 nHackySetRTAnimationsEnabled(divisor <= 1); 1166 } 1167 1168 /** 1169 * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be 1170 * called before any OpenGL context is created. 1171 * 1172 * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values. 1173 */ setContextPriority(int priority)1174 public static void setContextPriority(int priority) { 1175 nSetContextPriority(priority); 1176 } 1177 1178 /** Not actually public - internal use only. This doc to make lint happy */ disableVsync()1179 public static native void disableVsync(); 1180 setupShadersDiskCache(String cacheFile, String skiaCacheFile)1181 static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile); 1182 nRotateProcessStatsBuffer()1183 private static native void nRotateProcessStatsBuffer(); nSetProcessStatsBuffer(int fd)1184 private static native void nSetProcessStatsBuffer(int fd); nGetRenderThreadTid(long nativeProxy)1185 private static native int nGetRenderThreadTid(long nativeProxy); 1186 nCreateRootRenderNode()1187 private static native long nCreateRootRenderNode(); nCreateProxy(boolean translucent, long rootRenderNode)1188 private static native long nCreateProxy(boolean translucent, long rootRenderNode); nDeleteProxy(long nativeProxy)1189 private static native void nDeleteProxy(long nativeProxy); 1190 nLoadSystemProperties(long nativeProxy)1191 private static native boolean nLoadSystemProperties(long nativeProxy); nSetName(long nativeProxy, String name)1192 private static native void nSetName(long nativeProxy, String name); 1193 nInitialize(long nativeProxy, Surface window)1194 private static native void nInitialize(long nativeProxy, Surface window); nUpdateSurface(long nativeProxy, Surface window)1195 private static native void nUpdateSurface(long nativeProxy, Surface window); nPauseSurface(long nativeProxy, Surface window)1196 private static native boolean nPauseSurface(long nativeProxy, Surface window); nSetStopped(long nativeProxy, boolean stopped)1197 private static native void nSetStopped(long nativeProxy, boolean stopped); nSetup(long nativeProxy, float lightRadius, int ambientShadowAlpha, int spotShadowAlpha)1198 private static native void nSetup(long nativeProxy, 1199 float lightRadius, int ambientShadowAlpha, int spotShadowAlpha); nSetLightCenter(long nativeProxy, float lightX, float lightY, float lightZ)1200 private static native void nSetLightCenter(long nativeProxy, 1201 float lightX, float lightY, float lightZ); nSetOpaque(long nativeProxy, boolean opaque)1202 private static native void nSetOpaque(long nativeProxy, boolean opaque); nSetWideGamut(long nativeProxy, boolean wideGamut)1203 private static native void nSetWideGamut(long nativeProxy, boolean wideGamut); nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size)1204 private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); nDestroy(long nativeProxy, long rootRenderNode)1205 private static native void nDestroy(long nativeProxy, long rootRenderNode); nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode)1206 private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); nRegisterVectorDrawableAnimator(long rootRenderNode, long animator)1207 private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator); 1208 nInvokeFunctor(long functor, boolean waitForCompletion)1209 private static native void nInvokeFunctor(long functor, boolean waitForCompletion); 1210 nCreateTextureLayer(long nativeProxy)1211 private static native long nCreateTextureLayer(long nativeProxy); nBuildLayer(long nativeProxy, long node)1212 private static native void nBuildLayer(long nativeProxy, long node); nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap)1213 private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap); nPushLayerUpdate(long nativeProxy, long layer)1214 private static native void nPushLayerUpdate(long nativeProxy, long layer); nCancelLayerUpdate(long nativeProxy, long layer)1215 private static native void nCancelLayerUpdate(long nativeProxy, long layer); nDetachSurfaceTexture(long nativeProxy, long layer)1216 private static native void nDetachSurfaceTexture(long nativeProxy, long layer); 1217 nDestroyHardwareResources(long nativeProxy)1218 private static native void nDestroyHardwareResources(long nativeProxy); nTrimMemory(int level)1219 private static native void nTrimMemory(int level); nOverrideProperty(String name, String value)1220 private static native void nOverrideProperty(String name, String value); 1221 nFence(long nativeProxy)1222 private static native void nFence(long nativeProxy); nStopDrawing(long nativeProxy)1223 private static native void nStopDrawing(long nativeProxy); nNotifyFramePending(long nativeProxy)1224 private static native void nNotifyFramePending(long nativeProxy); 1225 nSerializeDisplayListTree(long nativeProxy)1226 private static native void nSerializeDisplayListTree(long nativeProxy); 1227 nDumpProfileInfo(long nativeProxy, FileDescriptor fd, @DumpFlags int dumpFlags)1228 private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd, 1229 @DumpFlags int dumpFlags); 1230 nAddRenderNode(long nativeProxy, long rootRenderNode, boolean placeFront)1231 private static native void nAddRenderNode(long nativeProxy, long rootRenderNode, 1232 boolean placeFront); nRemoveRenderNode(long nativeProxy, long rootRenderNode)1233 private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode); nDrawRenderNode(long nativeProxy, long rootRenderNode)1234 private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode); nSetContentDrawBounds(long nativeProxy, int left, int top, int right, int bottom)1235 private static native void nSetContentDrawBounds(long nativeProxy, int left, 1236 int top, int right, int bottom); nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback)1237 private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback)1238 private static native void nSetFrameCompleteCallback(long nativeProxy, 1239 FrameCompleteCallback callback); 1240 nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer)1241 private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer); nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver)1242 private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); 1243 nCopySurfaceInto(Surface surface, int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap)1244 private static native int nCopySurfaceInto(Surface surface, 1245 int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap); 1246 nCreateHardwareBitmap(long renderNode, int width, int height)1247 private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height); nSetHighContrastText(boolean enabled)1248 private static native void nSetHighContrastText(boolean enabled); 1249 // For temporary experimentation b/66945974 nHackySetRTAnimationsEnabled(boolean enabled)1250 private static native void nHackySetRTAnimationsEnabled(boolean enabled); nSetDebuggingEnabled(boolean enabled)1251 private static native void nSetDebuggingEnabled(boolean enabled); nSetIsolatedProcess(boolean enabled)1252 private static native void nSetIsolatedProcess(boolean enabled); nSetContextPriority(int priority)1253 private static native void nSetContextPriority(int priority); 1254 } 1255