2、Task的獲取
本章主要承接上面的來講,解析一下Task的獲取流程
2.1 preloadTasks
文件:RecentsTaskLoader.java
public void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
boolean includeFrontMostExcludedTask) {
// 見2.2
plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
}
2.2 preloadPlan
文件:RecentsTaskLoadPlan.java
public synchronized void preloadPlan(RecentsTaskLoader loader, int runningTaskId,
boolean includeFrontMostExcludedTask) {
Resources res = mContext.getResources();
ArrayList<Task> allTasks = new ArrayList<>();
if (mRawTasks == null) {
// 見2.2.1 主要是爲了獲取mRecentTasks,並轉換成RecentTaskInfo
preloadRawTasks(includeFrontMostExcludedTask);
}
SparseArray<Task.TaskKey> affiliatedTasks = new SparseArray<>();
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
String appInfoDescFormat = mContext.getString(
R.string.accessibility_recents_item_open_app_info);
long lastStackActiveTime = Prefs.getLong(mContext,
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
if (RecentsDebugFlags.Static.EnableMockTasks) {
lastStackActiveTime = 0;
}
long newLastStackActiveTime = -1;
int taskCount = mRawTasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
// Compose the task key
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
t.userId, t.firstActiveTime, t.lastActiveTime);
// This task is only shown in the stack if it statisfies the historical time or min
// number of tasks constraints. Freeform tasks are also always shown.
boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
boolean isStackTask = isFreeformTask || !isHistoricalTask(t) ||
(t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS));
boolean isLaunchTarget = taskKey.id == runningTaskId;
// The last stack active time is the baseline for which we show visible tasks. Since
// the system will store all the tasks, we don't want to show the tasks prior to the
// last visible ones, otherwise, as you dismiss them, the previous tasks may satisfy
// the other stack-task constraints.
if (isStackTask && newLastStackActiveTime < 0) {
newLastStackActiveTime = t.lastActiveTime;
}
// 加載標題,圖標和顏色
ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
String titleDescription = loader.getAndUpdateContentDescription(taskKey, res);
String dismissDescription = String.format(dismissDescFormat, titleDescription);
String appInfoDescription = String.format(appInfoDescFormat, titleDescription);
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
// 見3 縮略圖的獲取
Bitmap thumbnail = loader.getAndUpdateThumbnail(taskKey, false /* loadIfNotCached */);
int activityColor = loader.getActivityPrimaryColor(t.taskDescription);
int backgroundColor = loader.getActivityBackgroundColor(t.taskDescription);
boolean isSystemApp = (info != null) &&
((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
// 將任務添加到棧
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
t.isDockable, t.bounds, t.taskDescription, t.resizeMode, t.topActivity);
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
affiliatedTasks.put(taskKey.id, taskKey);
}
if (newLastStackActiveTime != -1) {
Prefs.putLong(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
newLastStackActiveTime);
}
// Initialize the stacks
mStack = new TaskStack();
mStack.setTasks(mContext, allTasks, false /* notifyStackChanges */);
}
2.2.1 獲取mRecentTasks
文件:RecentsTaskLoadPlan.java
public synchronized void preloadRawTasks(boolean includeFrontMostExcludedTask) {
int currentUserId = UserHandle.USER_CURRENT;
updateCurrentQuietProfilesCache(currentUserId);
SystemServicesProxy ssp = Recents.getSystemServices();
// 見2.3
mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
// 按照most-recent to least-recent的順序進行排序
Collections.reverse(mRawTasks);
}
2.3 getRecentTasks
文件:SystemServicesProxy.java
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
boolean includeFrontMostExcludedTask, ArraySet<Integer> quietProfileIds) {
if (mAm == null) return null;
......
// 移除掉 home/recents/excluded 這三種tasks
int minNumTasksToQuery = 10;
int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
int flags = ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK |
ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
ActivityManager.RECENT_INCLUDE_PROFILES;
if (includeFrontMostExcludedTask) {
flags |= ActivityManager.RECENT_WITH_EXCLUDED;
}
List<ActivityManager.RecentTaskInfo> tasks = null;
try {
// 見2.4 得到RecentTaskInfo
tasks = mAm.getRecentTasksForUser(numTasksToQuery, flags, userId);
} catch (Exception e) {
Log.e(TAG, "Failed to get recent tasks", e);
}
// 如果沒有獲得可用的tasks,那就提前退出
if (tasks == null) {
return new ArrayList<>();
}
boolean isFirstValidTask = true;
Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
while (iter.hasNext()) {
ActivityManager.RecentTaskInfo t = iter.next();
// NOTE: The order of these checks happens in the expected order of the traversal of the
// tasks
// Remove the task if it or it's package are blacklsited
if (sRecentsBlacklist.contains(t.realActivity.getClassName()) ||
sRecentsBlacklist.contains(t.realActivity.getPackageName())) {
iter.remove();
continue;
}
// Remove the task if it is marked as excluded, unless it is the first most task and we
// are requested to include it
boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
== Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
isExcluded |= quietProfileIds.contains(t.userId);
// 顯示每一個任務信息的LOG***
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
t.userId, t.firstActiveTime, t.lastActiveTime);
Log.d(TAG, "getRecentTasks:TASK = " + taskKey.toString()
+ "/isExcluded = " + isExcluded
+ "/includeFrontMostExcludedTask = " + includeFrontMostExcludedTask
+ "/isFirstValidTask = " + isFirstValidTask
+ "/t.id = " + t.id);
if (isExcluded && (!isFirstValidTask || !includeFrontMostExcludedTask)) {
iter.remove();
}
isFirstValidTask = false;
}
return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
}
這個方法的作用是返回一個最近任務的list
2.4 得到RecentTaskInfo
通過binder調用,可以得知最後調用的是AMS的getRecentTasks
文件:ActivityManagerService.java
@Override
public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
int userId) {
......
// 見2.4.1 根據userId來獲取mRecentTasks
mRecentTasks.loadUserRecentsLocked(userId);
......
for (int i = 0; i < recentsCount && maxNum > 0; i++) {
TaskRecord tr = mRecentTasks.get(i);
// Only add calling user or related users recent tasks
if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
continue;
}
if (tr.realActivitySuspended) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
continue;
}
if (i == 0
|| withExcluded
|| (tr.intent == null)
|| ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
== 0)) {
...... // 根據之前設置的flag去排除掉不需要的task
// 見2.4.2 調用createRecentTaskInfoFromTaskRecord()方法把mRecentTasks裏的TaskRecord轉換成RecentTaskInfo
ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
if (!detailed) {
rti.baseIntent.replaceExtras((Bundle)null);
}
res.add(rti);
maxNum--;
}
}
return new ParceledListSlice<>(res);
}
}
2.4.1 根據userId來獲取mRecentTasks
文件:RecentTasks.java
void loadUserRecentsLocked(int userId) {
// 如果沒有存儲則進來,如果存儲了就不做任何事情
if (!mUsersWithRecentsLoaded.get(userId)) {
// 如果沒有導入則導入
loadPersistedTaskIdsForUserLocked(userId);
Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
// 通過restoreTasksForUserLocked獲取TaskRecord
addAll(mTaskPersister.restoreTasksForUserLocked(userId));
cleanupLocked(userId);
mUsersWithRecentsLoaded.put(userId, true);
}
}
其中restoreTasksForUserLocked主要是去解析xml文件,位於/data/system_ce/0/recent_tasks目錄下,可以看到這些task信息是以文件形式保存的,這就是重啓後進RecentsActivity看到task還在的原因。解析完這些xml文件就獲取到了初始的task信息。但實際上loadUserRecentsLocked裏面的語句是只會在開機初始化時執行一次
2.4.2 把mRecentTasks裏的TaskRecord轉換成RecentTaskInfo
文件:ActivityManagerService.java
private ActivityManager.RecentTaskInfo createRecentTaskInfoFromTaskRecord(TaskRecord tr) {
// Update the task description to reflect any changes in the task stack
tr.updateTaskDescription();
// Compose the recent task info
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
rti.persistentId = tr.taskId;
rti.baseIntent = new Intent(tr.getBaseIntent());
rti.origActivity = tr.origActivity;
rti.realActivity = tr.realActivity;
rti.description = tr.lastDescription;
rti.stackId = tr.stack != null ? tr.stack.mStackId : -1;
rti.userId = tr.userId;
rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
rti.firstActiveTime = tr.firstActiveTime;
rti.lastActiveTime = tr.lastActiveTime;
rti.affiliatedTaskId = tr.mAffiliatedTaskId;
rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
rti.numActivities = 0;
if (tr.mBounds != null) {
rti.bounds = new Rect(tr.mBounds);
}
rti.isDockable = tr.canGoInDockedStack();
rti.resizeMode = tr.mResizeMode;
ActivityRecord base = null;
ActivityRecord top = null;
ActivityRecord tmp;
for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
tmp = tr.mActivities.get(i);
if (tmp.finishing) {
continue;
}
base = tmp;
if (top == null || (top.state == ActivityState.INITIALIZING)) {
top = base;
}
rti.numActivities++;
}
rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
rti.topActivity = (top != null) ? top.intent.getComponent() : null;
return rti;
}
Task的獲取就講到這裏,接下來講講縮略圖的獲取