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.TYPE_IME;
20 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
21 import static android.view.InsetsState.TYPE_TOP_BAR;
22 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
23 import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
24 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
25 import static android.view.ViewRootImpl.sNewInsetsMode;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.graphics.Point;
30 import android.graphics.Rect;
31 import android.util.proto.ProtoOutputStream;
32 import android.view.InsetsSource;
33 import android.view.InsetsSourceControl;
34 import android.view.InsetsState;
35 import android.view.SurfaceControl;
36 import android.view.SurfaceControl.Transaction;
37 
38 import com.android.internal.util.function.TriConsumer;
39 import com.android.internal.util.function.pooled.PooledLambda;
40 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
41 
42 import java.io.PrintWriter;
43 
44 /**
45  * Controller for a specific inset source on the server. It's called provider as it provides the
46  * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
47  */
48 class InsetsSourceProvider {
49 
50     private final Rect mTmpRect = new Rect();
51     private final @NonNull InsetsSource mSource;
52     private final DisplayContent mDisplayContent;
53     private final InsetsStateController mStateController;
54     private @Nullable InsetsSourceControl mControl;
55     private @Nullable WindowState mControllingWin;
56     private @Nullable ControlAdapter mAdapter;
57     private WindowState mWin;
58     private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
59 
60     /** The visibility override from the current controlling window. */
61     private boolean mClientVisible;
62 
63     /**
64      * Whether the window is available and considered visible as in {@link WindowState#isVisible}.
65      */
66     private boolean mServerVisible;
67 
68     private final boolean mControllable;
69 
InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, DisplayContent displayContent)70     InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
71             DisplayContent displayContent) {
72         mClientVisible = InsetsState.getDefaultVisibility(source.getType());
73         mSource = source;
74         mDisplayContent = displayContent;
75         mStateController = stateController;
76 
77         final int type = source.getType();
78         if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
79             mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
80         } else if (type == TYPE_IME) {
81             mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
82         } else {
83             mControllable = false;
84         }
85     }
86 
getSource()87     InsetsSource getSource() {
88         return mSource;
89     }
90 
91     /**
92      * @return Whether the current flag configuration allows to control this source.
93      */
isControllable()94     boolean isControllable() {
95         return mControllable;
96     }
97 
98     /**
99      * Updates the window that currently backs this source.
100      *
101      * @param win The window that links to this source.
102      * @param frameProvider Based on display frame state and the window, calculates the resulting
103      *                      frame that should be reported to clients.
104      */
setWindow(@ullable WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)105     void setWindow(@Nullable WindowState win,
106             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
107         if (mWin != null) {
108             mWin.setInsetProvider(null);
109         }
110         mWin = win;
111         mFrameProvider = frameProvider;
112         if (win == null) {
113             setServerVisible(false);
114             mSource.setFrame(new Rect());
115         } else {
116             mWin.setInsetProvider(this);
117             if (mControllingWin != null) {
118                 updateControlForTarget(mControllingWin, true /* force */);
119             }
120         }
121     }
122 
123     /**
124      * Called when a layout pass has occurred.
125      */
onPostLayout()126     void onPostLayout() {
127         if (mWin == null) {
128             return;
129         }
130 
131         mTmpRect.set(mWin.getFrameLw());
132         if (mFrameProvider != null) {
133             mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
134         } else {
135             mTmpRect.inset(mWin.mGivenContentInsets);
136         }
137         mSource.setFrame(mTmpRect);
138         if (mControl != null) {
139             final Rect frame = mWin.getWindowFrames().mFrame;
140             if (mControl.setSurfacePosition(frame.left, frame.top)) {
141                 mStateController.notifyControlChanged(mControllingWin);
142             }
143         }
144         setServerVisible(mWin.wouldBeVisibleIfPolicyIgnored() && mWin.isVisibleByPolicy()
145                 && !mWin.mGivenInsetsPending);
146     }
147 
updateControlForTarget(@ullable WindowState target, boolean force)148     void updateControlForTarget(@Nullable WindowState target, boolean force) {
149         if (mWin == null) {
150             mControllingWin = target;
151             return;
152         }
153         if (target == mControllingWin && !force) {
154             return;
155         }
156         if (target == null) {
157             // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
158             mWin.cancelAnimation();
159             return;
160         }
161         mAdapter = new ControlAdapter();
162         setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
163         mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter,
164                 !mClientVisible /* hidden */);
165         mControllingWin = target;
166         mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash,
167                 new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top));
168     }
169 
onInsetsModified(WindowState caller, InsetsSource modifiedSource)170     boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) {
171         if (mControllingWin != caller || modifiedSource.isVisible() == mClientVisible) {
172             return false;
173         }
174         setClientVisible(modifiedSource.isVisible());
175         return true;
176     }
177 
setClientVisible(boolean clientVisible)178     private void setClientVisible(boolean clientVisible) {
179         if (mClientVisible == clientVisible) {
180             return;
181         }
182         mClientVisible = clientVisible;
183         mDisplayContent.mWmService.mH.sendMessage(PooledLambda.obtainMessage(
184                 DisplayContent::layoutAndAssignWindowLayersIfNeeded, mDisplayContent));
185         updateVisibility();
186     }
187 
setServerVisible(boolean serverVisible)188     private void setServerVisible(boolean serverVisible) {
189         mServerVisible = serverVisible;
190         updateVisibility();
191     }
192 
updateVisibility()193     private void updateVisibility() {
194         mSource.setVisible(mServerVisible && mClientVisible);
195     }
196 
getControl()197     InsetsSourceControl getControl() {
198         return mControl;
199     }
200 
isClientVisible()201     boolean isClientVisible() {
202         return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
203     }
204 
205     private class ControlAdapter implements AnimationAdapter {
206 
207         private SurfaceControl mCapturedLeash;
208 
209         @Override
getShowWallpaper()210         public boolean getShowWallpaper() {
211             return false;
212         }
213 
214         @Override
getBackgroundColor()215         public int getBackgroundColor() {
216             return 0;
217         }
218 
219         @Override
startAnimation(SurfaceControl animationLeash, Transaction t, OnAnimationFinishedCallback finishCallback)220         public void startAnimation(SurfaceControl animationLeash, Transaction t,
221                 OnAnimationFinishedCallback finishCallback) {
222             mCapturedLeash = animationLeash;
223             final Rect frame = mWin.getWindowFrames().mFrame;
224             t.setPosition(mCapturedLeash, frame.left, frame.top);
225         }
226 
227         @Override
onAnimationCancelled(SurfaceControl animationLeash)228         public void onAnimationCancelled(SurfaceControl animationLeash) {
229             if (mAdapter == this) {
230                 mStateController.notifyControlRevoked(mControllingWin, InsetsSourceProvider.this);
231                 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
232                 mControl = null;
233                 mControllingWin = null;
234                 mAdapter = null;
235             }
236         }
237 
238         @Override
getDurationHint()239         public long getDurationHint() {
240             return 0;
241         }
242 
243         @Override
getStatusBarTransitionsStartTime()244         public long getStatusBarTransitionsStartTime() {
245             return 0;
246         }
247 
248         @Override
dump(PrintWriter pw, String prefix)249         public void dump(PrintWriter pw, String prefix) {
250         }
251 
252         @Override
writeToProto(ProtoOutputStream proto)253         public void writeToProto(ProtoOutputStream proto) {
254         }
255     };
256 }
257