• Activity管理笔记


    文章仅记录自己学习该模块时的一点理解,看到哪写到哪。所以特别散。


    AMS管理四大组件外加进程管理,当中最庞大的算是Activity了吧。

    1、AMS中对ActivityStack划分为两类。当中一类是FrontStack,还有一类刚好相反。

      boolean isFrontStack(ActivityStack stack) {
            return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
        }


       ActivityStack getFocusedStack() {
            if (mFocusedStack == null) {
                return mHomeStack;
            }
            switch (mStackState) {
                case STACK_STATE_HOME_IN_FRONT:
                case STACK_STATE_HOME_TO_FRONT:
                    return mHomeStack;
                case STACK_STATE_HOME_IN_BACK:
                case STACK_STATE_HOME_TO_BACK:
                default:
                    return mFocusedStack;
            }
        }

    从上面的代码能够得出下面结论:

    A )、对于4.4眼下仅仅有两个ActivityStack的逻辑非常清晰:HomeStack、AStack

    a、假设getFocusedStack()==HomeStack,那么HomeStack就是FrontStack。还有一个就是非FrontStack。

    b、假设getFocusedStack()==    AStack,那么HomeStack就是非FrontStack。还有一个就是FrontStack。 

    B )、假设做成**至少有三个ActivityStack:HomeStack、AStack、BStack

    a、假设getFocusedStack()==HomeStack,那么HomeStack就是FrontStack,AStack、BStack就是非FrontStack。

    b、假设getFocusedStack()==       AStack,那么HomeStack就是非FrontStack,AStack、BStack就是FrontStack。

    c、假设getFocusedStack()==       BStack。那么HomeStack就是非FrontStack,AStack、BStack就是FrontStack。

    依照现有的逻辑来说,HomeStack跟其它全部ActivityStack是全然相反的。其它全部ActivityStack要么都是FrontStack,要么都是非FrontStack。那它这个isFrontStack分类有啥用?出于什么目的而设计的?

    2、AMS中对Activity的管理是通过任务栈的形式来管理的。也就是利用TaskRecord代表Task,系统中有非常多Task。所以就出现了Task栈——ActivityStack,按理说仅仅要一个ActivityStack就OK了。可是Android4.4有两个ActivityStack,而且还能够有多个。这个确实是为**设计的。

    问题一:ActivityStackSupervisor是怎样管理ActivityStack的呢?

    问题二:ActivityStack是怎样管理TaskRecord的呢?

    问题三:TaskRecord怎样管理ActivityRecord的呢?

    这三个问题以下一一来研究。

    问题一:ActivityStackSupervisor是怎样管理ActivityStack的呢?

    ActivityStackSupervisor是一个管理ActivityStack类,里面的函数应该能够给出上面的答案。相关函数主要有adjustStackFocus()、getFocusedStack()、setFocusedStack()等,这几个函数比較有意思,以下来研究下。可是首先必需要搞清楚mFocusedStack是个什么东西。不然代码没法看。google源代码是这样解释的这个变量的:

      /** The non-home stack currently receiving input or launching the next activity. If home is
         * in front then mHomeStack overrides mFocusedStack.
         * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
    上面的解释说了跟没说一样。

    事实上这个变量应该这么理解:google把ActivityStack分为两类。一类是包括Launcher和后台界面ActivityRecord的mHomeStack,还有一类是包括普通应用ActivityRecord的“普通ActivityStack”,mFocusedStack就是全部“普通ActivityStack”中的“焦点ActivityStack”,所谓“焦点ActivityStack”就是接受输入事件和启动下一个Activity,仅仅要存在“普通ActivityStack”,那么mFocusedStack就不为null。可是“终极焦点ActivityStack”是在mHomeStack和全部“普通ActivityStack”中的“焦点ActivityStack”——mFocusedStack”中进行对决产生的。对决函数就是getFocusedStack(),对决策略就是推断mStackState状态值来选择mHomeStack或是mFocusedStack。

    注意,假设系统中没有启动过普通应用Activity,或是普通应用Activity都被移除了(“普通ActivityStack”中的Task被全部移除掉时会自己主动销毁掉这个“普通ActivityStack”,所以就会出现不存在“普通ActivityStack”),那么就不存在“普通ActivityStack”,也就是mFocusedStack为null。此时etFocusedStack()自然直接返回mHomeStack。

    可能是Launcher是个比較特殊的Activity。mHomeStack跟跟“普通ActivityStack”差别非常大。假设不加区分地进行统一设计。那么可能代码更加复杂。

    理解了mFocusedStack,再来研究上面几个函数。so easy!!!

    Ⅰ、先看adjustStackFocus()

       ActivityStack adjustStackFocus(ActivityRecord r)  {
            final TaskRecord task = r.task;
            if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
                if (task != null) {
                    final ActivityStack taskStack = task.stack;
                    if (mFocusedStack != taskStack) {
                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                                "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
                        mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
                    } else {
                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                            "adjustStackFocus: Focused stack already=" + mFocusedStack);
                    }
                    return taskStack;
                }
    
                if (mFocusedStack != null) {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                            "adjustStackFocus: Have a focused stack=" + mFocusedStack);
                    return mFocusedStack;
                }
    
                for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
                    ActivityStack stack = mStacks.get(stackNdx);
                    if (!stack.isHomeStack()) {
                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                                "adjustStackFocus: Setting focused stack=" + stack);
                        mFocusedStack = stack;
                        return mFocusedStack;
                    }
                }
    
                // Time to create the first app stack for this user.
                int stackId =
                        mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
                        " stackId=" + stackId);
                mFocusedStack = getStack(stackId);
                return mFocusedStack;
            }
            return mHomeStack;
        }
    

    adjustStackFocus()函数在startActivityUncheckedLocked()中调用,也就是说当起来一个Activity时,adjustStackFocus()函数修正Activity导致对mFocusedStack的影响。adjustStackFocus(r)函数的功能是依据參数r来调整mFocusedStack值。调整完mFocusedStack值,然后紧接着调用moveHomeStack()来修正mHomeStack的状态。详细调整规则是:

    ①假设启动的Activity是HOME_ACTIVITY_TYPE和RECENTS_ACTIVITY_TYPE类型,那么直接返回mHomeStack。然后利用moveHomeStack()将mHomeStack设为前台Stack。

    ②假设启动的Activity是APPLICATION_ACTIVITY_TYPE类型,那么又细分三种情况:A、假设不存在“普通ActivityStack”,那么直接调用AMS.createStack()创建一个“普通ActivityStack”;B、假设存在“普通ActivityStack”。那么直接返回mFocusedStack;C、假设r指定了某个“普通ActivityStack”,那么返回指定的ActivityStack,并把mFocusedStack设为指定的ActivityStack;

    Ⅱ、setFocusedStack()

        void setFocusedStack(ActivityRecord r)  {
            if (r == null) {
                return;
            }
            if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {  //①这个条件是针对Launcher和后台Activity的,所以仅仅要把mStackState设为STACK_STATE_HOME_TO_FRONT。对决函数getFocusedStack()返回的便是mHomeStack。
    
                if (mStackState != STACK_STATE_HOME_IN_FRONT) {
                    if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
                            stackStateToString(mStackState) + " new=" +
                            stackStateToString(STACK_STATE_HOME_TO_FRONT) +
                            " Callers=" + Debug.getCallers(3));
                    mStackState = STACK_STATE_HOME_TO_FRONT;
                }
            } else {                                                                     //②非Launcher和非后台Activity,走的便是这个逻辑。

    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task + " Callers=" + Debug.getCallers(3)); final ActivityStack taskStack = r.task.stack; mFocusedStack = taskStack.isHomeStack() ? null : taskStack; //③这行代码事实上仅仅要写成mFocusedStack =taskStack便可,由于taskStack不可能为mHomeStack的,这个是在②中限制住的。将mStackState = STACK_STATE_HOME_TO_BACK,那么对决函数getFocusedStack()返回的便是mFocusedStack 。 if (mStackState != STACK_STATE_HOME_IN_BACK) { if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" + stackStateToString(mStackState) + " new=" + stackStateToString(STACK_STATE_HOME_TO_BACK) + " Callers=" + Debug.getCallers(3)); mStackState = STACK_STATE_HOME_TO_BACK; } } }

    setFocusedStack()函数就是设置mStackState 的状态值来间接影响getFocusedStack()的返回值。

    总结:研究这两个函数,能够看出AMS对ActivityTask的管理是分为两种类型来管理的。

    问题二:ActivityStack是怎样管理TaskRecord的呢?

    TaskRecord代表一个Task。假设新启动的Activity执行在新的Task中,那么就须要创建一个TaskRecord,在哪些情况下Activity须要执行在新的Task中呢?回答这个问题须要细致研究startActivity()流程。以下来细致研究下Activity启动流程。

    startActivity()

    不论什么Activity的启动都会调用startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options)。

    解释下几个重要的參数。caller就是start该Activity的进程,resultTo是要将startActivity的结果返回给哪个Activity,比方startActivityForResult()。至于resultTo到底是个什么类型的Binder对象呢?这个跟踪下源代码就知道了。给出详细调用流程:startActivity()-->startActivityAsUser()-->startActivityMayWait()-->startActivityLocked()-->new ActivityRecord();new Token();-->startActivityUncheckedLocked()-->ActivityStack.startActivityLocked()-->ActivityStackSupervisor.resumeTopActivitiesLocked()-->ActivityStack.resumeTopActivityLocked()-->ActivityStackSupervisor.startSpecificActivityLocked()-->realStartActivityLocked()-->ActivityThread.scheduleLaunchActivity()-->r.token = token;从这个流程中能够知道Activity.mToken保存的是AMS側相应的ActivityRecord.appToken的Binder代理对象。

    随便看:

    Ⅰ、ActivityRecord.startLaunchTickingLocked(),记录Activity的启动时间点。同一时候会调用continueLaunchTickingLocked()来post一个延迟ActivityStack.LAUNCH_TICK毫秒的LAUNCH_TICK_MSG消息。Activity在LAUNCH_TICK时间内起来了必定调用会调用finishLaunchTickingLocked()来清除launchTickTime变量值,并打印一条日志;假设Activity起来的慢,那么post的延迟消息必定先运行,这个消息又运行continueLaunchTickingLocked()函数,如此循环直到Activity起来为止。这个机制就是定时打日志记录Activity的启动快慢用的。

    Ⅱ、Activity.mPausingActivity。在startPausingLocked()时会将要paused的ActivityRecord保存在mPausingActivity中,当pause成功后会调用activityPausedLocked()函数做兴许处理。在这个函数中会将mPausingActivity重置为null。这个过程与Google对这个变量的描写叙述一致:“ When we are in the process of pausing an activity, before starting the next one, this variable holds the activity that is currently being paused.”。

    Ⅲ、startPausingLocked()这个函数有非常多非常重要的学习点。重点研究下。

     final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
            if (mPausingActivity != null) {              //①假设要pause一个Activity时。已经有一个Activity在pause还未完毕(pause完毕的话mPausingActivity 为null),那么抛出一个异常。
                Slog.e(TAG, "Trying to pause when pause is already pending for "
                      + mPausingActivity, new RuntimeException("here").fillInStackTrace());
            }
            ActivityRecord prev = mResumedActivity;        //②mResumedActivity中保存的是当前resume的Activity。pause的对象肯定是当前的resume的Activity,假设当前没有resume对象,这样的情况也就是系统启动第一个Activity才有的情况,此时就直接resume Activity栈中的顶层Activity。
    
            if (prev == null) {
                Slog.e(TAG, "Trying to pause when nothing is resumed",
                        new RuntimeException("here").fillInStackTrace());
                mStackSupervisor.resumeTopActivitiesLocked();
                return;
            }
            if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
            else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
            mResumedActivity = null;   //③当前resume的Activity要被pause掉了,那么mResumedActivity必定要重置为null了。同一时候mPausingActivity指向当前resumed的Activity。

    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; //④要pause的ActivityRecord.state状态设置为PAUSING prev.task.touchActiveTime(); clearLaunchTime(prev); final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); //⑤取出要Start的ActivityRecord。 stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); if (prev.app != null && prev.app.thread != null) { if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev); try { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, prev.userId, System.identityHashCode(prev), prev.shortComponentName); mService.updateUsageStats(prev, false); prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags); //⑥回调上层应用ActivityThread的schedulePauseActivity()函数,做一些应用层的处理工作。 } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } } else { mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } // If we are not going to sleep, we want to ensure the device is // awake until the next activity is started. if (!mService.isSleepingOrShuttingDown()) { mStackSupervisor.acquireLaunchWakelock(); //⑦获取一个唤醒锁。防止系统睡眠。获取唤醒锁时要注意释放,看解释知道在Activity全然起来后必定会释放这个锁,可是假设出现异常呢?Google代码写的非常健壮。在获取一个唤醒锁时。同一时候也会post一个超时消息。假设超时了还没释放这个锁。那么就在这个超时消息处理中释放唤醒锁。

    } if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt // key dispatch; the same activity will pick it up again on wakeup. if (!uiSleeping) { prev.pauseKeyDispatchingLocked(); //⑧pause一个Activity时,须要关闭这个Activity的输入事件通道,关闭一个输入通道仅仅需将与该Activity相应的WindowToken.paused设为true,然后调用updateInputWindowsLw(true)将窗体状态更新到InputDispatcher中,InputDispatcher分发消息时是不会分发给paused状态窗体的,以此达到关闭输入通道效果。 } else { if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off"); } // Schedule a pause timeout in case the app doesn't respond. // We don't give it much time because this directly impacts the // responsiveness seen by the user. Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); //⑨post一个PAUSE_TIMEOUT_MSG消息,为什么要post这么个消息。是由于假设无法完毕paused前一个Activity,那么就无法start下一个Activity,这个超时消息是防止异常导致无法及时start下一个Activity,在超时消息处理函数中肯定有start next Activity的逻辑。 msg.obj = prev; prev.pauseTime = SystemClock.uptimeMillis(); mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete..."); } else { // This activity failed to schedule the // pause, so just treat it as being paused now. if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next."); mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null); } }

    从上面这个函数中能够看到要写一个健壮的代码须要考虑异常导致无法完毕下一步工作。此时能够利用超时机制来启动下一步工作。

    Ⅳ、stopActivityLocked()函数。

        final void stopActivityLocked(ActivityRecord r) {
            if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
            if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                    || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {  //①仅仅要设置了FLAG_ACTIVITY_NO_HISTORY和FLAG_NO_HISTORY属性,当stop一个Activity时。直接finish掉该Activity。
                if (!r.finishing) {           //②Activity.finishing表示这个Activity正在finish
                    if (!mService.mSleeping) {
                        if (DEBUG_STATES) {
                            Slog.d(TAG, "no-history finish of " + r);
                        }
                        requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                                "no-history", false);
                    } else {
                        if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
                                + " on stop because we're just sleeping");
                    }
                }
            }
    
            if (r.app != null && r.app.thread != null) {
                adjustFocusedActivityLocked(r);    //③调整AMS.mFocusedActivity值,看源代码在启动一个Activity调用startActivityUncheckedLocked()时便调用 mService.setFocusedActivityLocked(r)重置了mFocusedActivity值。

    r.resumeKeyDispatchingLocked(); //④要stop一个Activity了为什么要打开这个Activity的输入通道??打开输入通道仅仅有在完毕pause Activity(completePauseLocked())和完毕 resume Activity(completeResumeLocked())时才调用嘛。为啥要准备stop一个Activity时也要打开输入通道?? try { r.stopped = false; //⑤设置ActivityRecord.stoped为FALSE,由于这个Activity确实还没全然stop下来。 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r + " (stop requested)"); r.state = ActivityState.STOPPING; //⑥设置ActivityRecord.state为STOPPING状态 if (DEBUG_VISBILITY) Slog.v( TAG, "Stopping visible=" + r.visible + " for " + r); if (!r.visible) { mWindowManager.setAppVisibility(r.appToken, false); //⑤stop一个Activity时设置该Activity的窗体不可见。 } r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); //回调应用层的stop处理函数。 if (mService.isSleepingOrShuttingDown()) { //⑥当系统正准备要sleeping或shutdown时,将这个Activity进行sleep处理。在什么情况下须要sleep一个Activity呢?当系统要sleep。而且这个Activity的状态为stopping或stoped时便把这个Activity进行sleep处理。 r.setSleeping(true); } Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); } catch (Exception e) { // Maybe just ignore exceptions here... if the process // has crashed, our death notification will clean things // up. Slog.w(TAG, "Exception thrown during pause", e); // Just in case, assume it to be stopped. r.stopped = true; if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r); r.state = ActivityState.STOPPED; if (r.configDestroy) { destroyActivityLocked(r, true, false, "stop-except"); } } } }


    3、activityIdleInternalLocked()

        // Checked.
        final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
                Configuration config) {
            if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
    
            ArrayList<ActivityRecord> stops = null;
            ArrayList<ActivityRecord> finishes = null;
            ArrayList<UserStartedState> startingUsers = null;
            int NS = 0;
            int NF = 0;
            IApplicationThread sendThumbnail = null;
            boolean booting = false;
            boolean enableScreen = false;
            boolean activityRemoved = false;
    
            ActivityRecord r = ActivityRecord.forToken(token);    //①假设传进来的參数token不为null,将代表參数token的ActivityRecord.idle 设为true。

    if (r != null) { if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" + Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); if (fromTimeout) { reportActivityLaunchedLocked(fromTimeout, r, -1, -1); } // This is a hack to semi-deal with a race condition // in the client where it can be constructed with a // newer configuration from when we asked it to launch. // We'll update with whatever configuration it now says // it used to launch. if (config != null) { r.configuration = config; } // We are now idle. If someone is waiting for a thumbnail from // us, we can now deliver. r.idle = true; if (r.thumbnailNeeded && r.app != null && r.app.thread != null) { sendThumbnail = r.app.thread; r.thumbnailNeeded = false; } //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); if (!mService.mBooted && isFrontStack(r.task.stack)) { mService.mBooted = true; enableScreen = true; } } if (allResumedActivitiesIdle()) { //②假设全部ActivityStack.mResumedActivity.idle为true,。。

    。 if (r != null) { mService.scheduleAppGcsLocked(); } if (mLaunchingActivity.isHeld()) { mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) { throw new IllegalStateException("Calling must be system uid"); } mLaunchingActivity.release(); } ensureActivitiesVisibleLocked(null, 0); } // Atomically retrieve all of the other things to do. stops = processStoppingActivitiesLocked(true); //③将mStoppingActivities中不可见的Activity进行返回,在第⑦中进行进一步处理 NS = stops != null ? stops.size() : 0; if ((NF=mFinishingActivities.size()) > 0) { //④清除mFinishingActivities。并在第⑧中进一步进行处理 finishes = new ArrayList<ActivityRecord>(mFinishingActivities); mFinishingActivities.clear(); } final ArrayList<ActivityRecord> thumbnails; final int NT = mCancelledThumbnails.size(); if (NT > 0) { //⑤清除mCancelledThumbnails,并在第⑥中进一步处理 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails); mCancelledThumbnails.clear(); } else { thumbnails = null; } if (isFrontStack(mHomeStack)) { booting = mService.mBooting; mService.mBooting = false; } if (mStartingUsers.size() > 0) { startingUsers = new ArrayList<UserStartedState>(mStartingUsers); mStartingUsers.clear(); } // Perform the following actions from unsynchronized state. final IApplicationThread thumbnailThread = sendThumbnail; mHandler.post(new Runnable() { //⑥处理thumbnails。干嘛的? @Override public void run() { if (thumbnailThread != null) { try { thumbnailThread.requestThumbnail(token); } catch (Exception e) { Slog.w(TAG, "Exception thrown when requesting thumbnail", e); mService.sendPendingThumbnail(null, token, null, null, true); } } // Report back to any thumbnail receivers. for (int i = 0; i < NT; i++) { ActivityRecord r = thumbnails.get(i); mService.sendPendingThumbnail(r, null, null, null, true); } } }); // Stop any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NS; i++) { //⑦处理processStoppingActivitiesLocked()返回的Activity。假设这个Activity正在finish,那么直接调用finishCurrentActivityLocked()马上finish掉。否则调用stopActivityLocked()来stop这些Activity。

    r = stops.get(i); final ActivityStack stack = r.task.stack; if (r.finishing) { stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false); } else { stack.stopActivityLocked(r); } } // Finish any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NF; i++) { //⑧destroy掉mFinishingActivities中的Activity。

    r = finishes.get(i); activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle"); } if (booting) { mService.finishBooting(); } else if (startingUsers != null) { for (int i = 0; i < startingUsers.size(); i++) { mService.finishUserSwitch(startingUsers.get(i)); } } mService.trimApplications(); //⑨精简进程,回收内存。 //dump(); //mWindowManager.dump(); if (enableScreen) { mService.enableScreenAfterBoot(); } if (activityRemoved) { resumeTopActivitiesLocked(); } return r; }

    这个函数主要是将StoppingActivities进行finish或直接stop掉,FinishingActivities进行destroy掉。最后再调用trimApplications()精简进程,回收内存。

    4. isActivityOverHome()函数分析

        boolean isActivityOverHome(ActivityRecord record) {
            // Start at record and go down, look for either home or a visible fullscreen activity.
            final TaskRecord recordTask = record.task;
            for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) {
                TaskRecord task = mTaskHistory.get(taskNdx);
                final ArrayList<ActivityRecord> activities = task.mActivities;
                final int startNdx =
                        task == recordTask ?

    activities.indexOf(record) : activities.size() - 1; for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.isHomeActivity()) { return true; } if (!r.finishing && r.fullscreen) { // Passed activity is over a fullscreen activity. return false; } } if (task.mOnTopOfHome) { // Got to the bottom of a task on top of home without finding a visible fullscreen // activity. Home is visible. return true; } } // Got to the bottom of this stack and still don't know. If this is over the home stack // then record is over home. May not work if we ever get more than two layers. return mStackSupervisor.isFrontStack(this); }

    这个函数用来推断launcher是否显示在给出的activity之下,假设显示在给出的activity之下。那么返回true,否则返回false。

  • 相关阅读:
    hdu6325 /// 上凸包
    hdu6315 /// 线段树区间更新
    hdu6311 /// 欧拉路径 无向图最小路径覆盖 输出正反路径
    Codeforces Round #535 F-MST Unification
    HDU4405 Aeroplane chess (概率DP,转移)
    ZOJ 3329 One Person Game(概率DP,求期望)
    poj3744 (概率DP+矩阵快速幂)
    “美登杯”上海市高校大学生程序设计 E. 小花梨的数组 (线段树)
    关于标记的一些事~~
    关于C(n,m) 的奇偶 ,与C(n,0),C(n,1),C(n,2)…C(n,n).当中有多少个奇数
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6937886.html
Copyright © 2020-2023  润新知