android近期任務欄圖片生成過程

我們在android手機長按HOME鍵,會彈出一個近期任務欄。近期任務欄會顯示你訪問過的app的截圖。

實現過程分爲如下幾步:

Activiyty開始pause時截圖

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        if (mPausingActivity != null) {
            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
            completePauseLocked(false);
        }
        ActivityRecord prev = mResumedActivity;
        if (prev == null) {
            if (!resuming) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
                mStackSupervisor.resumeTopActivitiesLocked();
            }
            return false;
        }

        if (mActivityContainer.mParentActivity == null) {
            // Top level stack, not a child. Look for child stacks.
            mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
        }

        if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
        else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
        mResumedActivity = null;
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
        prev.state = ActivityState.PAUSING;
        prev.task.touchActiveTime();
        clearLaunchTime(prev);
        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
            prev.updateThumbnailLocked(screenshotActivities(prev), null);
        }

代碼路徑:frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

上述代碼中有兩個主要的函數:

 1)prev.updateThumbnailLocked  用於更新Activity的縮略圖,即在近期任務欄看到的縮略圖

2)screenshotActivities  用於截圖


先分析screenshotActivities  

   public final Bitmap screenshotActivities(ActivityRecord who) {
        if (DEBUG_SCREENSHOTS) Slog.d(TAG, "screenshotActivities: " + who);
        if (who.noDisplay) {
            if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tNo display");
            return null;
        }

        if (isHomeStack()) {
            // This is an optimization -- since we never show Home or Recents within Recents itself,
            // we can just go ahead and skip taking the screenshot if this is the home stack.
            if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tHome stack");
            return null;
        }

        int w = mService.mThumbnailWidth;
        int h = mService.mThumbnailHeight;
        if (w > 0) {
            if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tTaking screenshot");
            return mWindowManager.screenshotApplications(who.appToken, Display.DEFAULT_DISPLAY,
                    w, h, SCREENSHOT_FORCE_565);
        }
        Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h);
        return null;
    }

代碼路徑:frameworks\base\services\core\java\com\android\server\am\ActivityStack.java


截圖調用的是WindowManagerService的screenShotApplications。

 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
            int height, boolean force565) {
        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
                "screenshotApplications()")) {
            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
        }

        final DisplayContent displayContent = getDisplayContentLocked(displayId);
....
  bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                        inRotation, rot);

截圖最終call到SurfaceControl.screenshot函數。


另外一個函數:

   void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
        if (newThumbnail != null) {
            if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
                    "Setting thumbnail of " + this + " to " + newThumbnail);
            boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail);
            if (thumbnailUpdated && isPersistable()) {
                mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
            }
        }
        task.lastDescription = description;
    }

代碼路徑:frameworks\base\services\core\java\com\android\server\am\ActivityRecord.java

邏輯比較簡單,不在描述。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章