1 /* 2 * Copyright (C) 2019 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.app.StatusBarManager.WINDOW_STATE_HIDDEN; 20 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 23 import static android.view.InsetsController.ANIMATION_TYPE_HIDE; 24 import static android.view.InsetsController.ANIMATION_TYPE_SHOW; 25 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; 26 import static android.view.InsetsState.ITYPE_STATUS_BAR; 27 import static android.view.SyncRtSurfaceTransactionApplier.applyParams; 28 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; 29 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; 30 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 31 32 import android.annotation.Nullable; 33 import android.app.StatusBarManager; 34 import android.util.IntArray; 35 import android.util.SparseArray; 36 import android.view.InsetsAnimationControlCallbacks; 37 import android.view.InsetsAnimationControlImpl; 38 import android.view.InsetsAnimationControlRunner; 39 import android.view.InsetsController; 40 import android.view.InsetsSource; 41 import android.view.InsetsSourceControl; 42 import android.view.InsetsState; 43 import android.view.InsetsState.InternalInsetsType; 44 import android.view.SurfaceControl; 45 import android.view.SyncRtSurfaceTransactionApplier; 46 import android.view.ViewRootImpl; 47 import android.view.WindowInsetsAnimation; 48 import android.view.WindowInsetsAnimation.Bounds; 49 import android.view.WindowInsetsAnimationControlListener; 50 import android.view.WindowManager; 51 52 import com.android.internal.R; 53 import com.android.internal.annotations.VisibleForTesting; 54 import com.android.server.DisplayThread; 55 56 /** 57 * Policy that implements who gets control over the windows generating insets. 58 */ 59 class InsetsPolicy { 60 61 private final InsetsStateController mStateController; 62 private final DisplayContent mDisplayContent; 63 private final DisplayPolicy mPolicy; 64 private final IntArray mShowingTransientTypes = new IntArray(); 65 66 /** For resetting visibilities of insets sources. */ 67 private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { 68 69 @Override 70 public void notifyInsetsControlChanged() { 71 boolean hasLeash = false; 72 final InsetsSourceControl[] controls = 73 mStateController.getControlsForDispatch(this); 74 if (controls == null) { 75 return; 76 } 77 for (InsetsSourceControl control : controls) { 78 final @InternalInsetsType int type = control.getType(); 79 if (mShowingTransientTypes.indexOf(type) != -1) { 80 // The visibilities of transient bars will be handled with animations. 81 continue; 82 } 83 final SurfaceControl leash = control.getLeash(); 84 if (leash != null) { 85 hasLeash = true; 86 87 // We use alpha to control the visibility here which aligns the logic at 88 // SurfaceAnimator.createAnimationLeash 89 mDisplayContent.getPendingTransaction().setAlpha( 90 leash, InsetsState.getDefaultVisibility(type) ? 1f : 0f); 91 } 92 } 93 if (hasLeash) { 94 mDisplayContent.scheduleAnimation(); 95 } 96 } 97 }; 98 99 private WindowState mFocusedWin; 100 private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); 101 private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); 102 private boolean mAnimatingShown; 103 104 /** 105 * Let remote insets controller control system bars regardless of other settings. 106 */ 107 private boolean mRemoteInsetsControllerControlsSystemBars; 108 private final float[] mTmpFloat9 = new float[9]; 109 InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent)110 InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) { 111 mStateController = stateController; 112 mDisplayContent = displayContent; 113 mPolicy = displayContent.getDisplayPolicy(); 114 mRemoteInsetsControllerControlsSystemBars = mPolicy.getContext().getResources().getBoolean( 115 R.bool.config_remoteInsetsControllerControlsSystemBars); 116 } 117 getRemoteInsetsControllerControlsSystemBars()118 boolean getRemoteInsetsControllerControlsSystemBars() { 119 return mRemoteInsetsControllerControlsSystemBars; 120 } 121 122 /** 123 * Used only for testing. 124 */ 125 @VisibleForTesting setRemoteInsetsControllerControlsSystemBars(boolean controlsSystemBars)126 void setRemoteInsetsControllerControlsSystemBars(boolean controlsSystemBars) { 127 mRemoteInsetsControllerControlsSystemBars = controlsSystemBars; 128 } 129 130 /** Updates the target which can control system bars. */ updateBarControlTarget(@ullable WindowState focusedWin)131 void updateBarControlTarget(@Nullable WindowState focusedWin) { 132 if (focusedWin != null && (focusedWin.mAttrs.type == TYPE_APPLICATION_STARTING)) { 133 return; 134 } 135 if (mFocusedWin != focusedWin){ 136 abortTransient(); 137 } 138 mFocusedWin = focusedWin; 139 boolean forceShowsSystemBarsForWindowingMode = forceShowsSystemBarsForWindowingMode(); 140 InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin, 141 forceShowsSystemBarsForWindowingMode); 142 InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin, 143 forceShowsSystemBarsForWindowingMode); 144 mStateController.onBarControlTargetChanged(statusControlTarget, 145 getFakeControlTarget(focusedWin, statusControlTarget), 146 navControlTarget, 147 getFakeControlTarget(focusedWin, navControlTarget)); 148 if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { 149 return; 150 } 151 mStatusBar.updateVisibility(statusControlTarget, ITYPE_STATUS_BAR); 152 mNavBar.updateVisibility(navControlTarget, ITYPE_NAVIGATION_BAR); 153 mPolicy.updateHideNavInputEventReceiver(); 154 } 155 isHidden(@nternalInsetsType int type)156 boolean isHidden(@InternalInsetsType int type) { 157 final InsetsSourceProvider provider = mStateController.peekSourceProvider(type); 158 return provider != null && provider.hasWindow() && !provider.getSource().isVisible(); 159 } 160 showTransient(@nternalInsetsType int[] types)161 void showTransient(@InternalInsetsType int[] types) { 162 boolean changed = false; 163 for (int i = types.length - 1; i >= 0; i--) { 164 final @InternalInsetsType int type = types[i]; 165 if (!isHidden(type)) { 166 continue; 167 } 168 if (mShowingTransientTypes.indexOf(type) != -1) { 169 continue; 170 } 171 mShowingTransientTypes.add(type); 172 changed = true; 173 } 174 if (changed) { 175 mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(), 176 mShowingTransientTypes.toArray()); 177 updateBarControlTarget(mFocusedWin); 178 179 // The leashes can be created while updating bar control target. The surface transaction 180 // of the new leashes might not be applied yet. The callback posted here ensures we can 181 // get the valid leashes because the surface transaction will be applied in the next 182 // animation frame which will be triggered if a new leash is created. 183 mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> { 184 synchronized (mDisplayContent.mWmService.mGlobalLock) { 185 final InsetsState state = new InsetsState(mStateController.getRawInsetsState()); 186 startAnimation(true /* show */, () -> { 187 synchronized (mDisplayContent.mWmService.mGlobalLock) { 188 mStateController.notifyInsetsChanged(); 189 } 190 }, state); 191 mStateController.onInsetsModified(mDummyControlTarget, state); 192 } 193 }); 194 } 195 } 196 hideTransient()197 void hideTransient() { 198 if (mShowingTransientTypes.size() == 0) { 199 return; 200 } 201 InsetsState state = new InsetsState(mStateController.getRawInsetsState()); 202 startAnimation(false /* show */, () -> { 203 synchronized (mDisplayContent.mWmService.mGlobalLock) { 204 mShowingTransientTypes.clear(); 205 mStateController.notifyInsetsChanged(); 206 updateBarControlTarget(mFocusedWin); 207 } 208 }, state); 209 mStateController.onInsetsModified(mDummyControlTarget, state); 210 } 211 isTransient(@nternalInsetsType int type)212 boolean isTransient(@InternalInsetsType int type) { 213 return mShowingTransientTypes.indexOf(type) != -1; 214 } 215 216 /** 217 * @see InsetsStateController#getInsetsForDispatch 218 */ getInsetsForDispatch(WindowState target)219 InsetsState getInsetsForDispatch(WindowState target) { 220 final InsetsState originalState = mStateController.getInsetsForDispatch(target); 221 InsetsState state = originalState; 222 for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { 223 final int type = mShowingTransientTypes.get(i); 224 final InsetsSource originalSource = state.peekSource(type); 225 if (originalSource != null && originalSource.isVisible()) { 226 if (state == originalState) { 227 // The source will be modified, create a non-deep copy to store the new one. 228 state = new InsetsState(originalState); 229 } 230 // Replace the source with a copy in invisible state. 231 final InsetsSource source = new InsetsSource(originalSource); 232 source.setVisible(false); 233 state.addSource(source); 234 } 235 } 236 return state; 237 } 238 onInsetsModified(WindowState windowState, InsetsState state)239 void onInsetsModified(WindowState windowState, InsetsState state) { 240 mStateController.onInsetsModified(windowState, state); 241 checkAbortTransient(windowState, state); 242 updateBarControlTarget(mFocusedWin); 243 } 244 245 /** 246 * Called when a window modified the insets state. If the window set a insets source to visible 247 * while it is shown transiently, we need to abort the transient state. 248 * 249 * @param windowState who changed the insets state. 250 * @param state the modified insets state. 251 */ checkAbortTransient(WindowState windowState, InsetsState state)252 private void checkAbortTransient(WindowState windowState, InsetsState state) { 253 if (mShowingTransientTypes.size() != 0) { 254 IntArray abortTypes = new IntArray(); 255 for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { 256 final int type = mShowingTransientTypes.get(i); 257 if (mStateController.isFakeTarget(type, windowState) 258 && state.getSource(type).isVisible()) { 259 mShowingTransientTypes.remove(i); 260 abortTypes.add(type); 261 } 262 } 263 if (abortTypes.size() > 0) { 264 mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), 265 abortTypes.toArray()); 266 } 267 } 268 } 269 270 /** 271 * If the caller is not {@link #updateBarControlTarget}, it should call 272 * updateBarControlTarget(mFocusedWin) after this invocation. 273 */ abortTransient()274 private void abortTransient() { 275 mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), 276 mShowingTransientTypes.toArray()); 277 mShowingTransientTypes.clear(); 278 } 279 getFakeControlTarget(@ullable WindowState focused, InsetsControlTarget realControlTarget)280 private @Nullable InsetsControlTarget getFakeControlTarget(@Nullable WindowState focused, 281 InsetsControlTarget realControlTarget) { 282 return realControlTarget == mDummyControlTarget ? focused : null; 283 } 284 getStatusControlTarget(@ullable WindowState focusedWin, boolean forceShowsSystemBarsForWindowingMode)285 private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin, 286 boolean forceShowsSystemBarsForWindowingMode) { 287 if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { 288 return mDummyControlTarget; 289 } 290 if (focusedWin == mPolicy.getNotificationShade()) { 291 // Notification shade has control anyways, no reason to force anything. 292 return focusedWin; 293 } 294 if (remoteInsetsControllerControlsSystemBars(focusedWin)) { 295 mDisplayContent.mRemoteInsetsControlTarget.topFocusedWindowChanged( 296 focusedWin.mAttrs.packageName); 297 return mDisplayContent.mRemoteInsetsControlTarget; 298 } 299 if (forceShowsSystemBarsForWindowingMode) { 300 // Status bar is forcibly shown for the windowing mode which is a steady state. 301 // We don't want the client to control the status bar, and we will dispatch the real 302 // visibility of status bar to the client. 303 return null; 304 } 305 if (forceShowsStatusBarTransiently()) { 306 // Status bar is forcibly shown transiently, and its new visibility won't be 307 // dispatched to the client so that we can keep the layout stable. We will dispatch the 308 // fake control to the client, so that it can re-show the bar during this scenario. 309 return mDummyControlTarget; 310 } 311 if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar()) { 312 // Non-fullscreen focused window should not break the state that the top-fullscreen-app 313 // window hides status bar. 314 return mPolicy.getTopFullscreenOpaqueWindow(); 315 } 316 return focusedWin; 317 } 318 canBeTopFullscreenOpaqueWindow(@ullable WindowState win)319 private static boolean canBeTopFullscreenOpaqueWindow(@Nullable WindowState win) { 320 // The condition doesn't use WindowState#canAffectSystemUiFlags because the window may 321 // haven't drawn or committed the visibility. 322 final boolean nonAttachedAppWindow = win != null 323 && win.mAttrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 324 && win.mAttrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 325 return nonAttachedAppWindow && win.mAttrs.isFullscreen() && !win.isFullyTransparent() 326 && !win.inMultiWindowMode(); 327 } 328 getNavControlTarget(@ullable WindowState focusedWin, boolean forceShowsSystemBarsForWindowingMode)329 private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin, 330 boolean forceShowsSystemBarsForWindowingMode) { 331 if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { 332 return mDummyControlTarget; 333 } 334 if (focusedWin == mPolicy.getNotificationShade()) { 335 // Notification shade has control anyways, no reason to force anything. 336 return focusedWin; 337 } 338 if (remoteInsetsControllerControlsSystemBars(focusedWin)) { 339 mDisplayContent.mRemoteInsetsControlTarget.topFocusedWindowChanged( 340 focusedWin.mAttrs.packageName); 341 return mDisplayContent.mRemoteInsetsControlTarget; 342 } 343 if (forceShowsSystemBarsForWindowingMode) { 344 // Navigation bar is forcibly shown for the windowing mode which is a steady state. 345 // We don't want the client to control the navigation bar, and we will dispatch the real 346 // visibility of navigation bar to the client. 347 return null; 348 } 349 if (forceShowsNavigationBarTransiently()) { 350 // Navigation bar is forcibly shown transiently, and its new visibility won't be 351 // dispatched to the client so that we can keep the layout stable. We will dispatch the 352 // fake control to the client, so that it can re-show the bar during this scenario. 353 return mDummyControlTarget; 354 } 355 return focusedWin; 356 } 357 358 /** 359 * Determines whether the remote insets controller should take control of system bars for all 360 * windows. 361 */ remoteInsetsControllerControlsSystemBars(@ullable WindowState focusedWin)362 boolean remoteInsetsControllerControlsSystemBars(@Nullable WindowState focusedWin) { 363 if (focusedWin == null) { 364 return false; 365 } 366 if (!mRemoteInsetsControllerControlsSystemBars) { 367 return false; 368 } 369 if (mDisplayContent == null || mDisplayContent.mRemoteInsetsControlTarget == null) { 370 // No remote insets control target to take control of insets. 371 return false; 372 } 373 // If necessary, auto can control application windows when 374 // config_remoteInsetsControllerControlsSystemBars is set to true. This is useful in cases 375 // where we want to dictate system bar inset state for applications. 376 return focusedWin.getAttrs().type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 377 && focusedWin.getAttrs().type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 378 } 379 forceShowsStatusBarTransiently()380 private boolean forceShowsStatusBarTransiently() { 381 final WindowState win = mPolicy.getStatusBar(); 382 return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; 383 } 384 forceShowsNavigationBarTransiently()385 private boolean forceShowsNavigationBarTransiently() { 386 final WindowState win = mPolicy.getNotificationShade(); 387 return win != null 388 && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; 389 } 390 forceShowsSystemBarsForWindowingMode()391 private boolean forceShowsSystemBarsForWindowingMode() { 392 final boolean isDockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea() 393 .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); 394 final boolean isFreeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea() 395 .isStackVisible(WINDOWING_MODE_FREEFORM); 396 final boolean isResizing = mDisplayContent.getDockedDividerController().isResizing(); 397 398 // We need to force system bars when the docked stack is visible, when the freeform stack 399 // is visible but also when we are resizing for the transitions when docked stack 400 // visibility changes. 401 return isDockedStackVisible || isFreeformStackVisible || isResizing; 402 } 403 404 @VisibleForTesting startAnimation(boolean show, Runnable callback, InsetsState state)405 void startAnimation(boolean show, Runnable callback, InsetsState state) { 406 int typesReady = 0; 407 final SparseArray<InsetsSourceControl> controls = new SparseArray<>(); 408 final IntArray showingTransientTypes = mShowingTransientTypes; 409 for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { 410 int type = showingTransientTypes.get(i); 411 InsetsSourceProvider provider = mStateController.getSourceProvider(type); 412 InsetsSourceControl control = provider.getControl(mDummyControlTarget); 413 if (control == null || control.getLeash() == null) { 414 continue; 415 } 416 typesReady |= InsetsState.toPublicType(type); 417 controls.put(control.getType(), new InsetsSourceControl(control)); 418 state.setSourceVisible(type, show); 419 } 420 controlAnimationUnchecked(typesReady, controls, show, callback); 421 } 422 controlAnimationUnchecked(int typesReady, SparseArray<InsetsSourceControl> controls, boolean show, Runnable callback)423 private void controlAnimationUnchecked(int typesReady, 424 SparseArray<InsetsSourceControl> controls, boolean show, Runnable callback) { 425 InsetsPolicyAnimationControlListener listener = 426 new InsetsPolicyAnimationControlListener(show, callback, typesReady); 427 listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show); 428 } 429 430 private class BarWindow { 431 432 private final int mId; 433 private @StatusBarManager.WindowVisibleState int mState = 434 StatusBarManager.WINDOW_STATE_SHOWING; 435 BarWindow(int id)436 BarWindow(int id) { 437 mId = id; 438 } 439 updateVisibility(InsetsControlTarget controlTarget, @InternalInsetsType int type)440 private void updateVisibility(InsetsControlTarget controlTarget, 441 @InternalInsetsType int type) { 442 final WindowState controllingWin = 443 controlTarget instanceof WindowState ? (WindowState) controlTarget : null; 444 setVisible(controllingWin == null 445 || controllingWin.getRequestedInsetsState().getSourceOrDefaultVisibility(type)); 446 } 447 setVisible(boolean visible)448 private void setVisible(boolean visible) { 449 final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN; 450 if (mState != state) { 451 mState = state; 452 mPolicy.getStatusBarManagerInternal().setWindowState( 453 mDisplayContent.getDisplayId(), mId, state); 454 } 455 } 456 } 457 458 private class InsetsPolicyAnimationControlListener extends 459 InsetsController.InternalAnimationControlListener { 460 Runnable mFinishCallback; 461 InsetsPolicyAnimationControlCallbacks mControlCallbacks; 462 InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types)463 InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) { 464 465 super(show, false /* hasCallbacks */, types, false /* disable */, 466 (int) (mDisplayContent.getDisplayMetrics().density * FLOATING_IME_BOTTOM_INSET 467 + 0.5f)); 468 mFinishCallback = finishCallback; 469 mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this); 470 } 471 472 @Override onAnimationFinish()473 protected void onAnimationFinish() { 474 super.onAnimationFinish(); 475 DisplayThread.getHandler().post(mFinishCallback); 476 } 477 478 private class InsetsPolicyAnimationControlCallbacks implements 479 InsetsAnimationControlCallbacks { 480 private InsetsAnimationControlImpl mAnimationControl = null; 481 private InsetsPolicyAnimationControlListener mListener; 482 InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener)483 InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) { 484 mListener = listener; 485 } 486 controlAnimationUnchecked(int typesReady, SparseArray<InsetsSourceControl> controls, boolean show)487 private void controlAnimationUnchecked(int typesReady, 488 SparseArray<InsetsSourceControl> controls, boolean show) { 489 if (typesReady == 0) { 490 // nothing to animate. 491 return; 492 } 493 mAnimatingShown = show; 494 495 mAnimationControl = new InsetsAnimationControlImpl(controls, 496 mFocusedWin.getDisplayContent().getBounds(), getState(), 497 mListener, typesReady, this, mListener.getDurationMs(), 498 InsetsController.SYSTEM_BARS_INTERPOLATOR, 499 show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE); 500 SurfaceAnimationThread.getHandler().post( 501 () -> mListener.onReady(mAnimationControl, typesReady)); 502 } 503 504 /** Called on SurfaceAnimationThread without global WM lock held. */ 505 @Override scheduleApplyChangeInsets(InsetsAnimationControlRunner runner)506 public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) { 507 InsetsState state = getState(); 508 if (mAnimationControl.applyChangeInsets(state)) { 509 mAnimationControl.finish(mAnimatingShown); 510 } 511 } 512 513 @Override notifyFinished(InsetsAnimationControlRunner runner, boolean shown)514 public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { 515 // Nothing's needed here. Finish steps is handled in the listener 516 // onAnimationFinished callback. 517 } 518 519 /** 520 * This method will return a state with fullscreen frame override. No need to make copy 521 * after getting state from this method. 522 * @return The client insets state with full display frame override. 523 */ getState()524 private InsetsState getState() { 525 // To animate the transient animation correctly, we need to let the state hold 526 // the full display frame. 527 InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(), 528 true); 529 overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds()); 530 return overrideState; 531 } 532 533 /** Called on SurfaceAnimationThread without global WM lock held. */ 534 @Override applySurfaceParams( final SyncRtSurfaceTransactionApplier.SurfaceParams... params)535 public void applySurfaceParams( 536 final SyncRtSurfaceTransactionApplier.SurfaceParams... params) { 537 SurfaceControl.Transaction t = new SurfaceControl.Transaction(); 538 for (int i = params.length - 1; i >= 0; i--) { 539 SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i]; 540 applyParams(t, surfaceParams, mTmpFloat9); 541 } 542 t.apply(); 543 t.close(); 544 } 545 546 // Since we don't push applySurfaceParams to a Handler-queue we don't need 547 // to push release in this case. 548 @Override releaseSurfaceControlFromRt(SurfaceControl sc)549 public void releaseSurfaceControlFromRt(SurfaceControl sc) { 550 sc.release(); 551 } 552 553 @Override startAnimation(InsetsAnimationControlImpl controller, WindowInsetsAnimationControlListener listener, int types, WindowInsetsAnimation animation, Bounds bounds)554 public void startAnimation(InsetsAnimationControlImpl controller, 555 WindowInsetsAnimationControlListener listener, int types, 556 WindowInsetsAnimation animation, 557 Bounds bounds) { 558 } 559 560 @Override reportPerceptible(int types, boolean perceptible)561 public void reportPerceptible(int types, boolean perceptible) { 562 // No-op for now - only client windows report perceptibility for now, with policy 563 // controllers assumed to always be perceptible. 564 } 565 } 566 } 567 } 568