1 /* 2 * Copyright (C) 2015 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 com.android.server.wm; 18 19 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 20 import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; 21 import static android.view.SurfaceControl.METADATA_OWNER_UID; 22 import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; 23 24 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 25 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 27 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 30 import static com.android.server.wm.WindowSurfaceControllerProto.LAYER; 31 import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN; 32 33 import android.graphics.Rect; 34 import android.graphics.Region; 35 import android.os.Debug; 36 import android.os.Trace; 37 import android.util.Slog; 38 import android.util.proto.ProtoOutputStream; 39 import android.view.SurfaceControl; 40 import android.view.WindowContentFrameStats; 41 import android.view.WindowManager; 42 43 import com.android.server.protolog.common.ProtoLog; 44 45 import java.io.PrintWriter; 46 47 class WindowSurfaceController { 48 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfaceController" : TAG_WM; 49 50 final WindowStateAnimator mAnimator; 51 52 SurfaceControl mSurfaceControl; 53 54 /** 55 * WM only uses for deferred transactions. 56 */ 57 SurfaceControl mBLASTSurfaceControl; 58 59 // Should only be set from within setShown(). 60 private boolean mSurfaceShown = false; 61 private float mSurfaceX = 0; 62 private float mSurfaceY = 0; 63 private int mSurfaceW = 0; 64 private int mSurfaceH = 0; 65 private Rect mSurfaceCrop = new Rect(0, 0, -1, -1); 66 67 // Initialize to the identity matrix. 68 private float mLastDsdx = 1; 69 private float mLastDtdx = 0; 70 private float mLastDsdy = 0; 71 private float mLastDtdy = 1; 72 73 private float mSurfaceAlpha = 0; 74 75 private int mSurfaceLayer = 0; 76 77 // Surface flinger doesn't support crop rectangles where width or height is non-positive. 78 // However, we need to somehow handle the situation where the cropping would completely hide 79 // the window. We achieve this by explicitly hiding the surface and not letting it be shown. 80 private boolean mHiddenForCrop = false; 81 82 // Initially a surface is hidden after just being created. 83 private boolean mHiddenForOtherReasons = true; 84 private final String title; 85 86 private final WindowManagerService mService; 87 88 private final int mWindowType; 89 private final Session mWindowSession; 90 91 private final SurfaceControl.Transaction mTmpTransaction; 92 93 // Used to track whether we have called detach children on the way to invisibility. 94 boolean mChildrenDetached; 95 WindowSurfaceController(String name, int w, int h, int format, int flags, WindowStateAnimator animator, int windowType, int ownerUid)96 WindowSurfaceController(String name, int w, int h, int format, 97 int flags, WindowStateAnimator animator, int windowType, int ownerUid) { 98 mAnimator = animator; 99 100 mSurfaceW = w; 101 mSurfaceH = h; 102 103 title = name; 104 105 mService = animator.mService; 106 final WindowState win = animator.mWin; 107 mWindowType = windowType; 108 mWindowSession = win.mSession; 109 mTmpTransaction = mService.mTransactionFactory.get(); 110 111 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl"); 112 final SurfaceControl.Builder b = win.makeSurface() 113 .setParent(win.getSurfaceControl()) 114 .setName(name) 115 .setBufferSize(w, h) 116 .setFormat(format) 117 .setFlags(flags) 118 .setMetadata(METADATA_WINDOW_TYPE, windowType) 119 .setMetadata(METADATA_OWNER_UID, ownerUid) 120 .setCallsite("WindowSurfaceController"); 121 122 final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags & 123 WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0); 124 if (useBLAST) { 125 b.setContainerLayer(); 126 } 127 128 mSurfaceControl = b.build(); 129 130 if (useBLAST) { 131 mBLASTSurfaceControl = win.makeSurface() 132 .setParent(mSurfaceControl) 133 .setName(name + "(BLAST)") 134 .setHidden(false) 135 .setBLASTLayer() 136 .setCallsite("WindowSurfaceController") 137 .build(); 138 } 139 140 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 141 } 142 reparentChildrenInTransaction(WindowSurfaceController other)143 void reparentChildrenInTransaction(WindowSurfaceController other) { 144 ProtoLog.i(WM_SHOW_TRANSACTIONS, "REPARENT from: %s to: %s", this, other); 145 if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) { 146 mSurfaceControl.reparentChildren(other.mSurfaceControl); 147 } 148 } 149 detachChildren()150 void detachChildren() { 151 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SEVER CHILDREN"); 152 mChildrenDetached = true; 153 if (mSurfaceControl != null) { 154 mSurfaceControl.detachChildren(); 155 } 156 } 157 hide(SurfaceControl.Transaction transaction, String reason)158 void hide(SurfaceControl.Transaction transaction, String reason) { 159 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title); 160 mHiddenForOtherReasons = true; 161 162 mAnimator.destroyPreservedSurfaceLocked(); 163 if (mSurfaceShown) { 164 hideSurface(transaction); 165 } 166 } 167 hideSurface(SurfaceControl.Transaction transaction)168 private void hideSurface(SurfaceControl.Transaction transaction) { 169 if (mSurfaceControl == null) { 170 return; 171 } 172 setShown(false); 173 try { 174 transaction.hide(mSurfaceControl); 175 } catch (RuntimeException e) { 176 Slog.w(TAG, "Exception hiding surface in " + this); 177 } 178 } 179 destroyNotInTransaction()180 void destroyNotInTransaction() { 181 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 182 "Destroying surface %s called by %s", this, Debug.getCallers(8)); 183 try { 184 if (mSurfaceControl != null) { 185 mTmpTransaction.remove(mSurfaceControl).apply(); 186 } 187 } catch (RuntimeException e) { 188 Slog.w(TAG, "Error destroying surface in: " + this, e); 189 } finally { 190 setShown(false); 191 mSurfaceControl = null; 192 if (mBLASTSurfaceControl != null) { 193 mBLASTSurfaceControl.release(); 194 } 195 } 196 } 197 setCropInTransaction(Rect clipRect, boolean recoveringMemory)198 void setCropInTransaction(Rect clipRect, boolean recoveringMemory) { 199 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE CROP %s: %s", clipRect.toShortString(), title); 200 try { 201 if (clipRect.width() > 0 && clipRect.height() > 0) { 202 if (!clipRect.equals(mSurfaceCrop)) { 203 mSurfaceControl.setWindowCrop(clipRect); 204 mSurfaceCrop.set(clipRect); 205 } 206 mHiddenForCrop = false; 207 updateVisibility(); 208 } else { 209 mHiddenForCrop = true; 210 mAnimator.destroyPreservedSurfaceLocked(); 211 updateVisibility(); 212 } 213 } catch (RuntimeException e) { 214 Slog.w(TAG, "Error setting crop surface of " + this 215 + " crop=" + clipRect.toShortString(), e); 216 if (!recoveringMemory) { 217 mAnimator.reclaimSomeSurfaceMemory("crop", true); 218 } 219 } 220 } 221 clearCropInTransaction(boolean recoveringMemory)222 void clearCropInTransaction(boolean recoveringMemory) { 223 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE CLEAR CROP: %s", title); 224 try { 225 Rect clipRect = new Rect(0, 0, -1, -1); 226 if (mSurfaceCrop.equals(clipRect)) { 227 return; 228 } 229 mSurfaceControl.setWindowCrop(clipRect); 230 mSurfaceCrop.set(clipRect); 231 } catch (RuntimeException e) { 232 Slog.w(TAG, "Error setting clearing crop of " + this, e); 233 if (!recoveringMemory) { 234 mAnimator.reclaimSomeSurfaceMemory("crop", true); 235 } 236 } 237 } 238 setPositionInTransaction(float left, float top, boolean recoveringMemory)239 void setPositionInTransaction(float left, float top, boolean recoveringMemory) { 240 setPosition(null, left, top, recoveringMemory); 241 } 242 setPosition(SurfaceControl.Transaction t, float left, float top, boolean recoveringMemory)243 void setPosition(SurfaceControl.Transaction t, float left, float top, 244 boolean recoveringMemory) { 245 final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; 246 if (surfaceMoved) { 247 mSurfaceX = left; 248 mSurfaceY = top; 249 250 try { 251 ProtoLog.i(WM_SHOW_TRANSACTIONS, 252 "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title); 253 254 if (t == null) { 255 mSurfaceControl.setPosition(left, top); 256 } else { 257 t.setPosition(mSurfaceControl, left, top); 258 } 259 } catch (RuntimeException e) { 260 Slog.w(TAG, "Error positioning surface of " + this 261 + " pos=(" + left + "," + top + ")", e); 262 if (!recoveringMemory) { 263 mAnimator.reclaimSomeSurfaceMemory("position", true); 264 } 265 } 266 } 267 } 268 setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy, boolean recoveringMemory)269 void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy, 270 boolean recoveringMemory) { 271 setMatrix(null, dsdx, dtdx, dtdy, dsdy, false); 272 } 273 setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy, boolean recoveringMemory)274 void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, 275 float dtdy, float dsdy, boolean recoveringMemory) { 276 final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx || 277 mLastDtdy != dtdy || mLastDsdy != dsdy; 278 if (!matrixChanged) { 279 return; 280 } 281 282 mLastDsdx = dsdx; 283 mLastDtdx = dtdx; 284 mLastDtdy = dtdy; 285 mLastDsdy = dsdy; 286 287 try { 288 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s", 289 dsdx, dtdx, dtdy, dsdy, title); 290 if (t == null) { 291 mSurfaceControl.setMatrix(dsdx, dtdx, dtdy, dsdy); 292 } else { 293 t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); 294 } 295 } catch (RuntimeException e) { 296 // If something goes wrong with the surface (such 297 // as running out of memory), don't take down the 298 // entire system. 299 Slog.e(TAG, "Error setting matrix on surface surface" + title 300 + " MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null); 301 if (!recoveringMemory) { 302 mAnimator.reclaimSomeSurfaceMemory("matrix", true); 303 } 304 } 305 } 306 setBufferSizeInTransaction(int width, int height, boolean recoveringMemory)307 boolean setBufferSizeInTransaction(int width, int height, boolean recoveringMemory) { 308 final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height; 309 if (surfaceResized) { 310 mSurfaceW = width; 311 mSurfaceH = height; 312 313 try { 314 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SIZE %dx%d: %s", width, height, title); 315 mSurfaceControl.setBufferSize(width, height); 316 } catch (RuntimeException e) { 317 // If something goes wrong with the surface (such 318 // as running out of memory), don't take down the 319 // entire system. 320 Slog.e(TAG, "Error resizing surface of " + title 321 + " size=(" + width + "x" + height + ")", e); 322 if (!recoveringMemory) { 323 mAnimator.reclaimSomeSurfaceMemory("size", true); 324 } 325 return false; 326 } 327 return true; 328 } 329 return false; 330 } 331 prepareToShowInTransaction(float alpha, float dsdx, float dtdx, float dsdy, float dtdy, boolean recoveringMemory)332 boolean prepareToShowInTransaction(float alpha, 333 float dsdx, float dtdx, float dsdy, 334 float dtdy, boolean recoveringMemory) { 335 if (mSurfaceControl != null) { 336 try { 337 mSurfaceAlpha = alpha; 338 mSurfaceControl.setAlpha(alpha); 339 mLastDsdx = dsdx; 340 mLastDtdx = dtdx; 341 mLastDsdy = dsdy; 342 mLastDtdy = dtdy; 343 mSurfaceControl.setMatrix( 344 dsdx, dtdx, dsdy, dtdy); 345 } catch (RuntimeException e) { 346 Slog.w(TAG, "Error updating surface in " + title, e); 347 if (!recoveringMemory) { 348 mAnimator.reclaimSomeSurfaceMemory("update", true); 349 } 350 return false; 351 } 352 } 353 return true; 354 } 355 setTransparentRegionHint(final Region region)356 void setTransparentRegionHint(final Region region) { 357 if (mSurfaceControl == null) { 358 Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); 359 return; 360 } 361 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion"); 362 mService.openSurfaceTransaction(); 363 try { 364 mSurfaceControl.setTransparentRegionHint(region); 365 } finally { 366 mService.closeSurfaceTransaction("setTransparentRegion"); 367 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 368 "<<< CLOSE TRANSACTION setTransparentRegion"); 369 } 370 } 371 setOpaque(boolean isOpaque)372 void setOpaque(boolean isOpaque) { 373 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isOpaque=%b: %s", isOpaque, title); 374 375 if (mSurfaceControl == null) { 376 return; 377 } 378 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked"); 379 mService.openSurfaceTransaction(); 380 try { 381 mSurfaceControl.setOpaque(isOpaque); 382 } finally { 383 mService.closeSurfaceTransaction("setOpaqueLocked"); 384 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked"); 385 } 386 } 387 setSecure(boolean isSecure)388 void setSecure(boolean isSecure) { 389 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title); 390 391 if (mSurfaceControl == null) { 392 return; 393 } 394 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked"); 395 mService.openSurfaceTransaction(); 396 try { 397 mSurfaceControl.setSecure(isSecure); 398 } finally { 399 mService.closeSurfaceTransaction("setSecure"); 400 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked"); 401 } 402 } 403 setColorSpaceAgnostic(boolean agnostic)404 void setColorSpaceAgnostic(boolean agnostic) { 405 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isColorSpaceAgnostic=%b: %s", agnostic, title); 406 407 if (mSurfaceControl == null) { 408 return; 409 } 410 if (SHOW_LIGHT_TRANSACTIONS) { 411 Slog.i(TAG, ">>> OPEN TRANSACTION setColorSpaceAgnosticLocked"); 412 } 413 mService.openSurfaceTransaction(); 414 try { 415 mSurfaceControl.setColorSpaceAgnostic(agnostic); 416 } finally { 417 mService.closeSurfaceTransaction("setColorSpaceAgnostic"); 418 if (SHOW_LIGHT_TRANSACTIONS) { 419 Slog.i(TAG, "<<< CLOSE TRANSACTION setColorSpaceAgnosticLocked"); 420 } 421 } 422 } 423 getContainerRect(Rect rect)424 void getContainerRect(Rect rect) { 425 mAnimator.getContainerRect(rect); 426 } 427 showRobustlyInTransaction()428 boolean showRobustlyInTransaction() { 429 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title); 430 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this 431 + " during relayout"); 432 mHiddenForOtherReasons = false; 433 return updateVisibility(); 434 } 435 updateVisibility()436 private boolean updateVisibility() { 437 if (mHiddenForCrop || mHiddenForOtherReasons) { 438 if (mSurfaceShown) { 439 hideSurface(mTmpTransaction); 440 SurfaceControl.mergeToGlobalTransaction(mTmpTransaction); 441 } 442 return false; 443 } else { 444 if (!mSurfaceShown) { 445 return showSurface(); 446 } else { 447 return true; 448 } 449 } 450 } 451 showSurface()452 private boolean showSurface() { 453 try { 454 setShown(true); 455 mSurfaceControl.show(); 456 return true; 457 } catch (RuntimeException e) { 458 Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + this, e); 459 } 460 461 mAnimator.reclaimSomeSurfaceMemory("show", true); 462 463 return false; 464 } 465 deferTransactionUntil(SurfaceControl barrier, long frame)466 void deferTransactionUntil(SurfaceControl barrier, long frame) { 467 // TODO: Logging 468 mSurfaceControl.deferTransactionUntil(barrier, frame); 469 } 470 forceScaleableInTransaction(boolean force)471 void forceScaleableInTransaction(boolean force) { 472 // -1 means we don't override the default or client specified 473 // scaling mode. 474 int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1; 475 mSurfaceControl.setOverrideScalingMode(scalingMode); 476 } 477 clearWindowContentFrameStats()478 boolean clearWindowContentFrameStats() { 479 if (mSurfaceControl == null) { 480 return false; 481 } 482 return mSurfaceControl.clearContentFrameStats(); 483 } 484 getWindowContentFrameStats(WindowContentFrameStats outStats)485 boolean getWindowContentFrameStats(WindowContentFrameStats outStats) { 486 if (mSurfaceControl == null) { 487 return false; 488 } 489 return mSurfaceControl.getContentFrameStats(outStats); 490 } 491 492 hasSurface()493 boolean hasSurface() { 494 return mSurfaceControl != null; 495 } 496 getSurfaceControl(SurfaceControl outSurfaceControl)497 void getSurfaceControl(SurfaceControl outSurfaceControl) { 498 outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl"); 499 } 500 getBLASTSurfaceControl(SurfaceControl outSurfaceControl)501 void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) { 502 if (mBLASTSurfaceControl != null) { 503 outSurfaceControl.copyFrom(mBLASTSurfaceControl, "WindowSurfaceController.getBLASTSurfaceControl"); 504 } 505 } 506 getLayer()507 int getLayer() { 508 return mSurfaceLayer; 509 } 510 getShown()511 boolean getShown() { 512 return mSurfaceShown; 513 } 514 setShown(boolean surfaceShown)515 void setShown(boolean surfaceShown) { 516 mSurfaceShown = surfaceShown; 517 518 mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown); 519 520 mAnimator.mWin.onSurfaceShownChanged(surfaceShown); 521 522 if (mWindowSession != null) { 523 mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType); 524 } 525 } 526 getX()527 float getX() { 528 return mSurfaceX; 529 } 530 getY()531 float getY() { 532 return mSurfaceY; 533 } 534 getWidth()535 int getWidth() { 536 return mSurfaceW; 537 } 538 getHeight()539 int getHeight() { 540 return mSurfaceH; 541 } 542 543 /** 544 * Returns the Surface which the client-framework ViewRootImpl will be using. 545 * This is either the WSA SurfaceControl or it's BLAST child surface. 546 * This has too main uses: 547 * 1. This is the Surface the client will add children to, we use this to make 548 * sure we don't reparent the BLAST surface itself when calling reparentChildren 549 * 2. We use this as the barrier Surface for some deferTransaction operations. 550 */ getClientViewRootSurface()551 SurfaceControl getClientViewRootSurface() { 552 if (mBLASTSurfaceControl != null) { 553 return mBLASTSurfaceControl; 554 } 555 return mSurfaceControl; 556 } 557 dumpDebug(ProtoOutputStream proto, long fieldId)558 void dumpDebug(ProtoOutputStream proto, long fieldId) { 559 final long token = proto.start(fieldId); 560 proto.write(SHOWN, mSurfaceShown); 561 proto.write(LAYER, mSurfaceLayer); 562 proto.end(token); 563 } 564 dump(PrintWriter pw, String prefix, boolean dumpAll)565 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 566 if (dumpAll) { 567 pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl); 568 } 569 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 570 pw.print(" layer="); pw.print(mSurfaceLayer); 571 pw.print(" alpha="); pw.print(mSurfaceAlpha); 572 pw.print(" rect=("); pw.print(mSurfaceX); 573 pw.print(","); pw.print(mSurfaceY); 574 pw.print(") "); pw.print(mSurfaceW); 575 pw.print(" x "); pw.print(mSurfaceH); 576 pw.print(" transform=("); pw.print(mLastDsdx); pw.print(", "); 577 pw.print(mLastDtdx); pw.print(", "); pw.print(mLastDsdy); 578 pw.print(", "); pw.print(mLastDtdy); pw.println(")"); 579 } 580 581 @Override toString()582 public String toString() { 583 return mSurfaceControl.toString(); 584 } 585 } 586