3. 缩略图的获取
本章节主要讲一下缩略图的获取
3.1 获取或者更新缩略图
文件:RecentsTaskLoader.java
Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) {
SystemServicesProxy ssp = Recents.getSystemServices();
// 如果key存在,则返回缩略图的缓存
ThumbnailData thumbnailData = mThumbnailCache.getAndInvalidateIfModified(taskKey);
if (thumbnailData != null) {
return thumbnailData.thumbnail;
}
if (loadIfNotCached) {
RecentsConfiguration config = Recents.getConfiguration();
if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
// 见3.2 从系统中获取thumbnail
thumbnailData = ssp.getTaskThumbnail(taskKey.id);
if (thumbnailData.thumbnail != null) {
mThumbnailCache.put(taskKey, thumbnailData);
return thumbnailData.thumbnail;
}
}
}
// 没有装载任何缩略图
return null;
}
Task的key是有效的,那就返回缩略图的缓存,否则重新获得缩略图,并存储
3.2 从系统中获取缩略图
文件:SystemServiceProxy.java
public ThumbnailData getTaskThumbnail(int taskId) {
if (mAm == null) return null;
ThumbnailData thumbnailData = new ThumbnailData();
......
// 见3.3 获取task thumbnail
getThumbnail(taskId, thumbnailData);
if (thumbnailData.thumbnail != null) {
thumbnailData.thumbnail.setHasAlpha(false);
// We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
// left pixel, then assume the whole thumbnail is transparent. Generally, proper
// screenshots are always composed onto a bitmap that has no alpha.
if (Color.alpha(thumbnailData.thumbnail.getPixel(0, 0)) == 0) {
mBgProtectionCanvas.setBitmap(thumbnailData.thumbnail);
mBgProtectionCanvas.drawRect(0, 0, thumbnailData.thumbnail.getWidth(),
thumbnailData.thumbnail.getHeight(), mBgProtectionPaint);
mBgProtectionCanvas.setBitmap(null);
Log.e(TAG, "Invalid screenshot detected from getTaskThumbnail()");
}
}
return thumbnailData;
}
根据task id返回top task thumbnail
3.3 获取task thumbnail
文件:SystemServicesProxy.java
public void getThumbnail(int taskId, ThumbnailData thumbnailDataOut) {
if (mAm == null) {
return;
}
// 见3.4
ActivityManager.TaskThumbnail taskThumbnail = mAm.getTaskThumbnail(taskId);
if (taskThumbnail == null) {
return;
}
......
}
从Activity manager返回一个任务缩略图
3.4 getTaskThumbnail
通过binder调用,我们知道最后会调用AMS的getTaskThumbnail
文件:ActivityManagerService.java
@Override
public ActivityManager.TaskThumbnail getTaskThumbnail(int id) {
synchronized (this) {
// 首先要检查权限,必须有READ_FRAME_BUFFER权限
enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"getTaskThumbnail()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
id, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
if (tr != null) {
// 见3.5 根据ID找到栈,然后获取缩略图
return tr.getTaskThumbnailLocked();
}
}
return null;
}
3.5 根据ID找到栈,然后获取缩略图
文件:TaskRecord.java
public TaskThumbnail getTaskThumbnailLocked() {
if (stack != null) {
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity != null && resumedActivity.task == this) {
// 准备去截图
final Bitmap thumbnail = stack.screenshotActivitiesLocked(resumedActivity);
setLastThumbnailLocked(thumbnail);
}
}
final TaskThumbnail taskThumbnail = new TaskThumbnail();
// 见3.6
getLastThumbnail(taskThumbnail);
return taskThumbnail;
}
除了栈顶正在显示的TaskRecord会去实时的截取屏幕图像,其他走的是getLastThumbnail
3.6 getLastThumbnail
文件:TaskRecord.java
void getLastThumbnail(TaskThumbnail thumbs) {
thumbs.mainThumbnail = mLastThumbnail;
thumbs.thumbnailInfo = mLastThumbnailInfo;
thumbs.thumbnailFileDescriptor = null;
if (mLastThumbnail == null) {
thumbs.mainThumbnail = mService.mRecentTasks.getImageFromWriteQueue(
mLastThumbnailFile.getAbsolutePath());
}
// Only load the thumbnail file if we don't have a thumbnail
if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
try {
thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
ParcelFileDescriptor.MODE_READ_ONLY);
} catch (IOException e) {
}
}
}
这里是去读取缩略图,这些缩略图的保存位置在:/data/system_ce/0/recent_images文件夹