有Keyguard狀態下啓動應用會走兩邊生命週期分析

第一次啓動
07-31 14:58:26.179  2097  8344 I am_set_resumed_activity: [0,com.tencent.mobileqq/.activity.QQLSActivity,minimalResumeActivityLocked]
07-31 14:58:26.181  2097  8344 I am_pause_activity: [0,114682695,com.tencent.mobileqq/.activity.QQLSActivity,userLeaving=false]
07-31 14:58:26.186  2097  2114 I am_stop_activity: [0,250649096,com.tencent.mobileqq/.activity.SplashActivity]
07-31 14:58:26.274 17932 17932 I am_on_create_called: [0,com.tencent.mobileqq.activity.QQLSActivity,performCreate]
07-31 14:58:26.279 17932 17932 I am_on_start_called: [0,com.tencent.mobileqq.activity.QQLSActivity,handleStartActivity]
07-31 14:58:26.280 17932 17932 I am_on_resume_called: [0,com.tencent.mobileqq.activity.QQLSActivity,RESUME_ACTIVITY]
07-31 14:58:26.298 17932 17932 I am_on_paused_called: [0,com.tencent.mobileqq.activity.QQLSActivity,performPause]
....
第二次重新resume
07-31 14:58:26.307  2097  2114 I am_stop_activity: [0,114682695,com.tencent.mobileqq/.activity.QQLSActivity]
07-31 14:58:26.314  2097  2129 I am_set_resumed_activity: [0,com.tencent.mobileqq/.activity.QQLSActivity,resumeTopActivityInnerLocked]
07-31 14:58:26.322  2097  2129 I am_resume_activity: [0,114682695,62,com.tencent.mobileqq/.activity.QQLSActivity]
07-31 14:58:26.345 17932 17932 I am_on_stop_called: [0,com.tencent.mobileqq.activity.SplashActivity,STOP_ACTIVITY_ITEM]
07-31 14:58:26.409 17932 17932 I am_on_resume_called: [0,com.tencent.mobileqq.activity.QQLSActivity,RESUME_ACTIVITY]

07-31 14:58:26.179  2097  8344 I am_set_resumed_activity: [0,com.tencent.mobileqq/.activity.QQLSActivity,minimalResumeActivityLocked]

相關的堆棧流程

at com.android.server.am.ActivityRecord.completeResumeLocked(ActivityRecord.java:1905)
at com.android.server.am.ActivityStack.minimalResumeActivityLocked(ActivityStack.java:1319)
at com.android.server.am.ActivityStackSupervisor.realStartActivityLocked(ActivityStackSupervisor.java:1651)
at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1746)
at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2886)
at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2386)
at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2275)
at com.android.server.am.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1555)
at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:1270)
at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:923)
at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:558)
at com.android.server.am.ActivityStarter.startActivityMayWait(ActivityStarter.java:1154)
at com.android.server.am.ActivityStarter.execute(ActivityStarter.java:500)
at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:5651)
at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:5619)
at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:5610)
at android.app.IActivityManager$Stub.onTransact$startActivity$(IActivityManager.java:10231)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:122)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3599)

在frameworks/base/services/core/java/com/android/server/am/ActivityStack.java中

void minimalResumeActivityLocked(ActivityRecord r) {
...
      r.setState(RESUMED, "minimalResumeActivityLocked");
      r.completeResumeLocked();
      mStackSupervisor.getLaunchTimeTracker().setLaunchTime(r);
...
}

////////
frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java

void completeResumeLocked() {
.....
//恢復key分發
         resumeKeyDispatchingLocked();
....
//此時canTurnScreenOn爲false,所以會走checkReadyForSleep這個方法
        if (canTurnScreenOn()) {
            mStackSupervisor.wakeUp("turnScreenOnFlag");
        } else {
            // If the screen is going to turn on because the caller explicitly requested it and
            // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
            // pause and then resume again later, which will result in a double life-cycle event.
            stack.checkReadyForSleep();
        }
....

}
///////////////////
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
.....
    void checkReadyForSleep() {
        if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) {
            mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
        }
    }

