blob: f67b11b26b124187f2df77d7b4345c26b77b0700 [file] [log] [blame]
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001/*
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
17package com.android.server.wm;
18
Jorim Jaggia2759b22019-01-24 13:21:40 +010019import static android.view.InsetsState.TYPE_IME;
20import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
21import static android.view.InsetsState.TYPE_TOP_BAR;
22import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
23import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
Jorim Jaggi73f3e8a2019-01-14 13:06:23 +010024import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
Jorim Jaggia2759b22019-01-24 13:21:40 +010025import static android.view.ViewRootImpl.sNewInsetsMode;
Jorim Jaggi73f3e8a2019-01-14 13:06:23 +010026
Jorim Jaggif96c90a2018-09-26 16:55:15 +020027import android.annotation.NonNull;
28import android.annotation.Nullable;
Tarandeep Singh215929b2019-01-11 18:24:37 -080029import android.graphics.Point;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020030import android.graphics.Rect;
Jorim Jaggib6030952018-10-23 18:31:52 +020031import android.util.proto.ProtoOutputStream;
Jorim Jaggie35c0592018-11-06 16:21:08 +010032import android.view.InsetsState;
Jorim Jaggib6030952018-10-23 18:31:52 +020033import android.view.SurfaceControl;
34import android.view.SurfaceControl.Transaction;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020035import android.view.InsetsSource;
Jorim Jaggib6030952018-10-23 18:31:52 +020036import android.view.InsetsSourceControl;
Jorim Jaggi956f1242019-01-06 22:34:13 +010037import android.view.ViewRootImpl;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020038
39import com.android.internal.util.function.TriConsumer;
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +010040import com.android.internal.util.function.pooled.PooledLambda;
Jorim Jaggib6030952018-10-23 18:31:52 +020041import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
42
43import java.io.PrintWriter;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020044
45/**
46 * Controller for a specific inset source on the server. It's called provider as it provides the
47 * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
48 */
49class InsetsSourceProvider {
50
51 private final Rect mTmpRect = new Rect();
52 private final @NonNull InsetsSource mSource;
Jorim Jaggib6030952018-10-23 18:31:52 +020053 private final DisplayContent mDisplayContent;
54 private final InsetsStateController mStateController;
55 private @Nullable InsetsSourceControl mControl;
56 private @Nullable WindowState mControllingWin;
57 private @Nullable ControlAdapter mAdapter;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020058 private WindowState mWin;
59 private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
60
Jorim Jaggie35c0592018-11-06 16:21:08 +010061 /** The visibility override from the current controlling window. */
62 private boolean mClientVisible;
63
64 /**
65 * Whether the window is available and considered visible as in {@link WindowState#isVisible}.
66 */
67 private boolean mServerVisible;
68
Jorim Jaggia2759b22019-01-24 13:21:40 +010069 private final boolean mControllable;
Jorim Jaggie35c0592018-11-06 16:21:08 +010070
Jorim Jaggib6030952018-10-23 18:31:52 +020071 InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
72 DisplayContent displayContent) {
Jorim Jaggid89efeb2019-01-22 17:48:34 +010073 mClientVisible = InsetsState.getDefaultVisibility(source.getType());
Jorim Jaggif96c90a2018-09-26 16:55:15 +020074 mSource = source;
Jorim Jaggib6030952018-10-23 18:31:52 +020075 mDisplayContent = displayContent;
76 mStateController = stateController;
Jorim Jaggia2759b22019-01-24 13:21:40 +010077
78 final int type = source.getType();
79 if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
80 mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
81 } else if (type == TYPE_IME) {
82 mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
83 } else {
84 mControllable = false;
85 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +020086 }
87
88 InsetsSource getSource() {
89 return mSource;
90 }
91
92 /**
Jorim Jaggia2759b22019-01-24 13:21:40 +010093 * @return Whether the current flag configuration allows to control this source.
94 */
95 boolean isControllable() {
96 return mControllable;
97 }
98
99 /**
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200100 * Updates the window that currently backs this source.
101 *
102 * @param win The window that links to this source.
103 * @param frameProvider Based on display frame state and the window, calculates the resulting
104 * frame that should be reported to clients.
105 */
106 void setWindow(@Nullable WindowState win,
107 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
108 if (mWin != null) {
109 mWin.setInsetProvider(null);
110 }
111 mWin = win;
112 mFrameProvider = frameProvider;
113 if (win == null) {
Jorim Jaggie35c0592018-11-06 16:21:08 +0100114 setServerVisible(false);
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200115 mSource.setFrame(new Rect());
116 } else {
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200117 mWin.setInsetProvider(this);
Jorim Jaggia2759b22019-01-24 13:21:40 +0100118 if (mControllingWin != null) {
119 updateControlForTarget(mControllingWin, true /* force */);
120 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200121 }
122 }
123
124 /**
125 * Called when a layout pass has occurred.
126 */
127 void onPostLayout() {
128 if (mWin == null) {
129 return;
130 }
131
132 mTmpRect.set(mWin.getFrameLw());
133 if (mFrameProvider != null) {
134 mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
135 } else {
136 mTmpRect.inset(mWin.mGivenContentInsets);
137 }
138 mSource.setFrame(mTmpRect);
Tarandeep Singh215929b2019-01-11 18:24:37 -0800139 if (mControl != null) {
140 final Rect frame = mWin.getWindowFrames().mFrame;
141 if (mControl.setSurfacePosition(frame.left, frame.top)) {
142 mStateController.notifyControlChanged(mControllingWin);
143 }
144 }
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100145 setServerVisible(mWin.wouldBeVisibleIfPolicyIgnored() && mWin.mPolicyVisibility
146 && !mWin.mGivenInsetsPending);
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200147 }
Jorim Jaggib6030952018-10-23 18:31:52 +0200148
Jorim Jaggia2759b22019-01-24 13:21:40 +0100149 void updateControlForTarget(@Nullable WindowState target, boolean force) {
150 if (mWin == null) {
151 mControllingWin = target;
152 return;
153 }
154 if (target == mControllingWin && !force) {
Jorim Jaggib6030952018-10-23 18:31:52 +0200155 return;
156 }
157 if (target == null) {
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100158 // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
159 mWin.cancelAnimation();
Jorim Jaggib6030952018-10-23 18:31:52 +0200160 return;
161 }
162 mAdapter = new ControlAdapter();
Jorim Jaggid89efeb2019-01-22 17:48:34 +0100163 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
Jorim Jaggib6030952018-10-23 18:31:52 +0200164 mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter,
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100165 !mClientVisible /* hidden */);
Jorim Jaggib6030952018-10-23 18:31:52 +0200166 mControllingWin = target;
Tarandeep Singh215929b2019-01-11 18:24:37 -0800167 mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash,
168 new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top));
Jorim Jaggie35c0592018-11-06 16:21:08 +0100169 }
170
171 boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) {
172 if (mControllingWin != caller || modifiedSource.isVisible() == mClientVisible) {
173 return false;
174 }
175 setClientVisible(modifiedSource.isVisible());
176 return true;
177 }
178
179 private void setClientVisible(boolean clientVisible) {
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100180 if (mClientVisible == clientVisible) {
181 return;
182 }
Jorim Jaggie35c0592018-11-06 16:21:08 +0100183 mClientVisible = clientVisible;
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100184 mDisplayContent.mWmService.mH.sendMessage(PooledLambda.obtainMessage(
185 DisplayContent::layoutAndAssignWindowLayersIfNeeded, mDisplayContent));
Jorim Jaggie35c0592018-11-06 16:21:08 +0100186 updateVisibility();
187 }
188
189 private void setServerVisible(boolean serverVisible) {
190 mServerVisible = serverVisible;
191 updateVisibility();
192 }
193
194 private void updateVisibility() {
195 mSource.setVisible(mServerVisible && mClientVisible);
Jorim Jaggib6030952018-10-23 18:31:52 +0200196 }
197
198 InsetsSourceControl getControl() {
199 return mControl;
200 }
201
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100202 boolean isClientVisible() {
Jorim Jaggia2759b22019-01-24 13:21:40 +0100203 return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
Jorim Jaggib6030952018-10-23 18:31:52 +0200204 }
205
206 private class ControlAdapter implements AnimationAdapter {
207
208 private SurfaceControl mCapturedLeash;
209
210 @Override
211 public boolean getShowWallpaper() {
212 return false;
213 }
214
215 @Override
216 public int getBackgroundColor() {
217 return 0;
218 }
219
220 @Override
221 public void startAnimation(SurfaceControl animationLeash, Transaction t,
222 OnAnimationFinishedCallback finishCallback) {
223 mCapturedLeash = animationLeash;
Tarandeep Singh215929b2019-01-11 18:24:37 -0800224 final Rect frame = mWin.getWindowFrames().mFrame;
225 t.setPosition(mCapturedLeash, frame.left, frame.top);
Jorim Jaggib6030952018-10-23 18:31:52 +0200226 }
227
228 @Override
229 public void onAnimationCancelled(SurfaceControl animationLeash) {
230 if (mAdapter == this) {
231 mStateController.notifyControlRevoked(mControllingWin, InsetsSourceProvider.this);
Jorim Jaggid89efeb2019-01-22 17:48:34 +0100232 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
Jorim Jaggib6030952018-10-23 18:31:52 +0200233 mControl = null;
234 mControllingWin = null;
235 mAdapter = null;
236 }
237 }
238
239 @Override
240 public long getDurationHint() {
241 return 0;
242 }
243
244 @Override
245 public long getStatusBarTransitionsStartTime() {
246 return 0;
247 }
248
249 @Override
250 public void dump(PrintWriter pw, String prefix) {
251 }
252
253 @Override
254 public void writeToProto(ProtoOutputStream proto) {
255 }
256 };
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200257}