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

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正在finishif (!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。

Activity管理笔记相关推荐

  1. iOS 与OS X多线程和内存管理 笔记 ARC与所有权修饰符

    注:本文为笔记形式,所以很多都是摘抄的.<<iOS 与OS X多线程和内存管理>>书中写的很棒,简单易懂,建议各位看官自己去看看. ####ARC和MRC 前一篇主要是MRC环 ...

  2. Activity管理(三):activity内核管理方案详细讲解

    一.Activity的生命周期 Activity的管理同样是基于C/S架构的,所有的activity管理都在server端进行.在Server端对每个activity进行调度的同时,Client端负责 ...

  3. oracle 10g 用户管理笔记

    Oracle用户管理笔记 1.创建用户 sql>conn system/manager sql>create user xiaoming identfied by m123; //密码必须 ...

  4. RHCE课程-RH131Linux管理笔记五-Linux远程登陆telnet及ssh服务

    telnet相信大家都不陌生,在RHCE课程-RH131Linux管理笔记三-linux系统服务介绍及管理里面我们已经配置过了,我也不多做介绍,直接说安装吧. 使用yum安装的前提是你已经配置好YUM ...

  5. Android Activity学习笔记——Activity的启动和创建

    最近学习Android相关知识,感觉仅仅了解Activity几个生命周期函数基本上没有任何意义的: 于是想深入了解一下Activity到底是怎么一回事怎么运行来的:里面的东东真是叫个庞大: 现在只能简 ...

  6. 【Android工具类】Activity管理工具类AppManager

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 import java.util.Stack;import android.app.Activity; im ...

  7. 方根法公式_仓储管理笔记之库存分析法:ABC分析法、区域合并法......

    导读 国内有庞大的仓储物流从业人员队伍(根据中国物流与采购联合会的调查,2016年底我国物流从业人员5012万,是人员增速最快的行业),很多人只是想深入了解仓库从无序到有序,从源头开始应该如何管理.如 ...

  8. eas库存状态调整单不能反审核_仓储管理笔记:库存差错、毁损赔偿、自用管理、组织架构.........

    国内有庞大的仓储物流从业人员队伍(根据中国物流与采购联合会的调查,2016年底我国物流从业人员5012万,是人员增速最快的行业),很多人只是想深入了解仓库从无序到有序,从源头开始应该如何管理.如何优化 ...

  9. 用于Activity管理和应用程序退出

    ;import android.app.Activity; import android.content.Context;import java.util.Stack;/*** 应用程序Activit ...

最新文章

  1. Scrum敏捷开发工具实力推荐
  2. Xcode真机调试(有证书)
  3. 「LibreOJ β Round #4」子集
  4. 玩客云刷windows做服务器_精选 | 搭建一个私人服务器如何?
  5. axios get post下载文件
  6. linux spf13 vim安装,Linux 下安装 spf13-VIM
  7. 包管理器Bower使用手册之一
  8. (多重背包+记录路径)Charlie's Change (poj 1787)
  9. 中心极限与大数定理律的关系_多元函数的极限、连续性分析
  10. php js后端渲染,webpack后端渲染详解
  11. 中国庭院刮板市场趋势报告、技术动态创新及市场预测
  12. Google的语音识别API,支持各种语言
  13. 美和易思——互联网技术学院返校周测题
  14. OneZero第四周第五次站立会议(2016.4.15)
  15. 使用cpolar内网穿透搭建远程监控
  16. 飞塔防火墙MIB-OID列表
  17. 教你如何编写游戏外挂
  18. BT源代码学习心得(四):种子文件的生成 -- 转贴自wolfenstein (NeverSayNever)
  19. win10如何添加或禁用开机自启动项
  20. 1024分辨率《圣徒/天神魔煞/猎魔教士》BD中字无水印

热门文章

  1. node.js中ws模块创建服务端和客户端,网页WebSocket客户端
  2. delphi android路径 TPath 文件路径,文件管理
  3. Response.AddHeader
  4. 图像匹配得到精确的旋转角度
  5. python驱动级模拟按键大师_AB叔_C#驱动级模拟按键操作
  6. 计算机网络协议是网民们签订的合同,关于网络协议,下列__________选项是正确的。A.是网民们签订的合同B.是计算机之间的相互通信需...
  7. vue多页面开发_使用VUE进行移动端H5页面开发前准备
  8. C++ 常见错误(01) —— error LNK1104: 无法打开文件“avcodec.lib”
  9. java 485通讯_CAKJ-963U3-KT带485通讯上下限报警智能型仪表
  10. cenyos7安装 yum不可用_centos7安装fabric