//其中對應三個判斷變量
    boolean shouldSleepActivities() {
        final ActivityDisplay display = getDisplay();

        // Do not sleep activities in this stack if we're marked as focused and the keyguard
        // is in the process of going away.
        if (mStackSupervisor.getFocusedStack() == this
                && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
            return false;
        }
////當前display & AMS 都處於sleep狀態,所以這個方法return true
        return display != null ? display.isSleeping() : mService.isSleepingLocked();
    }
////
    /**
     * Tries to put the activities in the stack to sleep.
     *
     * If the stack is not in a state where its activities can be put to sleep, this function will
     * start any necessary actions to move the stack into such a state. It is expected that this
     * function get called again when those actions complete.
     *
     * @param shuttingDown true when the called because the device is shutting down.
     * @return true if the stack finished going to sleep, false if the stack only started the
     * process of going to sleep (checkReadyForSleep will be called when that process finishes).
     */
    boolean goToSleepIfPossible(boolean shuttingDown) {
....
        boolean shouldSleep = true;
        //如果當前有resume的Activity的界面則開始Pausing
        if (mResumedActivity != null) {
            // Still have something resumed; can't sleep until it is paused.
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "Sleep => pause with userLeaving=false");

            startPausingLocked(false, true, null, false);
            shouldSleep = false ;
        ///如果Activity已是Pausing則繼續sleep 
        } else if (mPausingActivity != null) {
            // Still waiting for something to pause; can't sleep yet.
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
            shouldSleep = false;
        }
        //按照流程傳遞進來的是false,所以會進入
        if (!shuttingDown) {
            if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) {
                // Still need to tell some activities to stop; can't sleep yet.
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop "
                        + mStackSupervisor.mStoppingActivities.size() + " activities");
                //檢測Message隊列中是否已經爲Idle ,如是則執行onStop操作
                mStackSupervisor.scheduleIdleLocked();
                shouldSleep = false;
            }

            if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) {
                // Still need to tell some activities to sleep; can't sleep yet.
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep "
                        + mStackSupervisor.mGoingToSleepActivities.size() + " activities");
                shouldSleep = false;
            }
        }

        if (shouldSleep) {
            goToSleep();
        }

        return shouldSleep;
    }
    }

如上第一次resume後馬上pause的原因是display.isSleeping() 和mService.isSleepingLocked()兩者都是true

後面再看一下從pause再resume的流程

當第一次的activity pause完成後,會觸發下次resumeFocusedStackTopActivityLocked
06-14 08:38:42.699 1087 7264 D ActivityManager: java.lang.Throwable
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2429)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2386)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2275)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1688)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1606)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:8906)
06-14 08:38:42.699 1087 7264 D ActivityManager: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:224)
06-14 08:38:42.699 1087 7264 D ActivityManager: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3599)
06-14 08:38:42.699 1087 7264 D ActivityManager: at android.os.Binder.execTransact(Binder.java:731)
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

activityPausedLocked的調用在如下幾個地方:

{moveToFrontAndResumeStateIfNeeded,startPausingLocked}--->
schedulePauseTimeout->H.PAUSE_TIMEOUT_MSG--->completePauseLocked

awakeFromSleepingLocked--->completePauseLocked


private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
....

        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            //第二次shouldSleepOrShutDownActivities爲false,進入到裏面執行
            if (!topStack.shouldSleepOrShutDownActivities()) {
                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
            } else {
                checkReadyForSleep();
                ActivityRecord top = topStack.topRunningActivityLocked();
                if (top == null || (prev != null && top != prev)) {
                    // If there are no more activities available to run, do resume anyway to start
                    // something. Also if the top activity on the stack is not the just paused
                    // activity, we need to go ahead and resume it to ensure we complete an
                    // in-flight app switch.
                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
                }
            }
        }
.....
}

