• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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