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