功能
在android设备上,
- 打开最近任务,会显示退出app时的界面
- 关机重启后马上打开最近任务,还是会显示关机前的app列表
Android为了实现上述的功能, 在每次app切换时都会对app界面进行截屏操作,截屏内容保存到内存和flash
代码分析
下面就从源码层面分析上面俩功能是如何实现的
主框架代码
TaskSnapshotController类在每次app切换时开始工作:
frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java
...
void onTransitionStarting(DisplayContent displayContent) {
handleClosingApps(displayContent.mClosingApps); // 正准备关闭的app
}
private void handleClosingApps(ArraySet<ActivityRecord> closingApps) {
if (shouldDisableSnapshots()) {
return;
}
// We need to take a snapshot of the task if and only if all activities of the task are
// either closing or hidden.
getClosingTasks(closingApps, mTmpTasks);
snapshotTasks(mTmpTasks); // 这里开始对即将退出的app界面做截屏操作
mSkipClosingAppSnapshotTasks.clear();
}
...
下面snapshotTasks函数遍历所有正要关闭的task,对每一个符合条件的task执行snapshotTask()函数得到一个snapshot对象, snapshot对象会保存到内存中和flash中:
- 内存中保存的snapshot用于最近任务里,显示出每个app的界面
- flash中的截图,用于手机重启后打开最近任务时,显示关机前的没有关闭的所有app的界面
frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java
181 private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
182 for (int i = tasks.size() - 1; i >= 0; i--) {
183 final Task task = tasks.valueAt(i);
184 final TaskSnapshot snapshot;
185 final boolean snapshotHome = allowSnapshotHome && task.isActivityTypeHome();
186 if (snapshotHome) {
187 snapshot = snapshotTask(task);
188 } else {
189 switch (getSnapshotMode(task)) {
190 case SNAPSHOT_MODE_NONE:
191 continue;
192 case SNAPSHOT_MODE_APP_THEME:
193 snapshot = drawAppThemeSnapshot(task);
194 break;
195 case SNAPSHOT_MODE_REAL:
196 snapshot = snapshotTask(task); // 得到task的截图
197 break;
198 default:
199 snapshot = null;
200 break;
201 }
202 }
203 if (snapshot != null) {
204 final GraphicBuffer buffer = snapshot.getSnapshot();
205 if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
206 buffer.destroy();
207 Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
208 + buffer.getHeight());
209 } else {
210 mCache.putSnapshot(task, snapshot); // task截图保存到缓存中
211 // Don't persist or notify the change for the temporal snapshot.
212 if (!snapshotHome) {
213 mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot); // 截图保存到flash中
214 task.onSnapshotChanged(snapshot); // 通知截图有变化
215 }
216 }
217 }
218 }
219 }
获取task截图的具体实现:
398 TaskSnapshot snapshotTask(Task task, int pixelFormat) {
399 TaskSnapshot.Builder builder = new TaskSnapshot.Builder();
400
401 if (!prepareTaskSnapsh