Stack call created by TaskView:
Free video tutorial at station b:
https://www.bilibili.com/video/BV1wj411o7A9/
TaskView creation call stack:
In fact, the call stack created here is, but the ViewPool method obviously used here is mainly to reduce frequent creation, so we simply cache it in the ViewPool and take it out when needed.
When to get it from ViewPool? The specific acquisition call chain is as follows:
07-29 17:50:08.170 1065 1065 I lsm444 : java.lang.Exception
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView.getTaskViewFromPool(RecentsView.java:2085)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView.applyLoadPlan(RecentsView.java:1443)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView$$ExternalSyntheticLambda19.accept(Unknown Source:4)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.quickstep.RecentTasksList.lambda$getTasks$3$com-android-quickstep-RecentTasksList(RecentTasksList.java:132)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.quickstep.RecentTasksList$$ExternalSyntheticLambda4.run(Unknown Source:6)
07-29 17:50:08.170 1065 1065 I lsm444 : at android.os.Handler.handleCallback(Handler.java:942)
07-29 17:50:08.170 1065 1065 I lsm444 : at android.os.Handler.dispatchMessage(Handler.java:99)
07-29 17:50:08.170 1065 1065 I lsm444 : at android.os.Looper.loopOnce(Looper.java:201)
07-29 17:50:08.170 1065 1065 I lsm444 : at android.os.Looper.loop(Looper.java:288)
07-29 17:50:08.170 1065 1065 I lsm444 : at android.app.ActivityThread.main(ActivityThread.java:7898)
07-29 17:50:08.170 1065 1065 I lsm444 : at java.lang.reflect.Method.invoke(Native Method)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
07-29 17:50:08.170 1065 1065 I lsm444 : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
It can be seen from the above that it is mainly through the RecentsView.applyLoadPlan method, which is actually called from the getTasks method.
public synchronized int getTasks(boolean loadKeysOnly,
Consumer<ArrayList<GroupTask>> callback) {
//省略
UI_HELPER_EXECUTOR.execute(() -> {
if (!mResultsBg.isValidForRequest(requestLoadId, loadKeysOnly)) {
mResultsBg = loadTasksInBackground(Integer.MAX_VALUE, requestLoadId, loadKeysOnly);
}
TaskLoadResult loadResult = mResultsBg;
mMainThreadExecutor.execute(() -> {
if (callback != null) {
ArrayList<GroupTask> result = copyOf(mResultsUi);
callback.accept(result);//这里进行的调用applyLoadPlan
}
});
});
return requestLoadId;
}
So where is the getTasks method called?
The call chain of getTask is as follows:
07-29 17:50:08.161 1065 1065 I lsm444 : getTasks
07-29 17:50:08.161 1065 1065 I lsm444 : java.lang.Exception
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.RecentTasksList.getTasks(RecentTasksList.java:119)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.RecentsModel.getTasks(RecentsModel.java:102)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView.reloadIfNeeded(RecentsView.java:2103)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView.updateTaskStackListenerState(RecentsView.java:1634)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.RecentsView.setOverviewStateEnabled(RecentsView.java:1178)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.LauncherRecentsView.setOverviewStateEnabled(LauncherRecentsView.java:133)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.LauncherRecentsView.onStateTransitionStart(LauncherRecentsView.java:100)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.quickstep.views.LauncherRecentsView.onStateTransitionStart(LauncherRecentsView.java:49)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.launcher3.statemanager.StateManager.onStateTransitionStart(StateManager.java:353)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.launcher3.statemanager.StateManager.-$$Nest$monStateTransitionStart(Unknown Source:0)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.launcher3.statemanager.StateManager$1.onAnimationStart(StateManager.java:338)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.animation.Animator$AnimatorListener.onAnimationStart(Animator.java:584)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.animation.AnimatorSet.start(AnimatorSet.java:737)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.animation.AnimatorSet.start(AnimatorSet.java:684)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.launcher3.statemanager.StateManager$StartAnimRunnable.run(StateManager.java:503)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.os.Handler.handleCallback(Handler.java:942)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.os.Handler.dispatchMessage(Handler.java:99)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.os.Looper.loopOnce(Looper.java:201)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.os.Looper.loop(Looper.java:288)
07-29 17:50:08.161 1065 1065 I lsm444 : at android.app.ActivityThread.main(ActivityThread.java:7898)
07-29 17:50:08.161 1065 1065 I lsm444 : at java.lang.reflect.Method.invoke(Native Method)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
07-29 17:50:08.161 1065 1065 I lsm444 : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
TaskInfo related data loading:
/**
* Loads and creates a list of all the recent tasks.
*/
@VisibleForTesting
TaskLoadResult loadTasksInBackground(int numTasks, int requestId, boolean loadKeysOnly) {
int currentUserId = Process.myUserHandle().getIdentifier();
//调用到sysui端的getRecentTasks
ArrayList<GroupedRecentTaskInfo> rawTasks =
mSysUiProxy.getRecentTasks(numTasks, currentUserId);
//省略
return allTasks;
}
Here, sysui's getRecentTasks will actually be called for query.
This is actually a cross-process communication:
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
private static class IRecentTasksImpl extends IRecentTasks.Stub {
//省略
@Override
public GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId)
//省略
这里核心又调用到了controller的getRecentTasks
executeRemoteCallWithTaskPermission(mController, "getRecentTasks",
(controller) -> out[0] = controller.getRecentTasks(maxNum, flags, userId)
.toArray(new GroupedRecentTaskInfo[0]),
true /* blocking */);
return out[0];
}
}
@VisibleForTesting
ArrayList<GroupedRecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) {
// Note: the returned task list is from the most-recent to least-recent order
//调用到了getRawRecentTasks方法
final List<ActivityManager.RecentTaskInfo> rawList = getRawRecentTasks(maxNum, flags,
userId);
//以下操作主要是为了分屏相关的task可以作为一个整体返回,一般把它们搞成一个gouped,有task1和task2
// Pull out the pairs as we iterate back in the list
ArrayList<GroupedRecentTaskInfo> recentTasks = new ArrayList<>();
for (int i = 0; i < rawList.size(); i++) {
final ActivityManager.RecentTaskInfo taskInfo = rawList.get(i);
if (!rawMapping.contains(taskInfo.taskId)) {
// If it's not in the mapping, then it was already paired with another task
continue;
}
final int pairedTaskId = mSplitTasks.get(taskInfo.taskId);
if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(pairedTaskId)) {
final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId);
rawMapping.remove(pairedTaskId);
recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo,
mTaskSplitBoundsMap.get(pairedTaskId)));
} else {
recentTasks.add(new GroupedRecentTaskInfo(taskInfo));
}
}
return recentTasks;
}
@VisibleForTesting
List<ActivityManager.RecentTaskInfo> getRawRecentTasks(int maxNum, int flags, int userId) {
//本质就是调用到了atms的getRecentTasks方法
return ActivityTaskManager.getInstance().getRecentTasks(maxNum, flags, userId);
}
The above acquisition of RecentTask information has been completed. To summarize:
1. The desktop calls sysui to obtain Task information, because sysui actually contains split-screen related TecentTask information.
2. sysui also calls atms to obtain RecentTask information.
Thumbnail setting analysis:
07-30 00:56:38.758 1059 1059 I lsm444 : setThumbnail task = [id=16 windowingMode=0 user=0 lastActiveTime=18031] null thumbnailData = com.android.systemui.shared.recents.model.ThumbnailData@57b6fdb
07-30 00:56:38.758 1059 1059 I lsm444 : java.lang.Exception
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.views.TaskThumbnailView.setThumbnail(TaskThumbnailView.java:150)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.views.TaskThumbnailView.setThumbnail(TaskThumbnailView.java:162)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.views.TaskView.lambda$onTaskListVisibilityChanged$5$com-android-quickstep-views-TaskView(TaskView.java:819)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.views.TaskView$$ExternalSyntheticLambda3.accept(Unknown Source:4)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.TaskThumbnailCache.lambda$updateThumbnailInBackground$1(TaskThumbnailCache.java:147)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.TaskThumbnailCache$$ExternalSyntheticLambda0.accept(Unknown Source:6)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.TaskThumbnailCache$1.handleResult(TaskThumbnailCache.java:173)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.TaskThumbnailCache$1.handleResult(TaskThumbnailCache.java:163)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.util.CancellableTask.lambda$run$0$com-android-quickstep-util-CancellableTask(CancellableTask.java:43)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.quickstep.util.CancellableTask$$ExternalSyntheticLambda0.run(Unknown Source:4)
07-30 00:56:38.758 1059 1059 I lsm444 : at android.os.Handler.handleCallback(Handler.java:942)
07-30 00:56:38.758 1059 1059 I lsm444 : at android.os.Handler.dispatchMessage(Handler.java:99)
07-30 00:56:38.758 1059 1059 I lsm444 : at android.os.Looper.loopOnce(Looper.java:201)
07-30 00:56:38.758 1059 1059 I lsm444 : at android.os.Looper.loop(Looper.java:288)
07-30 00:56:38.758 1059 1059 I lsm444 : at android.app.ActivityThread.main(ActivityThread.java:7898)
07-30 00:56:38.758 1059 1059 I lsm444 : at java.lang.reflect.Method.invoke(Native Method)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
07-30 00:56:38.758 1059 1059 I lsm444 : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Setting the relevant thumbnail is triggered by the following code:
public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) {
if (visible) {
// These calls are no-ops if the data is already loaded, try and load the high
// resolution thumbnail if the state permits
RecentsModel model = RecentsModel.INSTANCE.get(getContext());
TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
TaskIconCache iconCache = model.getIconCache();
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
//这里进行相关加载缩略图加载
mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
mTask, thumbnail -> {
//加载完成后进行回调
mSnapshotView.setThumbnail(mTask, thumbnail);
});
}
//省略
}
Next look at the updateThumbnailInBackground method:
public CancellableTask updateThumbnailInBackground(
Task task, Consumer<ThumbnailData> callback) {
Preconditions.assertUIThread();
//省略
return updateThumbnailInBackground(task.key, !mHighResLoadingState.isEnabled(), t -> {
//加在完成后的回调有
task.thumbnail = t;
callback.accept(t);
});
}
Let’s take a look at the implementation of the updateThumbnailInBackground method:
private CancellableTask updateThumbnailInBackground(TaskKey key, boolean lowResolution,
Consumer<ThumbnailData> callback) {
Preconditions.assertUIThread();
ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(key);
if (cachedThumbnail != null && cachedThumbnail.thumbnail != null
&& (!cachedThumbnail.reducedResolution || lowResolution)) {
// Already cached, lets use that thumbnail
callback.accept(cachedThumbnail);
return null;
}
CancellableTask<ThumbnailData> request = new CancellableTask<ThumbnailData>() {
@Override
public ThumbnailData getResultOnBg() {
//最终其实是通过传递taskId到ams中获取对应的缩略图
return ActivityManagerWrapper.getInstance().getTaskThumbnail(
key.id, lowResolution);
}
@Override
public void handleResult(ThumbnailData result) {
mCache.put(key, result);
callback.accept(result);
}
};
mBgExecutor.execute(request);
return request;
}