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