blob: 4ac319ddf6ce1cc46b8e93f1b980c993b8cd33e0 [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
Winson Chung8a168902020-03-12 22:39:22 -070019import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
Tiger Huang0f5347e2020-03-06 17:09:41 +080020import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Tiger Huanga16634032020-02-05 17:10:03 +080021import static android.view.InsetsState.ITYPE_CAPTION_BAR;
Tiger Huang332793b2019-10-29 23:21:27 +080022import static android.view.InsetsState.ITYPE_IME;
Charles Chenb8070fb2020-02-24 15:42:59 +080023import static android.view.InsetsState.ITYPE_INVALID;
Tiger Huang332793b2019-10-29 23:21:27 +080024import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
25import static android.view.InsetsState.ITYPE_STATUS_BAR;
Jorim Jaggia12ea562019-01-07 17:47:47 +010026import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
27import static android.view.ViewRootImpl.sNewInsetsMode;
Charles Chenb8070fb2020-02-24 15:42:59 +080028import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
29import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
30import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020031
Jorim Jaggib6030952018-10-23 18:31:52 +020032import android.annotation.NonNull;
33import android.annotation.Nullable;
Tiger Huang0f5347e2020-03-06 17:09:41 +080034import android.app.WindowConfiguration;
35import android.app.WindowConfiguration.WindowingMode;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020036import android.util.ArrayMap;
Jorim Jaggib6030952018-10-23 18:31:52 +020037import android.util.ArraySet;
38import android.util.SparseArray;
Jorim Jaggie35c0592018-11-06 16:21:08 +010039import android.view.InsetsSource;
Jorim Jaggib6030952018-10-23 18:31:52 +020040import android.view.InsetsSourceControl;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020041import android.view.InsetsState;
Tiger Huang332793b2019-10-29 23:21:27 +080042import android.view.InsetsState.InternalInsetsType;
Charles Chenb8070fb2020-02-24 15:42:59 +080043import android.view.WindowManager;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020044
45import java.io.PrintWriter;
Jorim Jaggib6030952018-10-23 18:31:52 +020046import java.util.ArrayList;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020047import java.util.function.Consumer;
48
49/**
50 * Manages global window inset state in the system represented by {@link InsetsState}.
51 */
52class InsetsStateController {
53
54 private final InsetsState mLastState = new InsetsState();
55 private final InsetsState mState = new InsetsState();
56 private final DisplayContent mDisplayContent;
Jorim Jaggib6030952018-10-23 18:31:52 +020057
Jorim Jaggi28620472019-01-02 23:21:49 +010058 private final ArrayMap<Integer, InsetsSourceProvider> mProviders = new ArrayMap<>();
59 private final ArrayMap<InsetsControlTarget, ArrayList<Integer>> mControlTargetTypeMap =
60 new ArrayMap<>();
61 private final SparseArray<InsetsControlTarget> mTypeControlTargetMap = new SparseArray<>();
Jorim Jaggia12ea562019-01-07 17:47:47 +010062
63 /** @see #onControlFakeTargetChanged */
64 private final SparseArray<InsetsControlTarget> mTypeFakeControlTargetMap = new SparseArray<>();
65
Jorim Jaggi28620472019-01-02 23:21:49 +010066 private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();
Jorim Jaggif96c90a2018-09-26 16:55:15 +020067
68 private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
69 if (w.isVisible()) {
70 w.notifyInsetsChanged();
71 }
72 };
Tiger Huangb9510ef2020-03-03 23:03:39 +080073 private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { };
Jorim Jaggif96c90a2018-09-26 16:55:15 +020074
75 InsetsStateController(DisplayContent displayContent) {
76 mDisplayContent = displayContent;
77 }
78
79 /**
80 * When dispatching window state to the client, we'll need to exclude the source that represents
Tiger Huang0f5347e2020-03-06 17:09:41 +080081 * the window that is being dispatched. We also need to exclude certain types of insets source
82 * for client within specific windowing modes.
Jorim Jaggif96c90a2018-09-26 16:55:15 +020083 *
84 * @param target The client we dispatch the state to.
85 * @return The state stripped of the necessary information.
86 */
Charles Chenb8070fb2020-02-24 15:42:59 +080087 InsetsState getInsetsForDispatch(@NonNull WindowState target) {
Jorim Jaggi956ca412019-01-07 14:49:14 +010088 final InsetsSourceProvider provider = target.getControllableInsetProvider();
Tiger Huang0f5347e2020-03-06 17:09:41 +080089 final @InternalInsetsType int type = provider != null
90 ? provider.getSource().getType() : ITYPE_INVALID;
Tiger Huang57e2e1c2020-03-13 22:54:36 +080091 return getInsetsForDispatchInner(type, target.getWindowingMode(), target.isAlwaysOnTop(),
92 isAboveIme(target));
Charles Chenb8070fb2020-02-24 15:42:59 +080093 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +020094
Charles Chenb8070fb2020-02-24 15:42:59 +080095 InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
96 final @InternalInsetsType int type = getInsetsTypeForWindowType(attrs.type);
Tiger Huang0f5347e2020-03-06 17:09:41 +080097 final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
98 final @WindowingMode int windowingMode = token != null
99 ? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
Tiger Huang57e2e1c2020-03-13 22:54:36 +0800100 final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
101 return getInsetsForDispatchInner(type, windowingMode, alwaysOnTop, isAboveIme(token));
102 }
103
104 private boolean isAboveIme(WindowContainer target) {
105 final WindowState imeWindow = mDisplayContent.mInputMethodWindow;
106 if (target == null || imeWindow == null) {
107 return false;
108 }
109 if (target instanceof WindowState) {
110 final WindowState win = (WindowState) target;
111 return win.needsRelativeLayeringToIme() || !win.mBehindIme;
112 }
113 return false;
Charles Chenb8070fb2020-02-24 15:42:59 +0800114 }
115
Tiger Huang0f5347e2020-03-06 17:09:41 +0800116 private static @InternalInsetsType int getInsetsTypeForWindowType(int type) {
Tiger Huang57e2e1c2020-03-13 22:54:36 +0800117 switch (type) {
Charles Chenb8070fb2020-02-24 15:42:59 +0800118 case TYPE_STATUS_BAR:
119 return ITYPE_STATUS_BAR;
120 case TYPE_NAVIGATION_BAR:
121 return ITYPE_NAVIGATION_BAR;
122 case TYPE_INPUT_METHOD:
123 return ITYPE_IME;
124 default:
125 return ITYPE_INVALID;
126 }
127 }
128
Tiger Huang0f5347e2020-03-06 17:09:41 +0800129 /** @see #getInsetsForDispatch */
Tiger Huang57e2e1c2020-03-13 22:54:36 +0800130 private InsetsState getInsetsForDispatchInner(@InternalInsetsType int type,
131 @WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme) {
Tiger Huang0f5347e2020-03-06 17:09:41 +0800132 InsetsState state = mState;
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200133
Tiger Huang0f5347e2020-03-06 17:09:41 +0800134 if (type != ITYPE_INVALID) {
135 state = new InsetsState(state);
136 state.removeSource(type);
Tiger Huanga16634032020-02-05 17:10:03 +0800137
Tiger Huang0f5347e2020-03-06 17:09:41 +0800138 // Navigation bar doesn't get influenced by anything else
139 if (type == ITYPE_NAVIGATION_BAR) {
140 state.removeSource(ITYPE_IME);
141 state.removeSource(ITYPE_STATUS_BAR);
142 state.removeSource(ITYPE_CAPTION_BAR);
143 }
Jorim Jaggi9b4f4202020-01-28 17:05:06 +0100144
Tiger Huang0f5347e2020-03-06 17:09:41 +0800145 // Status bar doesn't get influenced by caption bar
146 if (type == ITYPE_STATUS_BAR) {
147 state.removeSource(ITYPE_CAPTION_BAR);
148 }
149
150 // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
151 if (type == ITYPE_IME) {
152 for (int i = mProviders.size() - 1; i >= 0; i--) {
153 InsetsSourceProvider otherProvider = mProviders.valueAt(i);
154 if (otherProvider.overridesImeFrame()) {
155 InsetsSource override =
156 new InsetsSource(
157 state.getSource(otherProvider.getSource().getType()));
158 override.setFrame(otherProvider.getImeOverrideFrame());
159 state.addSource(override);
160 }
Jorim Jaggi9b4f4202020-01-28 17:05:06 +0100161 }
162 }
163 }
164
Winson Chung8a168902020-03-12 22:39:22 -0700165 if (WindowConfiguration.isFloating(windowingMode)
166 || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
Tiger Huang0f5347e2020-03-06 17:09:41 +0800167 state = new InsetsState(state);
168 state.removeSource(ITYPE_STATUS_BAR);
169 state.removeSource(ITYPE_NAVIGATION_BAR);
170 }
171
Tiger Huang57e2e1c2020-03-13 22:54:36 +0800172 if (aboveIme) {
173 state = new InsetsState(state);
Tiger Huanga70fd872020-04-15 05:25:16 +0800174 state.setSourceVisible(ITYPE_IME, false);
Tiger Huang57e2e1c2020-03-13 22:54:36 +0800175 }
176
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200177 return state;
178 }
179
Evan Rosky8d782e02019-10-14 15:43:53 -0700180 InsetsState getRawInsetsState() {
181 return mState;
182 }
183
Jorim Jaggi28620472019-01-02 23:21:49 +0100184 @Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) {
185 ArrayList<Integer> controlled = mControlTargetTypeMap.get(target);
Jorim Jaggib6030952018-10-23 18:31:52 +0200186 if (controlled == null) {
187 return null;
188 }
189 final int size = controlled.size();
190 final InsetsSourceControl[] result = new InsetsSourceControl[size];
191 for (int i = 0; i < size; i++) {
Jorim Jaggia12ea562019-01-07 17:47:47 +0100192 result[i] = mProviders.get(controlled.get(i)).getControl(target);
Jorim Jaggib6030952018-10-23 18:31:52 +0200193 }
194 return result;
195 }
196
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200197 /**
198 * @return The provider of a specific type.
199 */
Tiger Huang332793b2019-10-29 23:21:27 +0800200 InsetsSourceProvider getSourceProvider(@InternalInsetsType int type) {
201 if (type == ITYPE_IME) {
Tarandeep Singh500a38f2019-09-26 13:36:40 -0700202 return mProviders.computeIfAbsent(type,
203 key -> new ImeInsetsSourceProvider(
204 mState.getSource(key), this, mDisplayContent));
205 } else {
206 return mProviders.computeIfAbsent(type,
207 key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent));
208 }
209 }
210
211 ImeInsetsSourceProvider getImeSourceProvider() {
Tiger Huang332793b2019-10-29 23:21:27 +0800212 return (ImeInsetsSourceProvider) getSourceProvider(ITYPE_IME);
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200213 }
214
215 /**
Jorim Jaggi956ca412019-01-07 14:49:14 +0100216 * @return The provider of a specific type or null if we don't have it.
217 */
Tiger Huang332793b2019-10-29 23:21:27 +0800218 @Nullable InsetsSourceProvider peekSourceProvider(@InternalInsetsType int type) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100219 return mProviders.get(type);
220 }
221
222 /**
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200223 * Called when a layout pass has occurred.
224 */
225 void onPostLayout() {
Tarandeep Singha6f35612019-01-11 19:50:46 -0800226 mState.setDisplayFrame(mDisplayContent.getBounds());
Jorim Jaggi28620472019-01-02 23:21:49 +0100227 for (int i = mProviders.size() - 1; i >= 0; i--) {
228 mProviders.valueAt(i).onPostLayout();
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200229 }
Tiger Huang53c8eb82020-03-31 18:22:05 +0800230 final ArrayList<WindowState> winInsetsChanged = mDisplayContent.mWinInsetsChanged;
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200231 if (!mLastState.equals(mState)) {
232 mLastState.set(mState, true /* copySources */);
233 notifyInsetsChanged();
Tiger Huang53c8eb82020-03-31 18:22:05 +0800234 } else {
235 // The global insets state has not changed but there might be windows whose conditions
236 // (e.g., z-order) have changed. They can affect the insets states that we dispatch to
237 // the clients.
238 for (int i = winInsetsChanged.size() - 1; i >= 0; i--) {
239 winInsetsChanged.get(i).notifyInsetsChanged();
240 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200241 }
Tiger Huang53c8eb82020-03-31 18:22:05 +0800242 winInsetsChanged.clear();
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200243 }
244
Evan Rosky8d782e02019-10-14 15:43:53 -0700245 void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
Jorim Jaggie35c0592018-11-06 16:21:08 +0100246 boolean changed = false;
247 for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
248 final InsetsSource source = state.sourceAt(i);
Jorim Jaggi28620472019-01-02 23:21:49 +0100249 final InsetsSourceProvider provider = mProviders.get(source.getType());
Jorim Jaggie35c0592018-11-06 16:21:08 +0100250 if (provider == null) {
251 continue;
252 }
253 changed |= provider.onInsetsModified(windowState, source);
254 }
255 if (changed) {
256 notifyInsetsChanged();
Tiger Huangdd6db472020-02-13 21:38:46 +0800257 mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw();
Jorim Jaggie35c0592018-11-06 16:21:08 +0100258 }
259 }
260
Riddle Hsuc7175762020-01-10 21:03:48 +0800261 /**
262 * Computes insets state of the insets provider window in the display frames.
263 *
264 * @param state The output state.
265 * @param win The owner window of insets provider.
266 * @param displayFrames The display frames to create insets source.
267 * @param windowFrames The specified frames to represent the owner window.
268 */
269 void computeSimulatedState(InsetsState state, WindowState win, DisplayFrames displayFrames,
270 WindowFrames windowFrames) {
271 for (int i = mProviders.size() - 1; i >= 0; i--) {
272 final InsetsSourceProvider provider = mProviders.valueAt(i);
273 if (provider.mWin == win) {
274 state.addSource(provider.createSimulatedSource(displayFrames, windowFrames));
275 }
276 }
277 }
278
Tiger Huang332793b2019-10-29 23:21:27 +0800279 boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100280 return mTypeFakeControlTargetMap.get(type) == target;
281 }
282
Tarandeep Singha6590182020-01-24 16:05:18 -0800283 void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) {
Jorim Jaggif768ea52020-01-30 23:45:23 +0100284
285 // Make sure that we always have a control target for the IME, even if the IME target is
286 // null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible.
287 onControlChanged(ITYPE_IME, imeTarget != null ? imeTarget : mEmptyImeControlTarget);
Jorim Jaggib6030952018-10-23 18:31:52 +0200288 notifyPendingInsetsControlChanged();
289 }
290
291 /**
Jorim Jaggi28620472019-01-02 23:21:49 +0100292 * Called when the focused window that is able to control the system bars changes.
Jorim Jaggib6030952018-10-23 18:31:52 +0200293 *
Tiger Huanga16634032020-02-05 17:10:03 +0800294 * @param statusControlling The target that is now able to control the status bar appearance
295 * and visibility.
Jorim Jaggi28620472019-01-02 23:21:49 +0100296 * @param navControlling The target that is now able to control the nav bar appearance
297 * and visibility.
Jorim Jaggib6030952018-10-23 18:31:52 +0200298 */
Tiger Huanga16634032020-02-05 17:10:03 +0800299 void onBarControlTargetChanged(@Nullable InsetsControlTarget statusControlling,
300 @Nullable InsetsControlTarget fakeStatusControlling,
Jorim Jaggi956ca412019-01-07 14:49:14 +0100301 @Nullable InsetsControlTarget navControlling,
302 @Nullable InsetsControlTarget fakeNavControlling) {
Tiger Huanga16634032020-02-05 17:10:03 +0800303 onControlChanged(ITYPE_STATUS_BAR, statusControlling);
Tiger Huang332793b2019-10-29 23:21:27 +0800304 onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
Tiger Huanga16634032020-02-05 17:10:03 +0800305 onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
Tiger Huang332793b2019-10-29 23:21:27 +0800306 onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
Jorim Jaggib6030952018-10-23 18:31:52 +0200307 notifyPendingInsetsControlChanged();
308 }
309
Jorim Jaggi28620472019-01-02 23:21:49 +0100310 void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget,
Jorim Jaggib6030952018-10-23 18:31:52 +0200311 InsetsSourceProvider provider) {
Jorim Jaggia12ea562019-01-07 17:47:47 +0100312 removeFromControlMaps(previousControlTarget, provider.getSource().getType(),
313 false /* fake */);
Jorim Jaggib6030952018-10-23 18:31:52 +0200314 }
315
Tiger Huang332793b2019-10-29 23:21:27 +0800316 private void onControlChanged(@InternalInsetsType int type,
Jorim Jaggi28620472019-01-02 23:21:49 +0100317 @Nullable InsetsControlTarget target) {
318 final InsetsControlTarget previous = mTypeControlTargetMap.get(type);
319 if (target == previous) {
Jorim Jaggib6030952018-10-23 18:31:52 +0200320 return;
321 }
Tiger Huang969c6082019-12-24 20:08:57 +0800322 final InsetsSourceProvider provider = mProviders.get(type);
Jorim Jaggi28620472019-01-02 23:21:49 +0100323 if (provider == null) {
Jorim Jaggib6030952018-10-23 18:31:52 +0200324 return;
325 }
Jorim Jaggi28620472019-01-02 23:21:49 +0100326 if (!provider.isControllable()) {
Jorim Jaggia2759b22019-01-24 13:21:40 +0100327 return;
328 }
Jorim Jaggi28620472019-01-02 23:21:49 +0100329 provider.updateControlForTarget(target, false /* force */);
Tiger Huang969c6082019-12-24 20:08:57 +0800330 target = provider.getControlTarget();
Jorim Jaggib6030952018-10-23 18:31:52 +0200331 if (previous != null) {
Jorim Jaggia12ea562019-01-07 17:47:47 +0100332 removeFromControlMaps(previous, type, false /* fake */);
Jorim Jaggib6030952018-10-23 18:31:52 +0200333 mPendingControlChanged.add(previous);
334 }
Jorim Jaggi28620472019-01-02 23:21:49 +0100335 if (target != null) {
Jorim Jaggia12ea562019-01-07 17:47:47 +0100336 addToControlMaps(target, type, false /* fake */);
Jorim Jaggi28620472019-01-02 23:21:49 +0100337 mPendingControlChanged.add(target);
Jorim Jaggib6030952018-10-23 18:31:52 +0200338 }
339 }
340
Jorim Jaggia12ea562019-01-07 17:47:47 +0100341 /**
342 * The fake target saved here will be used to pretend to the app that it's still under control
343 * of the bars while it's not really, but we still need to find out the apps intentions around
344 * showing/hiding. For example, when the transient bars are showing, and the fake target
345 * requests to show system bars, the transient state will be aborted.
346 */
Tiger Huang332793b2019-10-29 23:21:27 +0800347 void onControlFakeTargetChanged(@InternalInsetsType int type,
Jorim Jaggia12ea562019-01-07 17:47:47 +0100348 @Nullable InsetsControlTarget fakeTarget) {
349 if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
350 return;
351 }
352 final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type);
353 if (fakeTarget == previous) {
354 return;
355 }
356 final InsetsSourceProvider provider = mProviders.get(type);
357 if (provider == null) {
358 return;
359 }
360 provider.updateControlForFakeTarget(fakeTarget);
361 if (previous != null) {
362 removeFromControlMaps(previous, type, true /* fake */);
363 mPendingControlChanged.add(previous);
364 }
365 if (fakeTarget != null) {
366 addToControlMaps(fakeTarget, type, true /* fake */);
367 mPendingControlChanged.add(fakeTarget);
368 }
369 }
370
Jorim Jaggi28620472019-01-02 23:21:49 +0100371 private void removeFromControlMaps(@NonNull InsetsControlTarget target,
Tiger Huang332793b2019-10-29 23:21:27 +0800372 @InternalInsetsType int type, boolean fake) {
Jorim Jaggi28620472019-01-02 23:21:49 +0100373 final ArrayList<Integer> array = mControlTargetTypeMap.get(target);
Jorim Jaggib6030952018-10-23 18:31:52 +0200374 if (array == null) {
375 return;
376 }
377 array.remove((Integer) type);
378 if (array.isEmpty()) {
Jorim Jaggi28620472019-01-02 23:21:49 +0100379 mControlTargetTypeMap.remove(target);
Jorim Jaggib6030952018-10-23 18:31:52 +0200380 }
Jorim Jaggia12ea562019-01-07 17:47:47 +0100381 if (fake) {
382 mTypeFakeControlTargetMap.remove(type);
383 } else {
384 mTypeControlTargetMap.remove(type);
385 }
Jorim Jaggib6030952018-10-23 18:31:52 +0200386 }
387
Jorim Jaggi28620472019-01-02 23:21:49 +0100388 private void addToControlMaps(@NonNull InsetsControlTarget target,
Tiger Huang332793b2019-10-29 23:21:27 +0800389 @InternalInsetsType int type, boolean fake) {
Jorim Jaggi28620472019-01-02 23:21:49 +0100390 final ArrayList<Integer> array = mControlTargetTypeMap.computeIfAbsent(target,
Jorim Jaggib6030952018-10-23 18:31:52 +0200391 key -> new ArrayList<>());
392 array.add(type);
Jorim Jaggia12ea562019-01-07 17:47:47 +0100393 if (fake) {
394 mTypeFakeControlTargetMap.put(type, target);
395 } else {
396 mTypeControlTargetMap.put(type, target);
397 }
Jorim Jaggib6030952018-10-23 18:31:52 +0200398 }
399
Jorim Jaggi28620472019-01-02 23:21:49 +0100400 void notifyControlChanged(InsetsControlTarget target) {
Tarandeep Singh215929b2019-01-11 18:24:37 -0800401 mPendingControlChanged.add(target);
402 notifyPendingInsetsControlChanged();
403 }
404
Jorim Jaggib6030952018-10-23 18:31:52 +0200405 private void notifyPendingInsetsControlChanged() {
Jorim Jaggif86eb492019-01-09 17:37:08 +0100406 if (mPendingControlChanged.isEmpty()) {
407 return;
408 }
Jorim Jaggib6030952018-10-23 18:31:52 +0200409 mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
410 for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
Jorim Jaggi28620472019-01-02 23:21:49 +0100411 final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
412 controlTarget.notifyInsetsControlChanged();
Jorim Jaggib6030952018-10-23 18:31:52 +0200413 }
414 mPendingControlChanged.clear();
415 });
416 }
417
Jorim Jaggi956ca412019-01-07 14:49:14 +0100418 void notifyInsetsChanged() {
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200419 mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
Evan Rosky8d782e02019-10-14 15:43:53 -0700420 if (mDisplayContent.mRemoteInsetsControlTarget != null) {
421 mDisplayContent.mRemoteInsetsControlTarget.notifyInsetsChanged();
422 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200423 }
424
425 void dump(String prefix, PrintWriter pw) {
426 pw.println(prefix + "WindowInsetsStateController");
427 mState.dump(prefix + " ", pw);
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100428 pw.println(prefix + " " + "Control map:");
Jorim Jaggi28620472019-01-02 23:21:49 +0100429 for (int i = mTypeControlTargetMap.size() - 1; i >= 0; i--) {
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100430 pw.print(prefix + " ");
Jorim Jaggi28620472019-01-02 23:21:49 +0100431 pw.println(InsetsState.typeToString(mTypeControlTargetMap.keyAt(i)) + " -> "
432 + mTypeControlTargetMap.valueAt(i));
Jorim Jaggicfd6f3b2018-11-07 15:30:18 +0100433 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200434 }
435}