////topStack.shouldSleepOrShutDownActivities()這個方法中跟上面有些類似,此時shouldSleepActivities爲false,所以可以成功resume起來
     boolean shouldSleepOrShutDownActivities() {
          return shouldSleepActivities() || mService.isShuttingDownLocked();
      }

////////////////////////
    boolean shouldSleepActivities() {
        final ActivityDisplay display = getDisplay();

        // Do not sleep activities in this stack if we're marked as focused and the keyguard
        // is in the process of going away.
        if (mStackSupervisor.getFocusedStack() == this
                && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
            return false;
        }

        return display != null ? display.isSleeping() : mService.isSleepingLocked();
    }

再看一下display.isSleeping() 和mService.isSleepingLocked() 這兩個狀態的獲取流程

frameworks/base/services/core/java/com/android/server/am/ActivityDisplay.java
  /**
86      * All of the stacks on this display. Order matters, topmost stack is in front of all other
87      * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
88      * changing the list should also call {@link #onStackOrderChanged()}.
89      */
90     private final ArrayList<ActivityStack> mStacks = new ArrayList<>();

     /** All tokens used to put activities on this stack to sleep (including mOffToken) */
97     final ArrayList<ActivityManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
........

    boolean isSleeping() {
803         return mSleeping;
804     }
805 
806     void setIsSleeping(boolean asleep) {
807         mSleeping = asleep;
808     }

   boolean shouldSleep() {
737         return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
738                 && (mSupervisor.mService.mRunningVoice == null);
739     }

////////
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
goingToSleepLocked---> applySleepTokensLocked(false /* applyToStacks */)-->


    void applySleepTokensLocked(boolean applyToStacks) {
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            // Set the sleeping state of the display.
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            // 獲取是否可以sleep狀態,包含mStacks是否爲空或者mAllSleepTokens不爲空
            final boolean displayShouldSleep = display.shouldSleep();
            if (displayShouldSleep == display.isSleeping()) {
                continue;
            }
            //設置是否睡眠狀態
            display.setIsSleeping(displayShouldSleep);

            if (!applyToStacks) {
                continue;
            }

......
    }
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

    SleepToken createSleepTokenLocked(String tag, int displayId) {
        ActivityDisplay display = mActivityDisplays.get(displayId);
        if (display == null) {
            throw new IllegalArgumentException("Invalid display: " + displayId);
        }

        final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
        mSleepTokens.add(token);
        //將token添加到mAllSleepTokens這個列表中
        display.mAllSleepTokens.add(token);
        return token;
    }

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

     SleepToken acquireSleepToken(String tag, int displayId) {
        synchronized (this) {
            final SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId);
            updateSleepIfNeededLocked();
            return token;
        }
    }
///////////
    @VisibleForTesting
    final class LocalService extends ActivityManagerInternal {
.....
        @Override
        public SleepToken acquireSleepToken(String tag, int displayId) {
            Preconditions.checkNotNull(tag);
            return ActivityManagerService.this.acquireSleepToken(tag, displayId);
        }

.....
     }

//其他地方通過類似這種方式調用
setKeyguardShown---->updateKeyguardSleepToken
keyguardGoingAway--->updateKeyguardSleepToken
handleOccludedChanged--->updateKeyguardSleepToken

frameworks/base/services/core/java/com/android/server/am/KeyguardController.java
    private void updateKeyguardSleepToken() {
        ///當Keyguard或者AOD顯示的時候申請SleepToken,反之則釋放
        if (mSleepToken == null && isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
            mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
        } else if (mSleepToken != null && !isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
            mSleepToken.release();
            mSleepToken = null;
        }
    }
////
    /**
     * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
     *         on the given display, false otherwise
     */
    ///displayId默認就爲DEFAULT_DISPLAY,所以需要mOccluded設爲false,isKeyguardOrAodShowing纔有可能返回true
    boolean isKeyguardOrAodShowing(int displayId) {
        return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway &&
                (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
    }

 

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