102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/* 202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Copyright (C) 2016 The Android Open Source Project 302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * you may not use this file except in compliance with the License. 602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * You may obtain a copy of the License at 702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * 1002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Unless required by applicable law or agreed to in writing, software 1102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 1202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * See the License for the specific language governing permissions and 1402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * limitations under the License 1502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */ 1602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 1702886a82d876aa5e31a92444fec70208599c509cJorim Jaggipackage com.android.server.wm; 1802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 1902886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.annotation.Nullable; 20e2c77f903504766102fe545af40c3e4ebcb3adc7Jorim Jaggiimport android.app.ActivityManager.TaskSnapshot; 2102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.util.ArrayMap; 227361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggiimport android.util.LruCache; 2302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 2410abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggiimport java.io.PrintWriter; 257361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggiimport java.util.Map; 267361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggiimport java.util.Map.Entry; 2710abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 2802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/** 2902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Caches snapshots. See {@link TaskSnapshotController}. 3002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * <p> 3102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Access to this class should be guarded by the global window manager lock. 3202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */ 3302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiclass TaskSnapshotCache { 3402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 357361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi private final WindowManagerService mService; 367361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi private final TaskSnapshotLoader mLoader; 377361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi private final ArrayMap<AppWindowToken, Integer> mAppTaskMap = new ArrayMap<>(); 387361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>(); 397361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 407361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) { 417361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi mService = service; 427361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi mLoader = loader; 437361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 4402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 45e2c77f903504766102fe545af40c3e4ebcb3adc7Jorim Jaggi void putSnapshot(Task task, TaskSnapshot snapshot) { 467361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final CacheEntry entry = mRunningCache.get(task.mTaskId); 4710abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi if (entry != null) { 4810abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi mAppTaskMap.remove(entry.topApp); 4910abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 5010abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi final AppWindowToken top = task.getTopChild(); 517361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi mAppTaskMap.put(top, task.mTaskId); 527361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild())); 5302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 5402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi 557361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi /** 567361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi * If {@param restoreFromDisk} equals {@code true}, DO NOT HOLD THE WINDOW MANAGER LOCK! 577361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi */ 5835e3f53a30588b79e0309fdbeef29a8c18eef65dJorim Jaggi @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk, 5935e3f53a30588b79e0309fdbeef29a8c18eef65dJorim Jaggi boolean reducedResolution) { 607361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 617361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi synchronized (mService.mWindowMap) { 627361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi // Try the running cache. 637361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final CacheEntry entry = mRunningCache.get(taskId); 647361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi if (entry != null) { 657361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi return entry.snapshot; 667361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 677361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 687361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 697361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi // Try to restore from disk if asked. 707361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi if (!restoreFromDisk) { 717361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi return null; 727361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 7335e3f53a30588b79e0309fdbeef29a8c18eef65dJorim Jaggi return tryRestoreFromDisk(taskId, userId, reducedResolution); 7410abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 7510abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 7610abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi /** 777361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD! 7810abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi */ 7935e3f53a30588b79e0309fdbeef29a8c18eef65dJorim Jaggi private TaskSnapshot tryRestoreFromDisk(int taskId, int userId, boolean reducedResolution) { 8035e3f53a30588b79e0309fdbeef29a8c18eef65dJorim Jaggi final TaskSnapshot snapshot = mLoader.loadTask(taskId, userId, reducedResolution); 817361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi if (snapshot == null) { 827361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi return null; 8310abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 847361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi return snapshot; 8510abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 8610abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 877361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi /** 887361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi * Called when an app token has been removed 897361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi */ 907361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi void onAppRemoved(AppWindowToken wtoken) { 917361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final Integer taskId = mAppTaskMap.get(wtoken); 927361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi if (taskId != null) { 937361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi removeRunningEntry(taskId); 947361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 957361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 967361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 977361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi /** 987361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi * Callend when an app window token's process died. 997361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi */ 1007361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi void onAppDied(AppWindowToken wtoken) { 1017361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final Integer taskId = mAppTaskMap.get(wtoken); 1027361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi if (taskId != null) { 1037361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi removeRunningEntry(taskId); 1047361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 1057361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 1067361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 1077361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi void onTaskRemoved(int taskId) { 1087361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi removeRunningEntry(taskId); 1097361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi } 1107361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi 1117361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi private void removeRunningEntry(int taskId) { 1127361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final CacheEntry entry = mRunningCache.get(taskId); 11310abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi if (entry != null) { 11410abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi mAppTaskMap.remove(entry.topApp); 1157361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi mRunningCache.remove(taskId); 11610abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 11710abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 11810abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 11910abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi void dump(PrintWriter pw, String prefix) { 12010abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi final String doublePrefix = prefix + " "; 12110abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi final String triplePrefix = doublePrefix + " "; 12210abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi pw.println(prefix + "SnapshotCache"); 1237361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi for (int i = mRunningCache.size() - 1; i >= 0; i--) { 1247361babf94baa985eaa8bd2e94fcb16f00670998Jorim Jaggi final CacheEntry entry = mRunningCache.valueAt(i); 125cdef591e52e691a6f57e367caa5670fdc4ee1a8aJorim Jaggi pw.println(doublePrefix + "Entry taskId=" + mRunningCache.keyAt(i)); 126cdef591e52e691a6f57e367caa5670fdc4ee1a8aJorim Jaggi pw.println(triplePrefix + "topApp=" + entry.topApp); 127cdef591e52e691a6f57e367caa5670fdc4ee1a8aJorim Jaggi pw.println(triplePrefix + "snapshot=" + entry.snapshot); 12810abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 12910abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 13010abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 13110abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi private static final class CacheEntry { 13210abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 13310abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi /** The snapshot. */ 13410abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi final TaskSnapshot snapshot; 13510abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 13610abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi /** The app token that was on top of the task when the snapshot was taken */ 13710abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi final AppWindowToken topApp; 13810abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi 13910abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi CacheEntry(TaskSnapshot snapshot, AppWindowToken topApp) { 14010abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi this.snapshot = snapshot; 14110abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi this.topApp = topApp; 14210abe2fe297ce1ec60c15a3bd947757aee5b14b3Jorim Jaggi } 14302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi } 14402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi} 145