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