blob: 7b0d841483bb0e4f539336c44386dbf3f63de4ce [file] [log] [blame]
Jorim Jaggi02886a82016-12-06 09:10:06 -08001/*
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
19import android.annotation.Nullable;
Jorim Jaggie2c77f92016-12-29 14:57:22 +010020import android.app.ActivityManager.TaskSnapshot;
Jorim Jaggi02886a82016-12-06 09:10:06 -080021import android.util.ArrayMap;
22
Jorim Jaggi10abe2f2017-01-03 16:44:46 +010023import java.io.PrintWriter;
24
Jorim Jaggi02886a82016-12-06 09:10:06 -080025/**
26 * Caches snapshots. See {@link TaskSnapshotController}.
27 * <p>
28 * Access to this class should be guarded by the global window manager lock.
29 */
30class TaskSnapshotCache {
31
Jorim Jaggi7361bab2017-01-16 17:17:58 +010032 private final WindowManagerService mService;
33 private final TaskSnapshotLoader mLoader;
Garfield Tane8d84ab2019-10-11 09:49:40 -070034 private final ArrayMap<ActivityRecord, Integer> mAppTaskMap = new ArrayMap<>();
Jorim Jaggi7361bab2017-01-16 17:17:58 +010035 private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>();
Jorim Jaggi7361bab2017-01-16 17:17:58 +010036
37 TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) {
38 mService = service;
39 mLoader = loader;
40 }
Jorim Jaggi02886a82016-12-06 09:10:06 -080041
Jay Aliomer8b2671b2019-10-24 13:18:06 -040042 void clearRunningCache() {
43 mRunningCache.clear();
44 }
45
Jorim Jaggie2c77f92016-12-29 14:57:22 +010046 void putSnapshot(Task task, TaskSnapshot snapshot) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +010047 final CacheEntry entry = mRunningCache.get(task.mTaskId);
Jorim Jaggi10abe2f2017-01-03 16:44:46 +010048 if (entry != null) {
49 mAppTaskMap.remove(entry.topApp);
50 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -080051 final ActivityRecord top = task.getTopMostActivity();
Jorim Jaggi7361bab2017-01-16 17:17:58 +010052 mAppTaskMap.put(top, task.mTaskId);
Wale Ogunwalea38654f2019-11-17 20:37:15 -080053 mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, top));
Jorim Jaggi10abe2f2017-01-03 16:44:46 +010054 }
55
56 /**
Jorim Jaggi7361bab2017-01-16 17:17:58 +010057 * If {@param restoreFromDisk} equals {@code true}, DO NOT HOLD THE WINDOW MANAGER LOCK!
Jorim Jaggi10abe2f2017-01-03 16:44:46 +010058 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +010059 @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk,
60 boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +010061
Wale Ogunwaledb485de2018-10-29 09:47:07 -070062 synchronized (mService.mGlobalLock) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +010063 // Try the running cache.
64 final CacheEntry entry = mRunningCache.get(taskId);
65 if (entry != null) {
66 return entry.snapshot;
67 }
Jorim Jaggi7361bab2017-01-16 17:17:58 +010068 }
69
70 // Try to restore from disk if asked.
71 if (!restoreFromDisk) {
72 return null;
73 }
Jorim Jaggi35e3f532017-03-17 17:06:50 +010074 return tryRestoreFromDisk(taskId, userId, reducedResolution);
Jorim Jaggi7361bab2017-01-16 17:17:58 +010075 }
76
77 /**
78 * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD!
79 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +010080 private TaskSnapshot tryRestoreFromDisk(int taskId, int userId, boolean reducedResolution) {
81 final TaskSnapshot snapshot = mLoader.loadTask(taskId, userId, reducedResolution);
Jorim Jaggi7361bab2017-01-16 17:17:58 +010082 if (snapshot == null) {
83 return null;
84 }
Jorim Jaggi7361bab2017-01-16 17:17:58 +010085 return snapshot;
86 }
87
88 /**
89 * Called when an app token has been removed
90 */
Garfield Tane8d84ab2019-10-11 09:49:40 -070091 void onAppRemoved(ActivityRecord activity) {
92 final Integer taskId = mAppTaskMap.get(activity);
Jorim Jaggi7361bab2017-01-16 17:17:58 +010093 if (taskId != null) {
94 removeRunningEntry(taskId);
95 }
Jorim Jaggi10abe2f2017-01-03 16:44:46 +010096 }
97
Jorim Jaggi7361bab2017-01-16 17:17:58 +010098 /**
99 * Callend when an app window token's process died.
100 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700101 void onAppDied(ActivityRecord activity) {
102 final Integer taskId = mAppTaskMap.get(activity);
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100103 if (taskId != null) {
104 removeRunningEntry(taskId);
105 }
106 }
107
108 void onTaskRemoved(int taskId) {
109 removeRunningEntry(taskId);
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100110 }
111
Riddle Hsu440f88b2019-11-06 22:17:35 +0800112 void removeRunningEntry(int taskId) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100113 final CacheEntry entry = mRunningCache.get(taskId);
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100114 if (entry != null) {
115 mAppTaskMap.remove(entry.topApp);
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100116 mRunningCache.remove(taskId);
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100117 }
118 }
119
120 void dump(PrintWriter pw, String prefix) {
121 final String doublePrefix = prefix + " ";
122 final String triplePrefix = doublePrefix + " ";
123 pw.println(prefix + "SnapshotCache");
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100124 for (int i = mRunningCache.size() - 1; i >= 0; i--) {
125 final CacheEntry entry = mRunningCache.valueAt(i);
Jorim Jaggicdef5912017-04-03 17:24:19 +0200126 pw.println(doublePrefix + "Entry taskId=" + mRunningCache.keyAt(i));
127 pw.println(triplePrefix + "topApp=" + entry.topApp);
128 pw.println(triplePrefix + "snapshot=" + entry.snapshot);
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100129 }
130 }
131
132 private static final class CacheEntry {
133
134 /** The snapshot. */
135 final TaskSnapshot snapshot;
136
137 /** The app token that was on top of the task when the snapshot was taken */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700138 final ActivityRecord topApp;
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100139
Garfield Tane8d84ab2019-10-11 09:49:40 -0700140 CacheEntry(TaskSnapshot snapshot, ActivityRecord topApp) {
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100141 this.snapshot = snapshot;
142 this.topApp = topApp;
143 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800144 }
145}