15a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi/* 25a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Copyright (C) 2016 The Android Open Source Project 35a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * 45a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 55a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * you may not use this file except in compliance with the License. 65a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * You may obtain a copy of the License at 75a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * 85a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 95a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * 105a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Unless required by applicable law or agreed to in writing, software 115a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 125a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * See the License for the specific language governing permissions and 145a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * limitations under the License 155a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 165a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 175a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggipackage com.android.server.wm; 185a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 191b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_UNKNOWN_APP_VISIBILITY; 201b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 211b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 221b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi 235a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggiimport android.annotation.NonNull; 245a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggiimport android.util.ArrayMap; 251b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggiimport android.util.Slog; 265a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 275a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggiimport com.android.server.wm.WindowManagerService.H; 285a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 295a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggiimport java.io.PrintWriter; 305a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 315a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi/** 325a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Manages the set of {@link AppWindowToken}s for which we don't know yet whether it's visible or 335a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * not. This happens when starting an activity while the lockscreen is showing. In that case, the 345a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * keyguard flags an app might set influence it's visibility, so we wait until this is resolved to 355a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * start the transition to avoid flickers. 365a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 375a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggiclass UnknownAppVisibilityController { 385a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 391b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi private static final String TAG = TAG_WITH_CLASS_NAME ? "UnknownAppVisibility" : TAG_WM; 401b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi 415a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 425a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * We are currently waiting until the app is done resuming. 435a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 445a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private static final int UNKNOWN_STATE_WAITING_RESUME = 1; 455a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 465a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 475a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * The activity has finished resuming, and we are waiting on the next relayout. 485a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 495a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private static final int UNKNOWN_STATE_WAITING_RELAYOUT = 2; 505a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 515a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 525a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * The client called {@link Session#relayout} with the appropriate Keyguard flags and we are 535a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * waiting until activity manager has updated the visibilities of all the apps. 545a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 555a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private static final int UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE = 3; 565a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 575a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi // Set of apps for which we don't know yet whether it's visible or not, depending on what kind 585a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi // of lockscreen flags the app might set during its first relayout. 595a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private final ArrayMap<AppWindowToken, Integer> mUnknownApps = new ArrayMap<>(); 605a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 615a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private final WindowManagerService mService; 625a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 635a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi UnknownAppVisibilityController(WindowManagerService service) { 645a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mService = service; 655a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 665a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 675a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi boolean allResolved() { 685a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi return mUnknownApps.isEmpty(); 695a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 705a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 715a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi void clear() { 725a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.clear(); 735a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 745a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 755a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi String getDebugMessage() { 765a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi final StringBuilder builder = new StringBuilder(); 775a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi for (int i = mUnknownApps.size() - 1; i >= 0; i--) { 785a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi builder.append("app=").append(mUnknownApps.keyAt(i)) 795a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi .append(" state=").append(mUnknownApps.valueAt(i)); 805a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (i != 0) { 815a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi builder.append(' '); 825a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 835a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 845a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi return builder.toString(); 855a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 865a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 87df038aa8f315d8672e3e9ee482d61b58f694e147Jorim Jaggi void appRemovedOrHidden(@NonNull AppWindowToken appWindow) { 881b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi if (DEBUG_UNKNOWN_APP_VISIBILITY) { 89df038aa8f315d8672e3e9ee482d61b58f694e147Jorim Jaggi Slog.d(TAG, "App removed or hidden appWindow=" + appWindow); 901b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi } 915a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.remove(appWindow); 925a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 935a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 945a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 955a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Notifies that {@param appWindow} has been launched behind Keyguard, and we need to wait until 965a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * it is resumed and relaid out to resolve the visibility. 975a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 985a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi void notifyLaunched(@NonNull AppWindowToken appWindow) { 991b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi if (DEBUG_UNKNOWN_APP_VISIBILITY) { 1001b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi Slog.d(TAG, "App launched appWindow=" + appWindow); 1011b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi } 1025a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RESUME); 1035a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1045a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 1055a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 1065a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Notifies that {@param appWindow} has finished resuming. 1075a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 1085a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi void notifyAppResumedFinished(@NonNull AppWindowToken appWindow) { 1095a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (mUnknownApps.containsKey(appWindow) 1105a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi && mUnknownApps.get(appWindow) == UNKNOWN_STATE_WAITING_RESUME) { 1111b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi if (DEBUG_UNKNOWN_APP_VISIBILITY) { 1121b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi Slog.d(TAG, "App resume finished appWindow=" + appWindow); 1131b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi } 1145a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RELAYOUT); 1155a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1165a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1175a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 1185a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi /** 1195a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi * Notifies that {@param appWindow} has relaid out. 1205a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi */ 1215a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi void notifyRelayouted(@NonNull AppWindowToken appWindow) { 1225a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (!mUnknownApps.containsKey(appWindow)) { 1235a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi return; 1245a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1251b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi if (DEBUG_UNKNOWN_APP_VISIBILITY) { 1261b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi Slog.d(TAG, "App relayouted appWindow=" + appWindow); 1271b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi } 1285a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi int state = mUnknownApps.get(appWindow); 1295a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (state == UNKNOWN_STATE_WAITING_RELAYOUT) { 1305a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE); 1315a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mService.notifyKeyguardFlagsChanged(this::notifyVisibilitiesUpdated); 1325a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1335a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1345a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 1355a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi private void notifyVisibilitiesUpdated() { 1361b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi if (DEBUG_UNKNOWN_APP_VISIBILITY) { 1371b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi Slog.d(TAG, "Visibility updated DONE"); 1381b4b23e93e2e0d194e82ce6175526346c6a16a01Jorim Jaggi } 1395a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi boolean changed = false; 1405a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi for (int i = mUnknownApps.size() - 1; i >= 0; i--) { 1415a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (mUnknownApps.valueAt(i) == UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE) { 1425a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mUnknownApps.removeAt(i); 1435a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi changed = true; 1445a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1455a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1465a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi if (changed) { 1475a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi mService.mWindowPlacerLocked.performSurfacePlacement(); 1485a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1495a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1505a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi 1515a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi void dump(PrintWriter pw, String prefix) { 1528d78693157cb3fa7ab1c9072ef913af4d67c6314Jorim Jaggi if (mUnknownApps.isEmpty()) { 1538d78693157cb3fa7ab1c9072ef913af4d67c6314Jorim Jaggi return; 1548d78693157cb3fa7ab1c9072ef913af4d67c6314Jorim Jaggi } 1558d78693157cb3fa7ab1c9072ef913af4d67c6314Jorim Jaggi pw.println(prefix + "Unknown visibilities:"); 1565a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi for (int i = mUnknownApps.size() - 1; i >= 0; i--) { 1575a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi pw.println(prefix + " app=" + mUnknownApps.keyAt(i) 1585a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi + " state=" + mUnknownApps.valueAt(i)); 1595a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1605a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi } 1615a108c225a81cedacb1cec9b5b1986f2f3eff75cJorim Jaggi} 162