Android 6.0 AMS分析的第二条线:以Launcher启动一个Activity为例,分析应用进程的创建、Activity的启动,以及他们和AMS之间的交互等知识;
来源:互联网 发布:海尔cosmo平台 知乎 编辑:程序博客网 时间:2024/05/29 19:20
这篇是通过Launcher启动一个activity的过程,先以一张开头。
Step 1. Launcher.startActivitySafely
在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。
Launcher.java (packages\apps\launcher3\src\com\android\launcher3)
public boolean startActivitySafely(View v, Intent intent, Object tag) { boolean success = false; if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) { Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show(); return false; } try { success = startActivity(v, intent, tag); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e); } return success; }
Step 2. Activity.startActivity
在Step 1中,我们看到,Launcher继承于Activity类,而Activity类实现了startActivity函数,因此,这里就调用了Activity.startActivity函数
Activity.java (frameworks\base\core\java\android\app)
@Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // 这个函数实现很简单,它调用startActivityForResult来进一步处理,第二个参数传入-1表示不需要这个Actvity结束后的返回结果。 startActivityForResult(intent, -1); } }
Step 3. Activity.startActivityForResult
public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) { Uri referrer = onProvideReferrer(); if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, who, requestCode, ar.getResultCode(), ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
1、这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。
2、这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,我们在Android系统在新进程中启动自定义服务过程(startService)的原理分析一文中已经介绍过了。这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。
3、这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
Step 4. Instrumentation.execStartActivity
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { ...... } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); // ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口 int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, /* 这里的intent.resolveTypeIfNeeded返回这个intent的MIME类型,在这个例子中, 没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。 */ intent.resolveTypeIfNeeded(who.getContentResolver()), token, target, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
Step 5. ActivityManagerProxy.startActivity
ActivityManagerNative.java (frameworks\base\core\java\android\app)
public int startActivity(......) throws RemoteException { /* 参数resolvedType、resultWho均为null; 参数caller为ApplicationThread类型的Binder实体; 参数resultTo为一个Binder实体的远程接口,我们先不关注它; 参数grantedMode为0,我们也先不关注它; 参数requestCode为-1; 参数onlyIfNeeded和debug均空false。 */ Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(callingPackage); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); return result; }
Step 6. ActivityManagerService.startActivity
这里只是简单地将操作转发给成员变量mStackSupervisor的startActivityMayWait函数,这里的mMainStack的类型为ActivityStackSupervisor。
@Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { enforceNotIsolatedCaller("startActivity"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, options, false, userId, null, null); }
Step 7. ActivityStackSupervisor.startActivityMayWait
一、ActivityStackSupervisor.java (frameworks\base\services\core\java\com\android\server\am)
一)、startActivityMayWait函数的目标是启动com.dfp.test.TestActivity,假设系统之前没有启动过该Activity,
本例最终的结果将是:
1、由于在am中设置了FLAG_ACTIVITY_NEW_TASK标志,因此除了会创建一个新的ActivityRecord外,
还会新建一个TaskR额cord
2、还需要启动一个新的应用进程以加载并运行com.dfp.test.TestActivity的一个实例
3、如果TestActivity不是home,还需要停止当前正在显示的Activity
二)、将这个函数分三部分进行介绍
第一部分:
1、首先需要通过PKMS查询匹配该Intent的ActivityInfo
2、处理FLAG_CANT_SAVE_STATE的情况,但系统目前不支持此情况
3、获取调用者的pid和uid,由于本例的caller为null,故所得到的pid和uid均为am所在进程的uid和pid。
第二部分:启动核心函数startActivityLocked
第三部分:根据返回值做一些处理,那么res返回成功后(即res==IActivityManager.START_SUCCESS的时候)
后为何还需要等待? 这是因为目标Activity要运行在一个新的应用进程中,就必须等待那个应用进程正常启动
并处理相关的请求。
final int startActivityMayWait(......) { // 第一部分:本例已经指明了component,这样可以省去为Intent匹配搜索之苦 boolean componentSpecified = intent.getComponent() != null; // 创建一个新的Intent,防止客户传入的Intent被修改 intent = new Intent(intent); // 查询满足条件的ActivityInfo,在resolveActivity内部和PKMS交互, // 参数intent的内容进行解析,得到MainActivity的相关信息,保存在aInfo变量中 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId); // ActivityContainer container = (ActivityContainer) iContainer; synchronized (mService) { if (container != null && container.mParentActivity != null && container.mParentActivity.state != RESUMED) { // Cannot start a child activity if the parent is not resumed. return ActivityManager.START_CANCELED; } final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { callingPid = -1; } else if (caller == null) { //本例中,caller为null callingPid = realCallingPid; // 取出调用进程的pid callingUid = realCallingUid;// 取出调用进程的uid } else { callingPid = callingUid = -1; } final ActivityStack stack; if (container == null || container.mStack.isOnHomeDisplay()) { stack = mFocusedStack; } else { stack = container.mStack; } // 在本例中config为null stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; final long origId = Binder.clearCallingIdentity(); if (aInfo != null && (aInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { ...... } // 第二部分:调用此函数启动Activity,将返回值保存到res int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, null, container, inTask); Binder.restoreCallingIdentity(origId); // 如果configuration发生变化,则调用AMS的updateConfigurationLocked进行处理 if (stack.mConfigWillChange) { // If the caller also wants to switch to a new configuration, // do so now. This allows a clean switch, as we are waiting // for the current activity to pause (so we will not destroy // it), and have not yet started the next activity. mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); stack.mConfigWillChange = false; mService.updateConfigurationLocked(config, null, false, false); } if (outResult != null) { outResult.result = res; // 第三部分:设置启动结果 if (res == ActivityManager.START_SUCCESS) { // 该结果在mWaitingActivityLaunched中保存 mWaitingActivityLaunched.add(outResult); do { try { mService.wait(); // 等待启动结果 } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } else if (res == ActivityManager.START_TASK_TO_FRONT) { // 处理START_TASK_TO_FRONT结果 ActivityRecord r = stack.topRunningActivityLocked(null); if (r.nowVisible && r.state == RESUMED) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mWaitingActivityVisible.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } } } return res; } }
Step 8. ActivityStack.startActivityLocked二、startActivityLocked分析
一)、startActivityLocked是startActivityMayWait第二阶段的重点
它的主要工作包括:
1、处理sourceRecord及resultRecord。其中,sourceRecord表示发起本次请求的Activity,
resultRecord表示接收处理结果的Activity(启动一个Activity肯定需要它完成某项事情,
当目标Activity将事情成后,就需要告知请求者该事情的处理结果)。
在一般情况下,sourceRecord和resultRecord应指向同一个Activity。
2、处理app switch。 如果AMS当前禁止app switch,则只能把本次启动请求保存起来,
以待允许app switch时在处理。 从代码中可知,AMS在处理本次请求前,会先调用
doPendingActivityLaunchesLocked函数,在该函数内部将启动之前因系统禁止app switch
而保存的Pending请求。
3、将对应ActivityRecord移动到Task的顶部
4、调用startActivityUncheckedLocked处理本次Activity启动请求
final int startActivityLocked(......) { int err = ActivityManager.START_SUCCESS; ProcessRecord callerApp = null; // 如果caller不为空,则需要从AMS中找到它的ProcessRecord。本例中的caller为null if (caller != null) { // 从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了 callerApp = mService.getRecordForAppLocked(caller); // 其实就是想得到进程的pid和uid if (callerApp != null) { // 一定要保证调用进程的pid和uid正确 callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { // 如果用进程没有在AMS中注册,则认为其实非法的 err = ActivityManager.START_PERMISSION_DENIED; } } final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; /* 下面两个变量很重要,sourceRecord用于描述启动目标Activity的那个Activity, resultRecord用于描述接收启动的结果的Activity,即,该Activity的onActivityResult 将被调用已通知启动结果 */ ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { // 参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。 sourceRecord = isInAnyStackLocked(resultTo); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } } // 获取Intent设置的启动标志,他们是和Launch Mode 类似的小把戏 final int launchFlags = intent.getFlags(); if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { /* 前面介绍的Launch Mode和Acitivity的启动有关,实际上还有一部分标志用于控制Activity启动结果的通知。 使用FLAG_ACTIVITY_FORWARD_RESULT前Activity必须先存在(sourceRecord != null) */ } // 检查err值及Intent的情况 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { // We couldn't find a class that can handle the given Intent. // That's the end of that! err = ActivityManager.START_INTENT_NOT_RESOLVED; } final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack; // 如果err不为0,则调用sendActivityResultLocked返回错误 if (err != ActivityManager.START_SUCCESS) { if (resultRecord != null) { // resultRecord接收启动结果 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); return err; } boolean abort = false; // 权限检查 final int startAnyPerm = mService.checkPermission( START_ANY_ACTIVITY, callingPid, callingUid); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); /* 可为AMS设置一个IActivityController类型的监听,AMS有任何动静都会回调该监听 不过谁又有如此本事监听AMS? 在进行Monkey测试的时候,Monkey会设置该回调的对象。 这样,Monkey就能根据AMS放映的情况进行相应的处理*/ if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data // stripped off, since it can contain private information. Intent watchIntent = intent.cloneFilter(); abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } } // 回调对象决定不启动该Activity,在进行monkey测试时,可设置黑名单,位于黑名单中的Activity将不能启动 if (abort) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } // We pretend to the caller that it was really started, but // they will just get a cancel result. ActivityOptions.abort(options); // 通知resultRecord return ActivityManager.START_SUCCESS; } // 创建一个ActivityRecord对象 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this, container, options); if (outActivity != null) { outActivity[0] = r; // 保存到输入参数outActivity数组中 } if (r.appTimeTracker == null && sourceRecord != null) { // If the caller didn't specify an explicit time tracker, we want to continue // tracking under any it has. r.appTimeTracker = sourceRecord.appTimeTracker; } final ActivityStack stack = mFocusedStack; // mResumedActivity 代表当前界面显示的Activity if (voiceSession == null && (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { // 检查调用进程是否有权限切换Application if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { // 如果调用进程没有权限切换Activity,则只能把这次Activity启动请求保存起来, // 后续有机会再启动它 PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack); // 所有Pending的请求均保存到AMS mPendingActivityLaunches变量中 mPendingActivityLaunches.add(pal); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; } } if (mService.mDidAppSwitch) { // 用于控制app switch // This is the second allowed switch since we stopped switches, // so now just generally allow switches. Use case: user presses // home (switches disabled, switch to home, mDidAppSwitch now true); // user taps a home icon (coming from home so allowed, we hit here // and now allow anyone to switch again). mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } doPendingActivityLaunchesLocked(false); // 调用startActivityUncheckedLocked函数 err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); if (err < 0) { // If someone asked to have the keyguard dismissed on the next // activity start, but we are not actually doing an activity // switch... just dismiss the keyguard now, because we // probably want to see whatever is behind it. notifyActivityDrawnForKeyguard(); } return err; }
二)、先来看看app switch,它虽然是一个小变量,但是意义重大,关于resume/stopAppSwitches的介绍
AMS提供了两个函数,用于暂时,禁止App切换,为什么会有这种需求? 因为当某些重要(例如设置账号)
Activity处于前台(即用户当前所见的Activity)时,不希望系统因用户操作之外的原因而切换Activity(例如来电)。
@Override public void stopAppSwitches() { // 检查调用进程是否有STOP_APP_SWITCHES权限 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires permission " + android.Manifest.permission.STOP_APP_SWITCHES); } synchronized (this) { // 设置一个超时时间,过了这个时间,AMS可以重新切换App(switch app) mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME; mDidAppSwitch = false; // 设置mDidAppSwitch为false mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG); // 防止应用进程调用了stop却没有调用resume,5秒后处理该消息 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG); mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME); } }
以上代码中有两点需要注意:
1、此处控制机制名为app switch, 而不是activity switch。为什么? 因为从受保护的
Activity中启动另一个Activity,那么这个新Activity的目的应该是针对同一任务,
这次启动就不应该受app switch的制约了,反而应该对其打开绿灯。目前,
在执行Settings中设置设备策略(DevicePlicy)时就会stopAppSwitch。
2、执行stopAppSwitch后,应用程序应该调用resumeAppSwitches以允许app switch,
但是为了防止应用程序有意或无意忘记resume app switch,系统设置了一个超时时间(5s)
过了这个时间,系统将处理相应的消息,内部会resume app switch
三)、再看resumeAppSwitch函数
public void resumeAppSwitches() { // 检测调用进程是否具有STOP_APP_SWITCHES权限 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires permission " + android.Manifest.permission.STOP_APP_SWITCHES); } synchronized (this) { // Note that we don't execute any pending app switches... we will // let those wait until either the timeout, or the next start // activity request. mAppSwitchesAllowedTime = 0; } }
在resumeAppSwitches中只设置mAppSwitchesAllowTime的值为0,它并不处理在stop和resume这段时间内积攒起来的Pending请求,
那么这些请求时在何时被处理的?
1、从前面代码可知,如果在执行resume app switch后,又有新的请求需要处理,则先处理那些pending的请求
(调用doPendingActivityLaunchesLocked)。
2、在resumeAppSwitches中并未撤销stopAppSwitches函数中设置的超时消息,所以在处理那条超时消息,
所以在处理那条消息的过程中,也会处理pending的请求。
注: 在本例中,由于不考虑app switch的情况,那么接下来的工作就是调用startActivityUncheckLocked函数
来处理本次Activity的启动请求。此时,我们已经创建了一个ActivityRecord用于保存目标Acticity的相关信息
Step 9. ActivityStackSupervisor.startActivityUncheckedLocked
ActivityStackSupervisor.java (frameworks\base\services\core\java\com\android\server\am)
四)、startActivityUncheckLocked函数分析
startActivityUncheckLocked函数比较长,但目的比较简单,为新创建的ActivityRecord找到一个合适的Task。
本例最终结果就是创建一个新的Task,其中startActivityUncheckLocked函数比较复杂,分为三段进行分析
1、确定是否需要为新的Activity创建一个Task,即是否设置FLAG_ACTIVITY_NEW_TASK标志
2、找到一个合适的Task然后做一些处理
3、创建一个新的TaskRecord,并调用startAcitivityLocked函数进行处理
4、首先调用adjustStackFocus()判断目标Activity是否是普通APP还是Home,对应的Stack是否已经创建,若未创建,则创建对应Stack。然后根据启动的Flag和启动模式,判断是否需要在新的Task里运行目标Activity。若需要新的Task,则new 一个TaskRecord,若不需要,则获得当前Taskd的对象,并将TaskRecord和对应的ActivityRecord 关联起来。
final int startActivityUncheckedLocked(......) { // final Intent intent = r.intent; final int callingUid = r.launchedFromUid; // 函数首先获得intent的标志值,保存在launchFlags变量中。 int launchFlags = intent.getFlags(); // 判断是否需要调用本次Acivity启动而被系统移到后台的当前Activity的 // onUserLeaveHint 函数, mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0; // If the caller has asked not to resume at this point, we make note // of this in the record so that we can skip it when trying to find // the top running activity. if (!doResume) { r.delayedResume = true; } // 本例的notTop为空 ActivityRecord notTop = (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; // if (sourceRecord == null && inTask != null && inTask.stack != null) { final Intent baseIntent = inTask.getBaseIntent(); final ActivityRecord root = inTask.getRootActivity(); if (baseIntent == null) { ActivityOptions.abort(options); throw new IllegalArgumentException("Launching into task without base intent: " + inTask); } // If this task is empty, then we are adding the first activity -- it // determines the root, and must be launching as a NEW_TASK. if (launchSingleInstance || launchSingleTask) { if (!baseIntent.getComponent().equals(r.intent.getComponent())) { ActivityOptions.abort(options); throw new IllegalArgumentException("Trying to launch singleInstance/Task " + r + " into different task " + inTask); } if (root != null) { ActivityOptions.abort(options); throw new IllegalArgumentException("Caller with inTask " + inTask + " has root " + root + " but target is singleInstance/Task"); } } // If task is empty, then adopt the interesting intent launch flags in to the // activity being started. if (root == null) { final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; launchFlags = (launchFlags & ~flagsOfInterest) | (baseIntent.getFlags() & flagsOfInterest); intent.setFlags(launchFlags); inTask.setIntent(r); addingToTask = true; } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { addingToTask = false; } else { addingToTask = true; } reuseTask = inTask; } else { inTask = null; } if (inTask == null) { if (sourceRecord == null) { // 如果请求的发起者为空,则需要新建一个Task if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } // 如果sourceRecord单独占一个Instance,则新的Activity必然处于另一个Task中 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // 如果启动模式设置为singleTask或singleInstance,则也要创建Task launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } else if (launchSingleInstance || launchSingleTask) { // The activity being started is a single instance... it always // gets launched into its own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } } ActivityInfo newTaskInfo = null; Intent newTaskIntent = null; ActivityStack sourceStack; if (sourceRecord != null) { if (sourceRecord.finishing) { // if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; } else { sourceStack = sourceRecord.task.stack; } } else { sourceStack = null; } boolean movedHome = false; ActivityStack targetStack; intent.setFlags(launchFlags); final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0; // 这么多复杂的逻辑处理,无非就是要找到一个合适的Task,然后对应做一些处理。 // if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask) { } // 第三阶段: if (r.packageName != null) { // 判断目标Activity是否已经在栈顶,如果是,需要判断是创建一个新的Activity还是调用 // onNewIntent(singleTop模式的处理) ActivityStack topStack = mFocusedStack; ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); // 在本例中,需要创建一个Task boolean newTask = false; boolean keepCurTransition = false; TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ? sourceRecord.task : null; // Should this be considered a new task? if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if (reuseTask == null) { // 为该ActivityRecord设置一个新的TaskRecord r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, !launchTaskBehind /* toTop */), taskToAffiliate); } else { r.setTask(reuseTask, taskToAffiliate); } if (isLockTaskModeViolation(r.task)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (!movedHome) { if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity, so before starting // their own activity we will bring home to the front. r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } } else if (sourceRecord != null) { final TaskRecord sourceTask = sourceRecord.task; if (isLockTaskModeViolation(sourceTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } targetStack = sourceTask.stack; targetStack.moveToFront("sourceStackToFront"); final TaskRecord topTask = targetStack.topTask(); if (topTask != sourceTask) { targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options, r.appTimeTracker, "sourceTaskToFront"); } if (!addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { // In this case, we are adding the activity to an existing // task, but the caller has asked to clear that task if the // activity is already running. ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags); keepCurTransition = true; if (top != null) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); // For paranoia, make sure we have correctly // resumed the top activity. targetStack.mLastPausedActivity = null; if (doResume) { targetStack.resumeTopActivityLocked(null); } ActivityOptions.abort(options); return ActivityManager.START_DELIVERED_TO_TOP; } } else if (!addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { // In this case, we are launching an activity in our own task // that may already be running somewhere in the history, and // we want to shuffle it to the front of the stack if so. final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r); if (top != null) { final TaskRecord task = top.task; task.moveActivityToFrontLocked(top); ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task); top.updateOptionsLocked(options); top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); targetStack.mLastPausedActivity = null; if (doResume) { targetStack.resumeTopActivityLocked(null); } return ActivityManager.START_DELIVERED_TO_TOP; } } // An existing activity is starting this new activity, so we want // to keep the new one in the same task as the one that is starting // it. r.setTask(sourceTask, null); } else if (inTask != null) { // The caller is asking that the new activity be started in an explicit // task it has provided to us. if (isLockTaskModeViolation(inTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } targetStack = inTask.stack; targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker, "inTaskToFront"); // Check whether we should actually launch the new activity in to the task, // or just reuse the current activity on top. ActivityRecord top = inTask.getTopActivity(); if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) { if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop || launchSingleTask) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and // the client said not to do anything if that // is the case, so this is it! return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); return ActivityManager.START_DELIVERED_TO_TOP; } } if (!addingToTask) { // We don't actually want to have this activity added to the task, so just // stop here but still tell the caller that we consumed the intent. ActivityOptions.abort(options); return ActivityManager.START_TASK_TO_FRONT; } r.setTask(inTask, null); } else { // This not being started from an existing activity, and not part // of a new task... just put it in the top task, though these days // this case should never happen. targetStack = computeStackFocus(r, newTask); targetStack.moveToFront("addingToTopTask"); ActivityRecord prev = targetStack.topActivity(); r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true), null); mWindowManager.moveTaskToTop(r.task.taskId); } mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, intent, r.getUriPermissionsLocked(), r.userId); if (sourceRecord != null && sourceRecord.isRecentsActivity()) { r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE); } if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); } ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); targetStack.mLastPausedActivity = null; // 调用startActivityLocked,此时ActivityRecord和TaskRecord均创建完毕 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); if (!launchTaskBehind) { // Don't set focus on an activity that's going to the back. mService.setFocusedActivityLocked(r, "startedActivity"); } return ActivityManager.START_SUCCESS; }
五)、以上代码第三阶段将创建一个新的TaskRecord,并调用startActivityLocked函数
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) { TaskRecord rTask = r.task; final int taskId = rTask.taskId; // mLaunchTaskBehind tasks get placed at the back of the task stack. if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { // insertTaskAtTop(rTask, r); mWindowManager.moveTaskToTop(taskId); } TaskRecord task = null; if (!newTask) { // 如果不是新的Task,则从mHistory中找到对应的AcitivityRecord的位置 ...... } // 设置ActivityRecord的inHistory变量为true,表示已经加到mHistory数组中了 task = r.task; task.addActivityToTop(r); task.setFrontOfTask(); r.putInHistory(); // 最终调用resumeTopActivitiesLocked函数,后面我们重点分析这个函数 if (doResume) { mStackSupervisor.resumeTopActivitiesLocked(this, r, options); } }
Step 10. ActivityStack.resumeTopActivityLocked
ActivityStack.java (frameworks\base\services\core\java\com\android\server\am)
六)、resumeTopActivitiesLocked函数分析
该函数首先判断栈顶是否有需要显示的Activity,没有则启动Launcher,如果有需要显示的,还需要判断是否有需要暂停的Activity,有则执行Activity暂停操作。
final boolean resumeTopActivityLocked(ActivityRecord prev) { return resumeTopActivityLocked(prev, null); }
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (mStackSupervisor.inResumeTopActivity) { /// M: BMW. Add log @{ if (MultiWindowProxy.isSupported()) { if (DEBUG_STACK) Slog.w(TAG, "[BMW] resumeTopActivityLocked:" + "Don't even start recursing Stack:" + this); } /// @} // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; mService.updateSleepIfNeededLocked(); } result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result; }
它首先看要启动的Activity是否就是当前处理Resumed状态的Activity,如果是的话,那就什么都不用做,直接返回就可以了;否则再看一 下系统当前是否休眠状态,如果是的话,再看看要启动的Activity是否就是当前处于堆栈顶端的Activity,如果是的话,也是什么都不用做。
上面两个条件都不满足,因此,在继续往下执行之前,首先要把当处于Resumed状态的Activity推入Paused状态,然后才可以启动新的 Activity。但是在将当前这个Resumed状态的Activity推入Paused状态之前,首先要看一下当前是否有Activity正在进入 Pausing状态,如果有的话,当前这个Resumed状态的Activity就要稍后才能进入Paused状态了,这样就保证了所有需要进入 Paused状态的Activity串行处理。
这里没有处于Pausing状态的Activity,即mPausingActivity为null,而且mResumedActivity也不为 null,于是就调用startPausingLocked函数把Launcher推入Paused状态去了。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { /* 1、从mHistory中找到第一个需要启动的ActivityRecord 2、函数先通过调用topRunningActivityLocked函数获得堆栈顶端的Activity, 这里就是MainActivity了,这是在上面的Step 9设置好的,保存在next变量中。 */ final ActivityRecord next = topRunningActivityLocked(null); /* 接下来把mUserLeaving的保存在本地变量userLeaving中,然后重新设置为false, 在上面的Step 9中,mUserLeaving的值为true,因此,这里的userLeaving为true。 */ final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; final TaskRecord prevTask = prev != null ? prev.task : null; if (next == null) { // There are no more activities! final String reason = "noMoreActivities"; if (!mFullscreen) { // Try to move focus to the next visible stack with a running activity if this // stack is not covering the entire screen. final ActivityStack stack = getNextVisibleStackLocked(); if (adjustFocusToNextVisibleStackLocked(stack, reason)) { return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null); } } // Let's just start up the Launcher... ActivityOptions.abort(options); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); // Only resume home if on home display final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason); } // 本例中,next将是目标Activity next.delayedResume = false; // If the top activity is the resumed one, nothing to do. if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } final TaskRecord nextTask = next.task; if (prevTask != null && prevTask.stack == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else if (!isOnHomeDisplay()) { return false; } else if (!isHomeStack()) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Launching home next"); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished"); } } /* 当我们处理休眠状态时,mLastPausedActivity保存堆栈顶端的Activity,因为当前不是休眠状态,所以mLastPausedActivity为null。 */ if (mService.isSleepingOrShuttingDown() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Going to sleep and all paused"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // Make sure that the user who owns this activity is started. If not, // we will just leave it as is because someone should be bringing // another user's activities to the top of the stack. if (mService.mStartedUsers.get(next.userId) == null) { Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } //将该ActivityRecord从下面几个队列中移除 mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mWaitingVisibleActivities.remove(next); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); // If we are currently pausing an activity, then don't do anything // until that is done. if (!mStackSupervisor.allPausedActivitiesComplete()) { if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing."); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // Okay we are now going to start a switch, to 'next'. We may first // have to pause the current activity, but this is an important point // where we have decided to go to 'next' so keep track of that. // XXX "App Redirected" dialog is getting too many false positives // at this point, so turn off for now. if (false) { if (mLastStartedActivity != null && !mLastStartedActivity.finishing) { long now = SystemClock.uptimeMillis(); final boolean inTime = mLastStartedActivity.startTime != 0 && (mLastStartedActivity.startTime + START_WARN_TIME) >= now; final int lastUid = mLastStartedActivity.info.applicationInfo.uid; final int nextUid = next.info.applicationInfo.uid; if (inTime && lastUid != nextUid && lastUid != next.launchedFromUid && mService.checkPermission( android.Manifest.permission.STOP_APP_SWITCHES, -1, next.launchedFromUid) != PackageManager.PERMISSION_GRANTED) { mService.showLaunchWarningLocked(mLastStartedActivity, next); } else { next.startTime = now; mLastStartedActivity = next; } } else { next.startTime = SystemClock.uptimeMillis(); mLastStartedActivity = next; } } mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); // We need to start pausing the current activity so the top one // can be resumed... boolean dontWaitForPause = (next.info.flags & ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); /* 1、如果当前正在中断一个Acitivity,需先等待那个Activity pause完毕,然后系统会重新 调用resumeTopActivityLocked函数以找到下一个个启动的Activity 2、mResumedActivity 指向上一次启动的Acitivity,也就是当前界面显示的这个Acitivity 在本例中,当前Activity就是Home界面 3、如果mResumedActivity为空,则一定是系统第一个启动的Acitivity,读者应该能猜出来他就是home */ if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); // 先中断Home,这种情况放在最后进行分析 pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } if (pausing) { // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } return true; } // If the most recent activity was noHistory but was only stopped rather // than stopped+finished because the device went to sleep, we need to make // sure to finish it as we're making a new activity topmost. if (mService.isSleeping() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, null, "resume-no-history", false); mLastNoHistoryActivity = null; } // 如果prev不为空,则需要通知WMS进行与Activity切换相关的工作 if (prev != null && prev != next) { } // 通知PKMS修改该package stop 状态 try { AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false, next.userId); /* TODO: Verify if correct userid */ } catch (RemoteException e1) { } // We are starting up the next activity, so tell the window manager // that the previous one will be hidden soon. This way it can know // to ignore it when computing the desired screen orientation. if (prev != null) { // 还是和wms有关,通知停止绘画 } // 如果该ActivityRecord已有对应的进程存在,则需要重启Activity,就本例而言, // 此进程还不存在,所以要先创建一个应用进程 if (next.app != null && next.app.thread != null && needResume) { } else { //第一次启动 if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { // 通知wms显示启动界面 } // 调用另外一个startSpecificActivityLocked函数 mStackSupervisor.startSpecificActivityLocked(next, true, true); } return true; }
Step 11. ActivityStack.startPausingLocked
一、
1、当启动一个新Activity时,系统将先行处理当前的Activity,即调用startPausingLocked函数暂停当前Acitivity
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, boolean dontWait) { if (mPausingActivity != null) { if (!mService.isSleeping()) { // Avoid recursion among check for sleep and complete pause during sleeping. // Because activity will be paused immediately after resume, just let pause // be completed by the order of activity paused from clients. completePauseLocked(false); } } // mResumedActivity 保存当前正现实的Activity函数首先把mResumedActivity保存在本地变量prev中。在上一步Step 10中,说到mResumedActivity就是Launcher,因此,这里把Launcher进程中的ApplicationThread对象取出来,通过它来通知Launcher这个Activity它要进入Paused状态了。当然,这里的prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity来通知Launcher进入Paused状态。 ActivityRecord prev = mResumedActivity; if (prev == null) { if (!resuming) { 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); } // 设置mPausingActivity为当前Activity 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; // 设置状态为PAUSING prev.task.touchActiveTime(); clearLaunchTime(prev); final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) { /// M: Add for launch time enhancement @{ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF, "amScreenCapture"); if (!prev.isHomeActivity()) { prev.updateThumbnailLocked(screenshotActivities(prev), null); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF); /// @} } stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); if (prev.app != null && prev.app.thread != null) { try { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, prev.userId, System.identityHashCode(prev), prev.shortComponentName); mService.updateUsageStats(prev, false); // 调用当前Activity所在进程的schedulePauseActivity函数参数prev.finishing表示prev所代表的Activity是否正在等待结束的Activity列表中,由于Laucher这个Activity还没结束,所以这里为false;参数prev.configChangeFlags表示哪些config发生了变化,这里我们不关心它的值。 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, dontWait); } catch (Exception e) { } // 获取WakeLock,以防止在Activity切换过程中掉电 if (!uiSleeping && !mService.isSleepingOrShuttingDown()) { mStackSupervisor.acquireLaunchWakelock(); } if (mPausingActivity != null) { // 暂停输入事件派发 if (!uiSleeping) { prev.pauseKeyDispatchingLocked(); } else if (DEBUG_PAUSE) { Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off"); } if (dontWait) { // If the caller said they don't want to wait for the pause, then complete // the pause now. completePauseLocked(false); return false; } else { // 设置PAUSE超时,时间为500ms Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); msg.obj = prev; prev.pauseTime = SystemClock.uptimeMillis(); mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); return true; } } else { if (!resuming) { mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null); } return false; } }
startPausingLocked将调用应用程序进程的schedulePauseActivity函数,并设置500ms的超时时间,所以应用进程需要尽快完成相关操作,和scheduleLaunchActivity一样,
schedulePauseActivity将向ActivityThread主线程发送PAUSE_ACTIVITY消息,最终该消息由handlePauseAcitivity来处理
Step 12. ApplicationThreadProxy.schedulePauseActivity
ApplicationThreadNative.java (frameworks\base\core\java\android\app)
public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(finished ? 1 : 0); data.writeInt(userLeaving ? 1 :0); data.writeInt(configChanges); data.writeInt(dontReport ? 1 : 0); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); }
这个函数通过Binder进程间通信机制进入到ApplicationThread.schedulePauseActivity函数中。
Step 13. ApplicationThread.schedulePauseActivity
public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, (userLeaving ? 1 : 0) | (dontReport ? 2 : 0), configChanges); }
这里调用的函数SendMessage是ActivityThread类的成员函数。
上面说到,这里的finished值为false,因此,SendMessage的第一个参数值为H.PAUSE_ACTIVITY,表示要暂停token所代表的Activity,即Launcher。
Step 14. ActivityThread.SendMessage
ActivityThread.java (frameworks\base\core\java\android\app)
private void sendMessage(int what, Object obj, int arg1, int arg2) { sendMessage(what, obj, arg1, arg2, false); } private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
这里首先将相关信息组装成一个msg,然后通过mH成员变量发送出去,mH的类型是H,继承于Handler类,是ActivityThread的内部类,因此,这个消息最后由H.handleMessage来处理。
Step 15. H.handleMessage
public void handleMessage(Message msg) { switch (msg.what) { case PAUSE_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2, (msg.arg1&2) != 0); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } }
这里调用ActivityThread.handlePauseActivity进一步操作,msg.obj是一个ActivityRecord对象的引用,它代表的是Launcher这个Activity。
Step 16. ActivityThread.handlePauseActivity
2、ActivityThread.java (frameworks\base\core\java\android\app)
private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { // 当Activity处于finishing状态时,finiished参数为true,不过在本例中该值为false ActivityClientRecord r = mActivities.get(token); if (r != null) { //调用Activity的onUserLeaving函数 if (userLeaving) { performUserLeavingActivity(r); } r.activity.mConfigChangeFlags |= configChanges; // 调用Activity的onPause函数 performPauseActivity(token, finished, r.isPreHoneycomb()); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { QueuedWork.waitToFinish(); } // Tell the activity manager we have paused. if (!dontReport) { try { // 调用AMS的activityPaused函数 ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } mSomeActivitiesChanged = true; } }
函数首先将Binder引用token转换成ActivityRecord的远程接口ActivityClientRecord,然后做了三个事情:1. 如果userLeaving为true,则通过调用performUserLeavingActivity函数来调用Activity.onUserLeaveHint通知Activity,用户要离开它了;2. 调用performPauseActivity函数来调用Activity.onPause函数,我们知道,在Activity的生命周期中,当它要让位于其它的Activity时,系统就会调用它的onPause函数;3. 它通知ActivityManagerService,这个Activity已经进入Paused状态了,ActivityManagerService现在可以完成未竟的事情,即启动MainActivity了。
Step 17. ActivityManagerProxy.activityPaused
ActivityManagerNative.java (frameworks\base\core\java\android\app)
public void activityPaused(IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); }
这里通过Binder进程间通信机制就进入到ActivityManagerService.activityPaused函数中去了。
Step 18. ActivityManagerService.activityPaused
ActivityManagerService.java (frameworks\base\services\core\java\com\android\server\am)
public final void activityPaused(IBinder token) { final long origId = Binder.clearCallingIdentity(); synchronized(this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { stack.activityPausedLocked(token, false); } } Binder.restoreCallingIdentity(origId); }
这里,又再次进入到ActivityStack类中,执行activityPaused函数。
Step 19. ActivityStack.activityPausedLocked
ActivityStack.java (frameworks\base\services\core\java\com\android\server\am)
final void activityPausedLocked(IBinder token, boolean timeout) { final ActivityRecord r = isInStackLocked(token); if (r != null) { // 从消息队列中撤销PAUSE_TIMEOUT_MSG消息 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); if (mPausingActivity == r) { // 完成本次pause操作 completePauseLocked(true); } else { // 设置ActivityRecotd状态 if (r.finishing && r.state == ActivityState.PAUSING) { finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false); } } /// M: activity state notifier @{ mService.notifyActivityState(r.packageName, r.getFocusAppPid(), r.realActivity.getShortClassName(), IActivityStateNotifier.ActivityState.Paused); /// @} } }
这里通过参数token在mHistory列表中得到ActivityRecord,从上面我们知道,这个ActivityRecord代表的是 Launcher这个Activity,而我们在Step 11中,把Launcher这个Activity的信息保存在mPausingActivity中,因此,这里mPausingActivity等于r, 于是,执行completePauseLocked操作。
Step 20. ActivityStack.completePauseLocked
3、ActivityStack.java (frameworks\base\services\core\java\com\android\server\am)
最后通过resumeTopActivitiesLocked来启动目标Acitivity
private void completePauseLocked(boolean resumeNext) { ActivityRecord prev = mPausingActivity; if (prev != null) { prev.state = ActivityState.PAUSED; if (prev.finishing) { prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false); } else if (prev.app != null) { if (prev.configDestroy) { destroyActivityLocked(prev, true, "pause-config"); } else if (!hasVisibleBehindActivity() || mService.isSleepingOrShuttingDown()) { // 将刚才被暂停的Activity保存到mStoppingActivities中 mStackSupervisor.mStoppingActivities.add(prev); if (mStackSupervisor.mStoppingActivities.size() > 3 || prev.frontOfTask && mTaskHistory.size() <= 1) { // 如果被暂停的Activity超过3个,则发送IDLE_NOW_MSG消息,该消息最终由我们前面介绍的activityIdleInternal处理 mStackSupervisor.scheduleIdleLocked(); } else { mStackSupervisor.checkReadyForSleepLocked(); } } } else { // 设置mPausingActivity为null prev = null; } // It is possible the activity was freezing the screen before it was paused. // In that case go ahead and remove the freeze this activity has on the screen // since it is no longer visible. prev.stopFreezingScreenLocked(true /*force*/); mPausingActivity = null; } if (resumeNext) { final ActivityStack topStack = mStackSupervisor.getFocusedStack(); if (!mService.isSleepingOrShuttingDown()) { // resumeTopActivitiesLocked将启动目标activity mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null); } else { } } }
函数首先把mPausingActivity变量清空,因为现在不需要它了,然后调用resumeTopActivityLokced进一步操作,它传入的参数即为代表Launcher这个Activity的ActivityRecord。
Step 21. ActivityStack.resumeTopActivityLokced
通过上面的Step 9,我们知道,当前在堆栈顶端的Activity为我们即将要启动的MainActivity,这里通过调用topRunningActivityLocked将它取回来,保存在next变量中。之前最后一个Resumed状态的Activity,即Launcher,到了这里已经处于Paused状态了,因此,mResumedActivity为null。最后一个处于Paused状态的Activity为Launcher,因此,这里的mLastPausedActivity就为Launcher。前面我们为MainActivity创建了ActivityRecord后,它的app域一直保持为null。有了这些信息后,上面这段代码就容易理解了,它最终调用startSpecificActivityLocked进行下一步操作。
Step 22. ActivityStackSupervisor.startSpecificActivityLocked
ActivityStackSupervisor.java (\frameworks\base\services\core\java\com\android\server\am)
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // 注意,这里由于是第一次启动应用程序的Activity,所以下面语句: ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); /* 取回来的app为null。在Activity应用程序中的AndroidManifest.xml配置文件中, 我们没有指定Application标签的process属性,系统就会默认使用package的名称, 这里就是"shy.luo.activity"了。每一个应用程序都有自己的uid,因此,这里uid + process的组合就 可以为每一个应用程序创建一个ProcessRecord。当然,我们可以配置两个应用程序具有相同的uid和package, 或者在AndroidManifest.xml配置文件的application标签或者activity标签中显式指定相同的process属性值, 这样,不同的应用程序也可以在同一个进程中启动。 */ if (app != null && app.thread != null) { try { if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
Step 23. ActivityManagerService.startProcessLocked
final ProcessRecord startProcessLocked(......) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); ...... String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null; if (app == null) { checkTime(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; checkTime(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: added package to existing proc"); } ...... startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); checkTime(startTime, "startProcess: done starting proc!"); return (app.pid != 0) ? app : null; } }
这里再次检查是否已经有以process + uid命名的进程存在,在我们这个情景中,返回值app为null,因此,后面会创建一个ProcessRecord,并存保存在成员变量mProcessNames中,最后,调用另一个startProcessLocked函数进一步操作:
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); }
这里主要是调用Process.start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数,这就是为什么我们前面说每一个应用程序都有一个ActivityThread实例来对应的原因。
4、根据前面的介绍,此次目标Acitivity将走完onCreate、onStart和onResume流程,但是被暂停的Activity才刚走完onPause流程,那么什么时候调用onStop?
答案就在activityIdelInternal中,他将成为mStopingActivities中的成员调用stopActivityLocked函数
final void stopActivityLocked(ActivityRecord r) { if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { if (!mService.isSleeping()) { if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "stop-no-history", false)) { // Activity was finished, no need to continue trying to schedule stop. adjustFocusedActivityLocked(r, "stopActivityFinished"); r.resumeKeyDispatchingLocked(); return; } } else { } } } if (r.app != null && r.app.thread != null) { adjustFocusedActivityLocked(r, "stopActivity"); r.resumeKeyDispatchingLocked(); try { r.stopped = false; // 设置STOPPING状态,并调用对应的scheduleStopActivity函数 r.state = ActivityState.STOPPING; r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); if (mService.isSleepingOrShuttingDown()) { r.setSleeping(true); } Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); } catch (Exception e) { } } }
5、对应进程scheduleStopActivity函数将根据visible的情况,向主线程消息循环发送H.STOP_ACTIVITY_HIDE和 H.STOP_ACTIVITY_SHOW 消息。
不论哪种情况,最终都由handleStopActivity来处理。
private void handleStopActivity(IBinder token, boolean show, int configChanges) { ActivityClientRecord r = mActivities.get(token); r.activity.mConfigChangeFlags |= configChanges; StopInfo info = new StopInfo(); // 调用Activity的onStop函数 performStopActivityInner(r, info, show, true); updateVisibility(r, show); info.activity = r; info.state = r.state; info.persistentState = r.persistentState; mH.post(info); mSomeActivitiesChanged = true; }
Step 24. ActivityThread.main
一、应用进程创建及初始化
1、ActivityThread.java (frameworks\base\core\java\android\app)
public static void main(String[] args) { logAppLaunchTime(TAG, "ActivityThread is created"); /// M: It's for debugging App Launch time SamplingProfilerIntegration.start(); // 和调试及strictMode有关 CloseGuard.setEnabled(false); Environment.initForCurrentUser(); AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); // 设置进程名为"<pre-initialized>" Process.setArgV0("<pre-initialized>"); // 准备主线程消息循环 Looper.prepareMainLooper(); // 创建一个ActivityThread对象 ActivityThread thread = new ActivityThread(); // 调用attach函数,注意其参数数值false thread.attach(false); Looper.loop(); // 进入主线程消息循环 }
在main函数中内部将创建一个消息循环Loop,接着调用ActivityThread的attach函数,最终将主线程加入消息循环。
2、我们在分析AMS的setSystemProcess是曾分析过ActivityThread的attach函数,那时传入的参数值为true,现在看看设置为false的情况
ActivityThread.java (frameworks\base\core\java\android\app)
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); // 设置在DDMS中看到的本进程的名字为"<pre-initialized>" android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); // 设置RuntimeInit的mApplicationObject参数,后续会介绍RuntimeInit类 RuntimeInit.setApplicationObject(mAppThread.asBinder()); // 获取和AMS交互的Binder客户端 final IActivityManager mgr = ActivityManagerNative.getDefault(); try { // 调用AMS的attachApplication,mAppThread为ApplicationThread类型,它是应用进程和AMS交互的接口 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3 * dalvikMax) / 4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax / 1024) + " total=" + (runtime.totalMemory() / 1024) + " used=" + (dalvikUsed / 1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else {// system process处理 } }
这个函数在进程中创建一个ActivityThread实例,然后调用它的attach函数,接着就进入消息循环了,直到最后进程退出。 函数attach最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象,它的作用是用来进行进程间通信的。
Step 25. ActivityManagerProxy.attachApplication
public void attachApplication(IApplicationThread app) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(app.asBinder()); mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); }
这里通过Binder驱动程序,最后进入ActivityManagerService的attachApplication函数中。
Step 26. ActivityManagerService.attachApplication
@Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); // 这里将操作转发给attachApplicationLocked函数。 attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } }
Step 27. ActivityManagerService.attachApplicationLocked
3、我们知道,AMS创建一个应用进程后,会设置一个超时时间(一般是10秒),如果超过这个时间,应用进程汗没有和AMS交互,则断定该进程创建失败。
所以,应用进程启动后,需要尽快和AMS交互,及调用AMS的attachApplication函数。在该函数内部将调用attachApplicationLocked,所以此处直接分析attachApplicationLocked,
先看其第一阶段工作。
第一阶段工作比较简单:
1)设置代表该应用进程ProcessRecord对象的一些成员变量,如用于和应用进程交互的thread对象、进程调度优先级及oom_adj的值等。
2)从消息队列中撤销PROC_START_TIMEOUT_MSG.
至此,该阶段启动成功,但是这一阶段的工作仅针对进程本身(如设置调度优先级,oom_adj等),还没有涉及和Activity启动相关的内容,这部分工作将在第二阶段完成。
第二阶段: 工作主要是为调用Application的bindApplication做准备
/*正如我们在前面分析时提到的,刚创建的这个进程并不知道自己的历史使命是什么,甚至连自己的进程名都不知道,只能设为<pre-initiallzed>。其实,Android应用进程的历史使命是AMS在其启动后才赋予它的,这一点和我们理解的一般意义上的进程不太一样。根据之前的介绍,Andorid的组件应该运行在Anroid运行环境中。从OS角度来说,该运行环境需要和一个进程绑定。所以,创建应用进程这一步只是创建一个能运行Android运行环境的容器,bindApplication的功能就是创建并初始化位于该进程的Anroid运行环境*/public final void bindApplication()
第三阶段:通知应用进程Activity和Service等组件,其中用于启动Activity的函数是ActivityStack realStartActivityLocked
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { // 第一阶段 此pid代表调用进程pid ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); // 根据pid查找对应的ProcessRecord对象 } } else { app = null; } /*如果该应用进程由AMS启动,则它一定在AMS中有对应的ProcessRecord,读者可以回顾前面创建 应用进程的代码:AMS先创建了一个ProcessRecord对象,然后才发命令给Zygote。 如果此处app为null,则表示AMS没有该进程的记录,故需要“杀死”它 * */ if (app == null) { EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid); if (pid > 0 && pid != MY_PID) { // 如果pid大于零,且不是system_server进程,则“杀死”process Process.killProcessQuiet(pid); //TODO: killProcessGroup(app.info.uid, pid); } else { try { // 调用ApplicationThread的scheduleExit函数,应用进程完成处理工作后,将退出运行 thread.scheduleExit(); } catch (Exception e) { // Ignore exceptions. } } return false; } /* 判断app的Thread是否为空,如果不为空,则表示该ProcessRecord对象还未和一个应用进程绑定。 注意,app是根据pid查找到的,如果旧的进程没有被“杀死”,则系统不会重用该pid */ if (app.thread != null) { handleAppDiedLocked(app, true, true); } final String processName = app.processName; try { /* 创建一个应用进程“讣告”接受对象。当应用进程退出时,该对象的binderDied将被调用。 这样,AMS就能做相应处理。binderDied函数将在另外一个线程中执行,其内部也会调用 handleAppDiedLocked。假如用户在binderDied被调用之前又启动一个进程, 那么就会出现以上代码中app.thread不为null的情况。这是多线程环境中常出现的情况 */ AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); return false; } // 设置该进程的调度优先级和oom_adj相关的成员 app.makeActive(thread, mProcessStats); app.curAdj = app.setAdj = -100; app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT; app.forcingToForeground = null; updateProcessForegroundLocked(app, false, false); app.hasShownUi = false; app.debugging = false; app.cached = false; app.killedByAm = false; // 启动成功,从消息队列中撤销PROC_START_TIMEOUT_MSG消息 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); // 第二阶段 systemserver 早就启动完毕,所以normalMode为true boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); // 该函数内部将查询(根据进程名,uid确定)PKMS以获取需要运行在该进程中的ContentProvider List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; try { int testMode = IApplicationThread.DEBUG_OFF; if (mDebugApp != null && mDebugApp.equals(processName)) { // 处理debug选项 testMode = mWaitForDebugger ? IApplicationThread.DEBUG_WAIT : IApplicationThread.DEBUG_ON; app.debugging = true; if (mDebugTransient) { mDebugApp = mOrigDebugApp; mWaitForDebugger = mOrigWaitForDebugger; } } // 处理profile String profileFile = app.instrumentationProfileFile; ParcelFileDescriptor profileFd = null; int samplingInterval = 0; boolean profileAutoStop = false; if (mProfileApp != null && mProfileApp.equals(processName)) { mProfileProc = app; profileFile = mProfileFile; profileFd = mProfileFd; samplingInterval = mSamplingInterval; profileAutoStop = mAutoStopProfiler; } boolean enableOpenGlTrace = false; if (mOpenGlTraceApp != null && mOpenGlTraceApp.equals(processName)) { enableOpenGlTrace = true; mOpenGlTraceApp = null; } // If the app is being launched for restore or full backup, set it up specially boolean isRestrictedBackupMode = false; if (mBackupTarget != null && mBackupAppName.equals(processName)) { isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE) || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL) || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL); } // dex化对应的apk包 ensurePackageDexOpt(app.instrumentationInfo != null ? app.instrumentationInfo.packageName : app.info.packageName); // 如果设置了设置了Instrumentation类,该类所在的package也需要dex化 if (app.instrumentationClass != null) { ensurePackageDexOpt(app.instrumentationClass.getPackageName()); } ApplicationInfo appInfo = app.instrumentationInfo != null ? app.instrumentationInfo : app.info; // 查询该Application使用的CompatibilityInfo app.compat = compatibilityInfoForPackageLocked(appInfo); if (profileFd != null) { // 用于记录性能文件 profileFd = profileFd.dup(); } ProfilerInfo profilerInfo = profileFile == null ? null : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop); // 通过ApplicationThread和应用进程交互,调用其bindApplication函数 thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); // updateLruProcessLocked(app, false, null); // 记录两个时间 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); startProcessLocked(app, "bind fail", processName); return false; } // 从mPersistentStartingProcesses和mProcessesOnHold中删除相关信息 mPersistentStartingProcesses.remove(app); mProcessesOnHold.remove(app); boolean badApp = false; boolean didSomething = false; // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { badApp = true; } } // Check if a next-broadcast receiver is in this process... if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { badApp = true; } } // Check whether the next backup agent is in this process... if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) { try { thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e); badApp = true; } } if (badApp) { /* 如果以上一个组件启动错误,则设置badApp为true。此处将调用handleAppDiedLocked进行处理 */ app.kill("error during init", true); handleAppDiedLocked(app, false, true); return false; } /* 调整进程oom_adj值,didsomething表示在以上流程中是否启动了Activity或其他组件。 如果启动了任一组件,则didsomething为true,读者以后知道,这里的启动只是向应用进程发出对应的指令, 客户端进程是否成功处理还是未知数。基于这种考虑,此处不宜马上调节进程的oom_adj. 读者可简单的把oom_adj看做一种优先级。如果一个应用进程没有运作任何组件,那么当内存出现不足时, 该进程是最先被系统“杀死”的。反之,如果一个应用进程运行的组建越多,那么它就越不易被系统“杀死” 以回收内存。updateOomAdjLocked就是根据该进程中的组件的情况对应调节进程的oom_adj值 */ if (!didSomething) { updateOomAdjLocked(); } return true; }
4、bindApplication为应用程序绑定一个Application
ActivityThread.java (frameworks\base\core\java\android\app)
public final void bindApplication(......) { if (services != null) { // 保存AMS传递过来的系统service信息 // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } // 向主线程消息队列添加SET_CORE_SETTINGS消息 setCoreSettings(coreSettings); IPackageManager pm = getPackageManager(); android.content.pm.PackageInfo pi = null; try { pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { } if (pi != null) { boolean sharedUserIdSet = (pi.sharedUserId != null); boolean processNameNotDefault = (pi.applicationInfo != null && !appInfo.packageName.equals(pi.applicationInfo.processName)); boolean sharable = (sharedUserIdSet || processNameNotDefault); // Tell the VMRuntime about the application, unless it is shared // inside a process. if (!sharable) { VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, appInfo.processName); } } // 创建AppBindData对象,用于保存一些参数 AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); }
5、有以上代码可知,ApplicationThread接收到来之AMS的指令后,会将指令中的参数封装到一个数据结构中,然后通过发送消息的方式转交给主线程去处理。
BIND_APPLICATION最终将由handleBindApplication函数处理。该函数并不复杂,但是其中有些点是值得关注的,这些点主要是初始化应用进程的一些参数。
其中最主要的有两点:
1)创建一个Application对象,该对象是本进程中运行的第一个Application
2)如果该进程Application有ContentProvider,则应安装他们
3)ContentProvider的创建于bindApplication函数中,其时机早于其他组建的创建
private void handleBindApplication(AppBindData data) { mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); // 初始化性能统计对象 mProfiler = new Profiler(); if (data.initProfilerInfo != null) { mProfiler.profileFile = data.initProfilerInfo.profileFile; mProfiler.profileFd = data.initProfilerInfo.profileFd; mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; } logAppLaunchTime(TAG, "handleBindApplication is called"); /// M: It's for debugging App Launch time // 设置进程名,从此,之前那个名为“<pre_initialized>”的进程终于有了正式的名字 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); // 启动性能统计 if (mProfiler.profileFd != null) { mProfiler.startProfiling(); } // 如果目标SDK版本小于12,则设置AsyncTask使用pool executor,否则使用 // serialized executor。这些executor涉及java concurrent 类 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } Message.updateCheckRecycle(data.appInfo.targetSdkVersion); /*设置时间 */ TimeZone.setDefault(null); /* * 设置语言 */ Locale.setDefault(data.config.locale); /*设置资源及兼容模式 */ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi; applyCompatConfiguration(mCurDefaultDisplayDpi); // 根据传递过来的ApplicationInfo创建一个对应的LoadApk对象 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); /** * 对于系统APK,如果当前系统为userdebug/eng版,则需要使能dropbox的日志记录 */ if ((data.appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } updateDefaultDensity(); final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); if (!Process.isIsolated()) { final File cacheDir = appContext.getCacheDir(); if (cacheDir != null) { // Provide a usable directory for temporary files System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); } else { Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property due to missing cache directory"); } // Use codeCacheDir to store generated/compiled graphics code final File codeCacheDir = appContext.getCodeCacheDir(); if (codeCacheDir != null) { setupGraphicsSupport(data.info, codeCacheDir); } else { Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory"); } } final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); DateFormat.set24HourTimePref(is24Hr); View.mDebugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; /** * For system applications on userdebug/eng builds, log stack * traces of disk and network access to dropbox for analysis. */ if ((data.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { StrictMode.conditionallyEnableDebugLogging(); } /** * Initialize the default http proxy in this process for the reasons we set the time zone. */ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { // In pre-boot mode (doing initial launch to collect password), not // all system is up. This includes the connectivity service, so don't // crash if we can't get it. IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { // 设置HTTP代理消息 final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo); } catch (RemoteException e) { } } if (data.instrumentationName != null) { // 在正常情况下此条件不满足 } else { // 创建Instrumentation对象,在正常情况下都在这个条件下执行 mInstrumentation = new Instrumentation(); } // 如果package中声明了FLAG_LARGE_HEAP,则可跳过虚拟机的内存限制,放心使用内存 if ((data.appInfo.flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } // Allow disk access during application and provider setup. This could // block processing ordered broadcasts, but later processing would // probably end up doing the same disk access. final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { //创建一个Application,data.info为LoadedApk类型,在其内部会通过Java反射机制 // 创建一个在该APK AndroidManifest.xml中声明的Application对象 Application app = data.info.makeApplication(data.restrictedBackupMode, null); // mInitialApplication保存该进程中第一个创建的Application mInitialApplication = app; // 安装package中携带的contentprovider if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10 * 1000); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { // 调用Application的onCraeate函数,做一些初始化工作 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { StrictMode.setThreadPolicy(savedPolicy); } }
Step 28. ActivityStack.realStartActivityLocked
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { ...... // r,是一个ActivityRecord类型的Binder对象,用来作来这个Activity的token值。 r.app = app; ...... int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } ..... try { if (app.thread == null) { throw new RemoteException(); } List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { results = r.results; newIntents = r.newIntents; } // app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); ...... } catch (RemoteException e) { } ...... return true; }
二、ActivityStack realStartActivityLocked 分析
AMS调用完bindApplication后,将通过realStartActivityLocked启动Activity。在此之前,要创建完应用进程并初始化Android运行环境
6.0的代码中已经没有该方法,但是里面包含了两个关键函数,分别是:scheduleLaunchActivity和completeResumeLocked。其中,
scheduleLaunchActivity用于和应用进程交互,通知它启动目标Activity。而completeResumeLocked将继续AMS的处理流程。
Step 29. ApplicationThreadProxy.scheduleLaunchActivity
public final void scheduleLaunchActivity(......) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data, 0); data.writeStrongBinder(token); data.writeInt(ident); info.writeToParcel(data, 0); curConfig.writeToParcel(data, 0); if (overrideConfig != null) { data.writeInt(1); overrideConfig.writeToParcel(data, 0); } else { data.writeInt(0); } compatInfo.writeToParcel(data, 0); data.writeString(referrer); data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null); data.writeInt(procState); data.writeBundle(state); data.writePersistableBundle(persistentState); data.writeTypedList(pendingResults); data.writeTypedList(pendingNewIntents); data.writeInt(notResumed ? 1 : 0); data.writeInt(isForward ? 1 : 0); if (profilerInfo != null) { data.writeInt(1); profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); }
这个函数最终通过Binder驱动程序进入到ApplicationThread的scheduleLaunchActivity函数中。
Step 30. ActivityThread.scheduleLaunchActivity
1、ActivityThread.java (frameworks\base\core\java\android\app)
public final void scheduleLaunchActivity(......) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); ...... // 保存AMS发送过来的参数信息 // 向主线程发送消息,该消息的处理在handleLaunchActivity中进行 sendMessage(H.LAUNCH_ACTIVITY, r); }
Step 31. ActivityThread.SendMessage
2、frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) { switch (msg.what) { case LAUNCH_ACTIVITY: { final ActivityClientRecord r = (ActivityClientRecord) msg.obj; // 根据ApplicationInfo得到对应的PakcageInfo r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); // 调用handleLaunchActivity处理 handleLaunchActivity(r, null); } break;
Step 32. H.handleMessage
Step 33. ActivityThread.handleLaunchActivity
Step 34. ActivityThread.performLaunchActivity
Step 35. MainActivity.onCreate
整个应用程序的启动过程要执行很多步骤,但是整体来看,主要分为以下五个阶段:
一. Step1 - Step 11:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity; 二. Step 12 - Step 16:ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态; 三. Step 17 - Step 24:Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行; 四. Step 25 - Step 27:ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信; 五. Step 28 - Step 35:ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。 这样,应用程序的启动过程就介绍完了,它实质上是启动应用程序的默认Activity,
- Android 6.0 AMS分析的第二条线:以Launcher启动一个Activity为例,分析应用进程的创建、Activity的启动,以及他们和AMS之间的交互等知识;
- Android ActivityManagerService(AMS)的启动分析
- Android ActivityManagerService(AMS)的启动分析
- AMS与Activity的交互
- Ams分析之activity启动
- 跟着Innost理解下Activity 的启动以及与AMS的交互
- Android 6.0 AMS分析的第一条线:SystemServer中的AMS的调用轨迹
- ActivityManagerService分析一:AMS的启动
- ActivityManagerService分析一:AMS的启动
- ActivityManagerService分析一:AMS的启动
- Android系统篇之----解读AMS远端服务调用机制以及Activity的启动流程
- Android7.0点击Launcher的AMS应用启动流程
- Android O Framework架构分析(一):以AMS视角看Activity启动过程
- Android ActivityManagerService(AMS)的Activity管理
- Android ActivityManagerService(AMS)的Activity管理
- AMS 启动的时候杀掉所有进程
- AMS对Activity的管理
- AMS启动Activity过程
- TweenAnimation、布间动画、和炸月球小项目
- (java题目第3讲)ACM(http://blog.csdn.net/kuhuaishuxia/article/details/52254209)
- OC-XIB使用&UITextField
- UIAlertController:supportedInterfaceOrientations was invoked recursively
- 设计模式之迭代器模式---以JDK源码为例
- Android 6.0 AMS分析的第二条线:以Launcher启动一个Activity为例,分析应用进程的创建、Activity的启动,以及他们和AMS之间的交互等知识;
- linux下各种小命令
- LeetCode-ZigZag Conversion
- Unity3D —— Socket通信(C#)
- Linux分页机制之分页机制的演变--Linux内存管理(七)
- Android下bluedroid、bluetooth apk介绍
- 深度卷积神经网络.cnn权值网络与cnn权值矩阵的创新思路
- [完]Python,解决Matplotlib制图时的中文问题
- synchronized与static synchronized