1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.view.InsetsState.ITYPE_IME; 20 21 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS; 22 import static com.android.server.wm.InsetsSourceProviderProto.CAPTURED_LEASH; 23 import static com.android.server.wm.InsetsSourceProviderProto.CLIENT_VISIBLE; 24 import static com.android.server.wm.InsetsSourceProviderProto.CONTROL; 25 import static com.android.server.wm.InsetsSourceProviderProto.CONTROLLABLE; 26 import static com.android.server.wm.InsetsSourceProviderProto.CONTROL_TARGET; 27 import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL; 28 import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL_TARGET; 29 import static com.android.server.wm.InsetsSourceProviderProto.FRAME; 30 import static com.android.server.wm.InsetsSourceProviderProto.IS_LEASH_READY_FOR_DISPATCHING; 31 import static com.android.server.wm.InsetsSourceProviderProto.PENDING_CONTROL_TARGET; 32 import static com.android.server.wm.InsetsSourceProviderProto.SEAMLESS_ROTATING; 33 import static com.android.server.wm.InsetsSourceProviderProto.SERVER_VISIBLE; 34 import static com.android.server.wm.InsetsSourceProviderProto.SOURCE; 35 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL; 36 import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED; 37 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.graphics.Insets; 41 import android.graphics.Point; 42 import android.graphics.Rect; 43 import android.util.SparseArray; 44 import android.util.proto.ProtoOutputStream; 45 import android.view.InsetsFrameProvider; 46 import android.view.InsetsSource; 47 import android.view.InsetsSourceControl; 48 import android.view.InsetsState; 49 import android.view.SurfaceControl; 50 import android.view.SurfaceControl.Transaction; 51 52 import com.android.internal.annotations.VisibleForTesting; 53 import com.android.internal.protolog.common.ProtoLog; 54 import com.android.internal.util.function.TriConsumer; 55 import com.android.server.wm.SurfaceAnimator.AnimationType; 56 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; 57 58 import java.io.PrintWriter; 59 import java.util.function.Consumer; 60 61 /** 62 * Controller for a specific inset source on the server. It's called provider as it provides the 63 * {@link InsetsSource} to the client that uses it in {@link android.view.InsetsSourceConsumer}. 64 */ 65 abstract class InsetsSourceProvider { 66 67 protected final DisplayContent mDisplayContent; 68 protected final @NonNull InsetsSource mSource; 69 protected WindowContainer mWindowContainer; 70 71 private final Rect mTmpRect = new Rect(); 72 private final InsetsStateController mStateController; 73 private final InsetsSourceControl mFakeControl; 74 private @Nullable InsetsSourceControl mControl; 75 private @Nullable InsetsControlTarget mControlTarget; 76 private @Nullable InsetsControlTarget mPendingControlTarget; 77 private @Nullable InsetsControlTarget mFakeControlTarget; 78 79 private @Nullable ControlAdapter mAdapter; 80 private TriConsumer<DisplayFrames, WindowContainer, Rect> mFrameProvider; 81 private SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> mOverrideFrameProviders; 82 private final SparseArray<Rect> mOverrideFrames = new SparseArray<Rect>(); 83 private boolean mIsLeashReadyForDispatching; 84 private final Rect mSourceFrame = new Rect(); 85 private final Rect mLastSourceFrame = new Rect(); 86 private @NonNull Insets mInsetsHint = Insets.NONE; 87 88 private final Consumer<Transaction> mSetLeashPositionConsumer = t -> { 89 if (mControl != null) { 90 final SurfaceControl leash = mControl.getLeash(); 91 if (leash != null) { 92 final Point position = mControl.getSurfacePosition(); 93 t.setPosition(leash, position.x, position.y); 94 } 95 } 96 }; 97 98 /** The visibility override from the current controlling window. */ 99 private boolean mClientVisible; 100 101 /** 102 * Whether the window container is available and considered visible as in 103 * {@link WindowContainer#isVisible}. 104 */ 105 private boolean mServerVisible; 106 107 private boolean mSeamlessRotating; 108 109 private final boolean mControllable; 110 111 /** 112 * Whether to forced the dimensions of the source window container to the inset frame and crop 113 * out any overflow. 114 * Used to crop the taskbar inset source when a task animation is occurring to hide the taskbar 115 * rounded corners overlays. 116 * 117 * TODO: Remove when we enable shell transitions (b/202383002) 118 */ 119 private boolean mCropToProvidingInsets = false; 120 InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, DisplayContent displayContent)121 InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, 122 DisplayContent displayContent) { 123 mClientVisible = InsetsState.getDefaultVisibility(source.getType()); 124 mSource = source; 125 mDisplayContent = displayContent; 126 mStateController = stateController; 127 mFakeControl = new InsetsSourceControl( 128 source.getType(), null /* leash */, false /* initialVisible */, new Point(), 129 Insets.NONE); 130 mControllable = InsetsPolicy.isInsetsTypeControllable(source.getType()); 131 } 132 getSource()133 InsetsSource getSource() { 134 return mSource; 135 } 136 137 /** 138 * @return Whether the current flag configuration allows to control this source. 139 */ isControllable()140 boolean isControllable() { 141 return mControllable; 142 } 143 144 /** 145 * Updates the window container that currently backs this source. 146 * 147 * @param windowContainer The window container that links to this source. 148 * @param frameProvider Based on display frame state and the window, calculates the resulting 149 * frame that should be reported to clients. 150 * This will only be used when the window container providing the insets is 151 * not a WindowState. 152 * @param overrideFrameProviders Based on display frame state and the window, calculates the 153 * resulting frame that should be reported to given window type. 154 */ setWindowContainer(@ullable WindowContainer windowContainer, @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> overrideFrameProviders)155 void setWindowContainer(@Nullable WindowContainer windowContainer, 156 @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, 157 @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> 158 overrideFrameProviders) { 159 if (mWindowContainer != null) { 160 if (mControllable) { 161 mWindowContainer.setControllableInsetProvider(null); 162 } 163 // The window container may be animating such that we can hand out the leash to the 164 // control target. Revoke the leash by cancelling the animation to correct the state. 165 // TODO: Ideally, we should wait for the animation to finish so previous window can 166 // animate-out as new one animates-in. 167 mWindowContainer.cancelAnimation(); 168 mWindowContainer.getProvidedInsetsSources().remove(mSource.getType()); 169 mSeamlessRotating = false; 170 } 171 ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s", 172 windowContainer, InsetsState.typeToString(mSource.getType())); 173 mWindowContainer = windowContainer; 174 // TODO: remove the frame provider for non-WindowState container. 175 mFrameProvider = frameProvider; 176 mOverrideFrames.clear(); 177 mOverrideFrameProviders = overrideFrameProviders; 178 if (windowContainer == null) { 179 setServerVisible(false); 180 mSource.setVisibleFrame(null); 181 mSource.setInsetsRoundedCornerFrame(false); 182 mSourceFrame.setEmpty(); 183 } else { 184 mWindowContainer.getProvidedInsetsSources().put(mSource.getType(), mSource); 185 if (mControllable) { 186 mWindowContainer.setControllableInsetProvider(this); 187 if (mPendingControlTarget != null) { 188 updateControlForTarget(mPendingControlTarget, true /* force */); 189 mPendingControlTarget = null; 190 } 191 } 192 } 193 } 194 195 /** 196 * @return Whether there is a window container which backs this source. 197 */ hasWindowContainer()198 boolean hasWindowContainer() { 199 return mWindowContainer != null; 200 } 201 202 /** 203 * The source frame can affect the layout of other windows, so this should be called once the 204 * window container gets laid out. 205 */ updateSourceFrame(Rect frame)206 void updateSourceFrame(Rect frame) { 207 if (mWindowContainer == null) { 208 return; 209 } 210 WindowState win = mWindowContainer.asWindowState(); 211 212 if (win == null) { 213 // For all the non window WindowContainers. 214 if (mServerVisible) { 215 mTmpRect.set(mWindowContainer.getBounds()); 216 if (mFrameProvider != null) { 217 mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, 218 mWindowContainer, mTmpRect); 219 } 220 } else { 221 mTmpRect.setEmpty(); 222 } 223 mSource.setFrame(mTmpRect); 224 mSource.setVisibleFrame(null); 225 return; 226 } 227 228 mSourceFrame.set(frame); 229 if (mFrameProvider != null) { 230 mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, 231 mWindowContainer, mSourceFrame); 232 } else { 233 mSourceFrame.inset(win.mGivenContentInsets); 234 } 235 updateSourceFrameForServerVisibility(); 236 237 if (mOverrideFrameProviders != null) { 238 // Not necessary to clear the mOverrideFrames here. It will be cleared every time the 239 // override frame provider updates. 240 for (int i = mOverrideFrameProviders.size() - 1; i >= 0; i--) { 241 final int windowType = mOverrideFrameProviders.keyAt(i); 242 final Rect overrideFrame; 243 if (mOverrideFrames.contains(windowType)) { 244 overrideFrame = mOverrideFrames.get(windowType); 245 overrideFrame.set(frame); 246 } else { 247 overrideFrame = new Rect(frame); 248 } 249 final TriConsumer<DisplayFrames, WindowContainer, Rect> provider = 250 mOverrideFrameProviders.get(windowType); 251 if (provider != null) { 252 mOverrideFrameProviders.get(windowType).accept( 253 mWindowContainer.getDisplayContent().mDisplayFrames, mWindowContainer, 254 overrideFrame); 255 } 256 mOverrideFrames.put(windowType, overrideFrame); 257 } 258 } 259 260 if (win.mGivenVisibleInsets.left != 0 || win.mGivenVisibleInsets.top != 0 261 || win.mGivenVisibleInsets.right != 0 262 || win.mGivenVisibleInsets.bottom != 0) { 263 mTmpRect.set(frame); 264 mTmpRect.inset(win.mGivenVisibleInsets); 265 mSource.setVisibleFrame(mTmpRect); 266 } else { 267 mSource.setVisibleFrame(null); 268 } 269 } 270 updateSourceFrameForServerVisibility()271 private void updateSourceFrameForServerVisibility() { 272 // Make sure we set the valid source frame only when server visible is true, because the 273 // frame may not yet determined that server side doesn't think the window is ready to 274 // visible. (i.e. No surface, pending insets that were given during layout, etc..) 275 if (mServerVisible) { 276 mSource.setFrame(mSourceFrame); 277 } else { 278 mSource.setFrame(0, 0, 0, 0); 279 } 280 } 281 282 /** @return A new source computed by the specified window frame in the given display frames. */ createSimulatedSource(DisplayFrames displayFrames, Rect frame)283 InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect frame) { 284 // Don't copy visible frame because it might not be calculated in the provided display 285 // frames and it is not significant for this usage. 286 final InsetsSource source = new InsetsSource(mSource.getType()); 287 source.setVisible(mSource.isVisible()); 288 mTmpRect.set(frame); 289 if (mFrameProvider != null) { 290 mFrameProvider.accept(displayFrames, mWindowContainer, mTmpRect); 291 } 292 source.setFrame(mTmpRect); 293 return source; 294 } 295 296 /** 297 * Called when a layout pass has occurred. 298 */ onPostLayout()299 void onPostLayout() { 300 if (mWindowContainer == null) { 301 return; 302 } 303 WindowState windowState = mWindowContainer.asWindowState(); 304 boolean isServerVisible = windowState != null 305 ? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy() 306 : mWindowContainer.isVisibleRequested(); 307 setServerVisible(isServerVisible); 308 if (mControl != null) { 309 boolean changed = false; 310 final Point position = getWindowFrameSurfacePosition(); 311 if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) { 312 changed = true; 313 if (windowState != null && windowState.getWindowFrames().didFrameSizeChange() 314 && windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) { 315 windowState.applyWithNextDraw(mSetLeashPositionConsumer); 316 } else { 317 Transaction t = mWindowContainer.getSyncTransaction(); 318 if (windowState != null) { 319 // Make the buffer, token transformation, and leash position to be updated 320 // together when the window is drawn for new rotation. Otherwise the window 321 // may be outside the screen by the inconsistent orientations. 322 final AsyncRotationController rotationController = 323 mDisplayContent.getAsyncRotationController(); 324 if (rotationController != null) { 325 final Transaction drawT = 326 rotationController.getDrawTransaction(windowState.mToken); 327 if (drawT != null) { 328 t = drawT; 329 } 330 } 331 } 332 mSetLeashPositionConsumer.accept(t); 333 } 334 } 335 if (mServerVisible && !mLastSourceFrame.equals(mSource.getFrame())) { 336 final Insets insetsHint = mSource.calculateInsets( 337 mWindowContainer.getBounds(), true /* ignoreVisibility */); 338 if (!insetsHint.equals(mControl.getInsetsHint())) { 339 changed = true; 340 mControl.setInsetsHint(insetsHint); 341 mInsetsHint = insetsHint; 342 } 343 mLastSourceFrame.set(mSource.getFrame()); 344 } 345 if (changed) { 346 mStateController.notifyControlChanged(mControlTarget); 347 } 348 } 349 } 350 getWindowFrameSurfacePosition()351 private Point getWindowFrameSurfacePosition() { 352 final WindowState win = mWindowContainer.asWindowState(); 353 if (win != null && mControl != null) { 354 final AsyncRotationController controller = mDisplayContent.getAsyncRotationController(); 355 if (controller != null && controller.shouldFreezeInsetsPosition(win)) { 356 // Use previous position because the window still shows with old rotation. 357 return mControl.getSurfacePosition(); 358 } 359 } 360 final Rect frame = win != null ? win.getFrame() : mWindowContainer.getBounds(); 361 final Point position = new Point(); 362 mWindowContainer.transformFrameToSurfacePosition(frame.left, frame.top, position); 363 return position; 364 } 365 366 /** 367 * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget) 368 */ updateControlForFakeTarget(@ullable InsetsControlTarget fakeTarget)369 void updateControlForFakeTarget(@Nullable InsetsControlTarget fakeTarget) { 370 if (fakeTarget == mFakeControlTarget) { 371 return; 372 } 373 mFakeControlTarget = fakeTarget; 374 } 375 376 /** 377 * Ensures that the inset source window container is cropped so that anything that doesn't fit 378 * within the inset frame is cropped out until removeCropToProvidingInsetsBounds is called. 379 * 380 * The inset source surface will get cropped to the be of the size of the insets it's providing. 381 * 382 * For example, for the taskbar window which serves as the ITYPE_EXTRA_NAVIGATION_BAR inset 383 * source, the window is larger than the insets because of the rounded corners overlay, but 384 * during task animations we want to make sure that the overlay is cropped out of the window so 385 * that they don't hide the window animations. 386 * 387 * @param t The transaction to use to apply immediate overflow cropping operations. 388 * 389 * NOTE: The relies on the inset source window to have a leash (usually this would be a leash 390 * for the ANIMATION_TYPE_INSETS_CONTROL animation if the inset is controlled by the client) 391 * 392 * TODO: Remove when we migrate over to shell transitions (b/202383002) 393 */ setCropToProvidingInsetsBounds(Transaction t)394 void setCropToProvidingInsetsBounds(Transaction t) { 395 mCropToProvidingInsets = true; 396 397 if (mWindowContainer != null && mWindowContainer.mSurfaceAnimator.hasLeash()) { 398 // apply to existing leash 399 t.setWindowCrop(mWindowContainer.mSurfaceAnimator.mLeash, 400 getProvidingInsetsBoundsCropRect()); 401 } 402 } 403 404 /** 405 * Removes any overflow cropping and future cropping to the inset source window's leash that may 406 * have been set with a call to setCropToProvidingInsetsBounds(). 407 * @param t The transaction to use to apply immediate removal of overflow cropping. 408 * 409 * TODO: Remove when we migrate over to shell transitions (b/202383002) 410 */ removeCropToProvidingInsetsBounds(Transaction t)411 void removeCropToProvidingInsetsBounds(Transaction t) { 412 mCropToProvidingInsets = false; 413 414 // apply to existing leash 415 if (mWindowContainer != null && mWindowContainer.mSurfaceAnimator.hasLeash()) { 416 t.setWindowCrop(mWindowContainer.mSurfaceAnimator.mLeash, null); 417 } 418 } 419 getProvidingInsetsBoundsCropRect()420 private Rect getProvidingInsetsBoundsCropRect() { 421 Rect sourceWindowFrame = mWindowContainer.asWindowState() != null 422 ? mWindowContainer.asWindowState().getFrame() 423 : mWindowContainer.getBounds(); 424 Rect insetFrame = getSource().getFrame(); 425 426 // The rectangle in buffer space we want to crop to 427 return new Rect( 428 insetFrame.left - sourceWindowFrame.left, 429 insetFrame.top - sourceWindowFrame.top, 430 insetFrame.right - sourceWindowFrame.left, 431 insetFrame.bottom - sourceWindowFrame.top 432 ); 433 } 434 updateControlForTarget(@ullable InsetsControlTarget target, boolean force)435 void updateControlForTarget(@Nullable InsetsControlTarget target, boolean force) { 436 if (mSeamlessRotating) { 437 // We are un-rotating the window against the display rotation. We don't want the target 438 // to control the window for now. 439 return; 440 } 441 442 if (mWindowContainer != null && mWindowContainer.getSurfaceControl() == null) { 443 // if window doesn't have a surface, set it null and return. 444 setWindowContainer(null, null, null); 445 } 446 if (mWindowContainer == null) { 447 mPendingControlTarget = target; 448 return; 449 } 450 if (target == mControlTarget && !force) { 451 return; 452 } 453 if (target == null) { 454 // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields. 455 mWindowContainer.cancelAnimation(); 456 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); 457 return; 458 } 459 final Point surfacePosition = getWindowFrameSurfacePosition(); 460 mAdapter = new ControlAdapter(surfacePosition); 461 if (getSource().getType() == ITYPE_IME) { 462 setClientVisible(target.getRequestedVisibility(mSource.getType())); 463 } 464 final Transaction t = mDisplayContent.getSyncTransaction(); 465 mWindowContainer.startAnimation(t, mAdapter, !mClientVisible /* hidden */, 466 ANIMATION_TYPE_INSETS_CONTROL); 467 468 // The leash was just created. We cannot dispatch it until its surface transaction is 469 // applied. Otherwise, the client's operation to the leash might be overwritten by us. 470 mIsLeashReadyForDispatching = false; 471 472 final SurfaceControl leash = mAdapter.mCapturedLeash; 473 mControlTarget = target; 474 updateVisibility(); 475 mControl = new InsetsSourceControl(mSource.getType(), leash, mClientVisible, 476 surfacePosition, mInsetsHint); 477 478 ProtoLog.d(WM_DEBUG_WINDOW_INSETS, 479 "InsetsSource Control %s for target %s", mControl, mControlTarget); 480 } 481 startSeamlessRotation()482 void startSeamlessRotation() { 483 if (!mSeamlessRotating) { 484 mSeamlessRotating = true; 485 mWindowContainer.cancelAnimation(); 486 } 487 } 488 finishSeamlessRotation()489 void finishSeamlessRotation() { 490 mSeamlessRotating = false; 491 } 492 updateClientVisibility(InsetsControlTarget caller)493 boolean updateClientVisibility(InsetsControlTarget caller) { 494 final boolean requestedVisible = caller.getRequestedVisibility(mSource.getType()); 495 if (caller != mControlTarget || requestedVisible == mClientVisible) { 496 return false; 497 } 498 setClientVisible(requestedVisible); 499 return true; 500 } 501 onSurfaceTransactionApplied()502 void onSurfaceTransactionApplied() { 503 mIsLeashReadyForDispatching = true; 504 } 505 setClientVisible(boolean clientVisible)506 void setClientVisible(boolean clientVisible) { 507 if (mClientVisible == clientVisible) { 508 return; 509 } 510 mClientVisible = clientVisible; 511 if (!mDisplayContent.mLayoutAndAssignWindowLayersScheduled) { 512 mDisplayContent.mLayoutAndAssignWindowLayersScheduled = true; 513 mDisplayContent.mWmService.mH.obtainMessage( 514 LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED, mDisplayContent).sendToTarget(); 515 } 516 updateVisibility(); 517 } 518 519 @VisibleForTesting setServerVisible(boolean serverVisible)520 void setServerVisible(boolean serverVisible) { 521 mServerVisible = serverVisible; 522 updateSourceFrameForServerVisibility(); 523 updateVisibility(); 524 } 525 updateVisibility()526 protected void updateVisibility() { 527 mSource.setVisible(mServerVisible && (isMirroredSource() || mClientVisible)); 528 ProtoLog.d(WM_DEBUG_WINDOW_INSETS, 529 "InsetsSource updateVisibility for %s, serverVisible: %s clientVisible: %s", 530 InsetsState.typeToString(mSource.getType()), 531 mServerVisible, mClientVisible); 532 } 533 isMirroredSource()534 private boolean isMirroredSource() { 535 if (mWindowContainer == null) { 536 return false; 537 } 538 if (mWindowContainer.asWindowState() == null) { 539 return false; 540 } 541 final InsetsFrameProvider[] providers = 542 ((WindowState) mWindowContainer).mAttrs.providedInsets; 543 if (providers == null) { 544 return false; 545 } 546 for (int i = 0; i < providers.length; i++) { 547 if (providers[i].type == ITYPE_IME) { 548 return true; 549 } 550 } 551 return false; 552 } 553 getControl(InsetsControlTarget target)554 InsetsSourceControl getControl(InsetsControlTarget target) { 555 if (target == mControlTarget) { 556 if (!mIsLeashReadyForDispatching && mControl != null) { 557 // The surface transaction of preparing leash is not applied yet. We don't send it 558 // to the client in case that the client applies its transaction sooner than ours 559 // that we could unexpectedly overwrite the surface state. 560 return new InsetsSourceControl(mControl.getType(), null /* leash */, 561 mControl.isInitiallyVisible(), mControl.getSurfacePosition(), 562 mControl.getInsetsHint()); 563 } 564 return mControl; 565 } 566 if (target == mFakeControlTarget) { 567 return mFakeControl; 568 } 569 return null; 570 } 571 getControlTarget()572 InsetsControlTarget getControlTarget() { 573 return mControlTarget; 574 } 575 isClientVisible()576 boolean isClientVisible() { 577 return mClientVisible; 578 } 579 overridesFrame(int windowType)580 boolean overridesFrame(int windowType) { 581 return mOverrideFrames.contains(windowType); 582 } 583 getOverriddenFrame(int windowType)584 Rect getOverriddenFrame(int windowType) { 585 return mOverrideFrames.get(windowType); 586 } 587 dump(PrintWriter pw, String prefix)588 public void dump(PrintWriter pw, String prefix) { 589 pw.println(prefix + getClass().getSimpleName()); 590 prefix = prefix + " "; 591 pw.print(prefix + "mSource="); mSource.dump("", pw); 592 pw.print(prefix + "mSourceFrame="); 593 pw.println(mSourceFrame); 594 if (mOverrideFrames.size() > 0) { 595 pw.print(prefix + "mOverrideFrames="); 596 pw.println(mOverrideFrames); 597 } 598 if (mControl != null) { 599 pw.print(prefix + "mControl="); 600 mControl.dump("", pw); 601 } 602 pw.print(prefix); 603 pw.print("mIsLeashReadyForDispatching="); pw.print(mIsLeashReadyForDispatching); 604 pw.println(); 605 if (mWindowContainer != null) { 606 pw.print(prefix + "mWindowContainer="); 607 pw.println(mWindowContainer); 608 } 609 if (mAdapter != null) { 610 pw.print(prefix + "mAdapter="); 611 mAdapter.dump(pw, ""); 612 } 613 if (mControlTarget != null) { 614 pw.print(prefix + "mControlTarget="); 615 pw.println(mControlTarget.getWindow()); 616 } 617 if (mPendingControlTarget != null) { 618 pw.print(prefix + "mPendingControlTarget="); 619 pw.println(mPendingControlTarget.getWindow()); 620 } 621 if (mFakeControlTarget != null) { 622 pw.print(prefix + "mFakeControlTarget="); 623 pw.println(mFakeControlTarget.getWindow()); 624 } 625 } 626 dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)627 void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) { 628 final long token = proto.start(fieldId); 629 mSource.dumpDebug(proto, SOURCE); 630 mTmpRect.dumpDebug(proto, FRAME); 631 mFakeControl.dumpDebug(proto, FAKE_CONTROL); 632 if (mControl != null) { 633 mControl.dumpDebug(proto, CONTROL); 634 } 635 if (mControlTarget != null && mControlTarget.getWindow() != null) { 636 mControlTarget.getWindow().dumpDebug(proto, CONTROL_TARGET, logLevel); 637 } 638 if (mPendingControlTarget != null && mPendingControlTarget.getWindow() != null) { 639 mPendingControlTarget.getWindow().dumpDebug(proto, PENDING_CONTROL_TARGET, logLevel); 640 } 641 if (mFakeControlTarget != null && mFakeControlTarget.getWindow() != null) { 642 mFakeControlTarget.getWindow().dumpDebug(proto, FAKE_CONTROL_TARGET, logLevel); 643 } 644 if (mAdapter != null && mAdapter.mCapturedLeash != null) { 645 mAdapter.mCapturedLeash.dumpDebug(proto, CAPTURED_LEASH); 646 } 647 proto.write(IS_LEASH_READY_FOR_DISPATCHING, mIsLeashReadyForDispatching); 648 proto.write(CLIENT_VISIBLE, mClientVisible); 649 proto.write(SERVER_VISIBLE, mServerVisible); 650 proto.write(SEAMLESS_ROTATING, mSeamlessRotating); 651 proto.write(CONTROLLABLE, mControllable); 652 proto.end(token); 653 } 654 655 private class ControlAdapter implements AnimationAdapter { 656 657 private final Point mSurfacePosition; 658 private SurfaceControl mCapturedLeash; 659 ControlAdapter(Point surfacePosition)660 ControlAdapter(Point surfacePosition) { 661 mSurfacePosition = surfacePosition; 662 } 663 664 @Override getShowWallpaper()665 public boolean getShowWallpaper() { 666 return false; 667 } 668 669 @Override startAnimation(SurfaceControl animationLeash, Transaction t, @AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback)670 public void startAnimation(SurfaceControl animationLeash, Transaction t, 671 @AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback) { 672 // TODO(b/166736352): Check if we still need to control the IME visibility here. 673 if (mSource.getType() == ITYPE_IME) { 674 // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed. 675 t.setAlpha(animationLeash, 1 /* alpha */); 676 t.hide(animationLeash); 677 } 678 ProtoLog.i(WM_DEBUG_WINDOW_INSETS, 679 "ControlAdapter startAnimation mSource: %s controlTarget: %s", mSource, 680 mControlTarget); 681 682 mCapturedLeash = animationLeash; 683 t.setPosition(mCapturedLeash, mSurfacePosition.x, mSurfacePosition.y); 684 685 if (mCropToProvidingInsets) { 686 // Apply crop to hide overflow 687 t.setWindowCrop(mCapturedLeash, getProvidingInsetsBoundsCropRect()); 688 } 689 } 690 691 @Override onAnimationCancelled(SurfaceControl animationLeash)692 public void onAnimationCancelled(SurfaceControl animationLeash) { 693 if (mAdapter == this) { 694 mStateController.notifyControlRevoked(mControlTarget, InsetsSourceProvider.this); 695 mControl = null; 696 mControlTarget = null; 697 mAdapter = null; 698 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); 699 ProtoLog.i(WM_DEBUG_WINDOW_INSETS, 700 "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s", 701 mSource, mControlTarget); 702 } 703 } 704 705 @Override getDurationHint()706 public long getDurationHint() { 707 return 0; 708 } 709 710 @Override getStatusBarTransitionsStartTime()711 public long getStatusBarTransitionsStartTime() { 712 return 0; 713 } 714 715 @Override dump(PrintWriter pw, String prefix)716 public void dump(PrintWriter pw, String prefix) { 717 pw.print(prefix + "ControlAdapter mCapturedLeash="); 718 pw.print(mCapturedLeash); 719 pw.println(); 720 } 721 722 @Override dumpDebug(ProtoOutputStream proto)723 public void dumpDebug(ProtoOutputStream proto) { 724 } 725 } 726 } 727