blob: 01abcab45760abe7858bce0eb1199f5fa9e1f8fb [file] [log] [blame]
Jorim Jaggi5a108c22016-10-13 14:33:27 +02001/*
2 * Copyright (C) 2016 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 Jaggi1b4b23e2016-11-15 16:30:12 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_UNKNOWN_APP_VISIBILITY;
20import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
21import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
22
Jorim Jaggi5a108c22016-10-13 14:33:27 +020023import android.annotation.NonNull;
24import android.util.ArrayMap;
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -080025import android.util.Slog;
Jorim Jaggi5a108c22016-10-13 14:33:27 +020026
27import com.android.server.wm.WindowManagerService.H;
28
29import java.io.PrintWriter;
30
31/**
32 * Manages the set of {@link AppWindowToken}s for which we don't know yet whether it's visible or
33 * not. This happens when starting an activity while the lockscreen is showing. In that case, the
34 * keyguard flags an app might set influence it's visibility, so we wait until this is resolved to
35 * start the transition to avoid flickers.
36 */
37class UnknownAppVisibilityController {
38
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -080039 private static final String TAG = TAG_WITH_CLASS_NAME ? "UnknownAppVisibility" : TAG_WM;
40
Jorim Jaggi5a108c22016-10-13 14:33:27 +020041 /**
42 * We are currently waiting until the app is done resuming.
43 */
44 private static final int UNKNOWN_STATE_WAITING_RESUME = 1;
45
46 /**
47 * The activity has finished resuming, and we are waiting on the next relayout.
48 */
49 private static final int UNKNOWN_STATE_WAITING_RELAYOUT = 2;
50
51 /**
52 * The client called {@link Session#relayout} with the appropriate Keyguard flags and we are
53 * waiting until activity manager has updated the visibilities of all the apps.
54 */
55 private static final int UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE = 3;
56
57 // Set of apps for which we don't know yet whether it's visible or not, depending on what kind
58 // of lockscreen flags the app might set during its first relayout.
59 private final ArrayMap<AppWindowToken, Integer> mUnknownApps = new ArrayMap<>();
60
61 private final WindowManagerService mService;
62
lumark588a3e82018-07-20 18:53:54 +080063 private final DisplayContent mDisplayContent;
64
65 UnknownAppVisibilityController(WindowManagerService service, DisplayContent displayContent) {
Jorim Jaggi5a108c22016-10-13 14:33:27 +020066 mService = service;
lumark588a3e82018-07-20 18:53:54 +080067 mDisplayContent = displayContent;
Jorim Jaggi5a108c22016-10-13 14:33:27 +020068 }
69
70 boolean allResolved() {
71 return mUnknownApps.isEmpty();
72 }
73
74 void clear() {
75 mUnknownApps.clear();
76 }
77
78 String getDebugMessage() {
79 final StringBuilder builder = new StringBuilder();
80 for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
81 builder.append("app=").append(mUnknownApps.keyAt(i))
82 .append(" state=").append(mUnknownApps.valueAt(i));
83 if (i != 0) {
84 builder.append(' ');
85 }
86 }
87 return builder.toString();
88 }
89
Jorim Jaggi45ca0542017-05-30 16:16:01 -070090 void appRemovedOrHidden(@NonNull AppWindowToken appWindow) {
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -080091 if (DEBUG_UNKNOWN_APP_VISIBILITY) {
Jorim Jaggi45ca0542017-05-30 16:16:01 -070092 Slog.d(TAG, "App removed or hidden appWindow=" + appWindow);
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -080093 }
Jorim Jaggi5a108c22016-10-13 14:33:27 +020094 mUnknownApps.remove(appWindow);
95 }
96
97 /**
98 * Notifies that {@param appWindow} has been launched behind Keyguard, and we need to wait until
99 * it is resumed and relaid out to resolve the visibility.
100 */
101 void notifyLaunched(@NonNull AppWindowToken appWindow) {
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -0800102 if (DEBUG_UNKNOWN_APP_VISIBILITY) {
103 Slog.d(TAG, "App launched appWindow=" + appWindow);
104 }
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200105 mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RESUME);
106 }
107
108 /**
109 * Notifies that {@param appWindow} has finished resuming.
110 */
111 void notifyAppResumedFinished(@NonNull AppWindowToken appWindow) {
112 if (mUnknownApps.containsKey(appWindow)
113 && mUnknownApps.get(appWindow) == UNKNOWN_STATE_WAITING_RESUME) {
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -0800114 if (DEBUG_UNKNOWN_APP_VISIBILITY) {
115 Slog.d(TAG, "App resume finished appWindow=" + appWindow);
116 }
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200117 mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RELAYOUT);
118 }
119 }
120
121 /**
122 * Notifies that {@param appWindow} has relaid out.
123 */
124 void notifyRelayouted(@NonNull AppWindowToken appWindow) {
125 if (!mUnknownApps.containsKey(appWindow)) {
126 return;
127 }
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -0800128 if (DEBUG_UNKNOWN_APP_VISIBILITY) {
129 Slog.d(TAG, "App relayouted appWindow=" + appWindow);
130 }
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200131 int state = mUnknownApps.get(appWindow);
132 if (state == UNKNOWN_STATE_WAITING_RELAYOUT) {
133 mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
lumark588a3e82018-07-20 18:53:54 +0800134 mService.notifyKeyguardFlagsChanged(this::notifyVisibilitiesUpdated,
135 appWindow.getDisplayContent().getDisplayId());
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200136 }
137 }
138
139 private void notifyVisibilitiesUpdated() {
Jorim Jaggi1b4b23e2016-11-15 16:30:12 -0800140 if (DEBUG_UNKNOWN_APP_VISIBILITY) {
141 Slog.d(TAG, "Visibility updated DONE");
142 }
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200143 boolean changed = false;
144 for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
145 if (mUnknownApps.valueAt(i) == UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE) {
146 mUnknownApps.removeAt(i);
147 changed = true;
148 }
149 }
150 if (changed) {
151 mService.mWindowPlacerLocked.performSurfacePlacement();
152 }
153 }
154
155 void dump(PrintWriter pw, String prefix) {
Jorim Jaggi8d786932016-10-26 19:08:36 -0700156 if (mUnknownApps.isEmpty()) {
157 return;
158 }
159 pw.println(prefix + "Unknown visibilities:");
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200160 for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
161 pw.println(prefix + " app=" + mUnknownApps.keyAt(i)
162 + " state=" + mUnknownApps.valueAt(i));
163 }
164 }
165}