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