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