因为工作中经常要用到应用的启动流程,而网上和书本上大部分都是Android5.0和6.0的文章,有些部分Android7.0又做了修改,故本篇文章主要是整理以往大牛们在Android5.0、Android6.0的基础上对Android7.0点击Launcher到应用启动完成的一个大体流程,用于工作和大家参考,如有不足之处,欢迎指正。
当点击桌面的应用图标后,会触发Launcher3的Launcher.java中的onClick(View v)方法执行,一系列判断后将点击的View作为参数,调用startAppShortcutOrInfoActivity(v),
在startAppShortcutOrInfoActivity(v)中,根据传入参数View v的v.getTag()方法得到被点击应用图标的ShortcutInfo,然后得到Intent数据。
通过final Intent intent = ((ShortcutInfo) tag).intent语句得到数据,有了一个应用的Intent就可以启动一个应用了。
public void onClick(View v) {
...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if (v == mAllAppsButton) {
onClickAllAppsButton(v);
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
}
}
}
@Thunk void startAppShortcutOrInfoActivity(View v) {
Object tag = v.getTag();
final ShortcutInfo shortcut;
final Intent intent;
if (tag instanceof ShortcutInfo) {
shortcut = (ShortcutInfo) tag;
intent = shortcut.intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
} else if (tag instanceof AppInfo) {
shortcut = null;
intent = ((AppInfo) tag).intent;
} else {
throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
}
boolean success = startActivitySafely(v, intent, tag);
...
}
接着调用了startActivitySafely(v, intent, tag),这里调用了startActivity(v, intent, tag),参数中含有intent,intent中包含了action、category等信息。
public boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
...
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
if (v instanceof TextView){
return success;
}
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;
}
Launcher继承于Activity类,在startActivity(v, intent, tag)中调用了重写的startActivity(Intent intent, @Nullable Bundle options),因此,这里就调用了Activity.startActivity方法;
在startActivity(intent, optsBundle)中参数optsBundle包含了应用启动动画的坐标,width和height。
private boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
if (user.equals(UserHandleCompat.myUserHandle())) {
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
try {
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
.penaltyLog().build());
startActivity(intent, optsBundle);
} finally {
StrictMode.setVmPolicy(oldPolicy);
}
}
...
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
在Activity.startActivity方法中又调用了Activity.startActivityForResult方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...
}
...
}
这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在Instrumentation.java文件中,它用来监控应用程序和系统的交互。
这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程。这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,ActivityManagerService会使用它来和ActivityThread来进行进程间通信,mMainThread代表的是Launcher应用程序运行的进程。
这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
接下来调用了Instrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options)
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
可以看出,启动Activity真正的实现由ActivityManagerNative.getDefault()的.startActivity方法执行。
这里的ActivityManagerNative.getDefault()返回的是ActivityManagerService的一个代理类ActivityManagerProxy。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
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);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
这里的参数比较多,我们先整理一下。从上面的调用可以知道,这里的参数resolvedType、grantedUriPermissions和resultWho均为null;参数caller为ApplicationThread类型的Binder实体;参数resultTo为一个Binder实体的远程接口,我们先不关注它;参数grantedMode为0,我们也先不关注它;参数requestCode为-1;参数onlyIfNeeded和debug均空false。
由于ActivityManagerProxy是一个代理类,上面是通过IPC的Binder联系到ActivityManagerService,最后会调用ActivityManagerService的startActivity方法。
AMS(ActivityManagerServie)中提供了几个借口来启动Activity,但是,他们都会调用到ActivityStarter类的startActivityMayWait()方法,Android7.0以前是ActivityStackSupervisor类;
接下来以上面调用的startActivity方法继续分析,startActivity方法调用了startActivityAsUser方法,代码如下
@Override
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
...
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
// 获取启动的Activity信息
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
if (outResult != null) { // 如果需要返回结果
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
mSupervisor.mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait(); // 等待应用进程中Activity的启动完成
} catch (InterruptedException e) {
}
} while (outResult.result != START_TASK_TO_FRONT
&& !outResult.timeout && outResult.who == null);
if (outResult.result == START_TASK_TO_FRONT) {
res = START_TASK_TO_FRONT;
}
}
...
return res;
}
startActivityMayWait()首先调用了resolveActivity()方法来获取需要启动的Activity的信息,保存在aInfo中。resolveActivity()方法通过调用PMS(PackageMangerServie)的resolveIntent()方法
来获取Activity的信息。得到Activity信息后,继续调用startActivityLocked()方法来继续启动Activity。如果启动的Activity的应用需要返回结果,则调用mService的wait()方法挂起线程等待启动的结果。
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId) {
return resolveIntent(intent, resolvedType, userId, 0);
}
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
try {
return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | flags
| ActivityManagerService.STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
}
return null;
}
以下是startActivityLocked()方法部分:
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller); // 得到调用进程的信息
...
}
... // 错误检查
// 检查防火墙是否屏蔽了该Intent
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
resultRecord, resultStack, options);
if (abort) Slog.d(TAG,"startActivityLocked checkStartAnyActivityPermission result:false");
boolean firewallCheck = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
if (firewallCheck) Slog.d(TAG,"startActivityLocked mIntentFirewall.checkStartActivity result:false");
abort |= firewallCheck;
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
// 将Activity启动的消息通知监听系统Activity变动的接口IActivityController
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
...
if (abort) {
...
return START_SUCCESS; // 如果前面将abort置为true,则返回
}
...
// 创建ActivityRecord对象
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
...
// 取得当前接收用户输入的ActivityStack
final ActivityStack stack = mSupervisor.mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
// 如果需要经常进程切换,检查是否有权限切换
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
PendingActivityLaunch pal = new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp);
// 现在不能切换,把Activity的信息放入mPendingActivityLaunches列表
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
Slog.d(TAG,"startActivityLocked return START_SWITCHES_CANCELED");
return ActivityManager.START_SWITCHES_CANCELED; // 退出
}
}
if (mService.mDidAppSwitch) {
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true; // 打开开关,允许进程间切换
}
doPendingActivityLaunchesLocked(false); // 启动挂起等待的Activity
try {
mService.mWindowManager.deferSurfaceLayout();
// 继续启动当前的Activity
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
Slog.d(TAG,"startActivityUncheckedLocked result : " + err);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
startActivityLocked()方法首先进行了各种错误检查,以及Intent防火墙是否屏蔽了该Intent。Intent防火墙的规则是通过/data/system/ifw目录下的文件设置的,可以让系统禁止使用某些Intent。
完成所有检查后,startActivityLocked()方法创建了一个ActivityRecord对象,并通过mSupervisor.mFocusedStack来得到当前具有用户输入焦点的ActivityStack。接下来检查启动Activity是否会引起进程切换,如果需要切换,还要检查Android系统目前是否允许切换。比如,位于通话界面打电话时,可以调用AMS的stopAppSwitches()接口来禁止切换进程,电话结束后再调用resumeAppSwitches()接口恢复切换。如果系统不允许进程切换,只能把需要启动的Activity的信息保存在mPendingActivityLaunches变量中,然后返回。
如果允许进程切换,这时要调用doPendingActivityLaunchesLocked()方法先处理所有pending状态的Activity,然后再调用startActivityUnchecked()方法继续处理当前的Activity。处理pending状态的Activity也是调用startActivityUnchecked()方法,代码如下:
final void doPendingActivityLaunchesLocked(boolean doResume) {
while (!mPendingActivityLaunches.isEmpty()) {
final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
try {
final int result = startActivityUnchecked(
pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
postStartActivityUncheckedProcessing(
pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
mTargetStack);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
}
}
}
接下来调用了startActivityUnchecked(),这个方法主要是通过判断Intent的标志和Activity的属性来确定Activity的Task,方法中找到包含Activity的Task后,调用startActivityLocked()方法继续启动:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
// 重置当前类的成员变量;保存当前准备启动的Activity;Activity启动时对Intent的flag进行判断
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
// 为启动的Activity匹配task,若没有可以使用的,则创建一个
computeLaunchingTaskFlags();
// 启动的Activity是否需要携带FLAG_ACTIVITY_NEW_TASK标志,是否需要新建一个Task对象
computeSourceStack();
... // task中Activity的复用
// 决定是否为待启动的Activity创建对应的Task,同时将Activity和Task关联起来
...
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
if (!mLaunchTaskBehind) {
mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
}
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
}
...
return START_SUCCESS;
}
ActivityStack类的startActivityLocked()方法将ActivityRecord对象加入到Task顶部,同时把Task也放到MHistoryStack列表的顶部,同时这里也调用了WMS(WindowManagerServie)的方法来处理Activity的显示和切换的动画。最后startActivityUnchecked()方法通过mSupervisor对象的resumeFocusedStackTopActivityLocked()方法来显示位于Task栈顶的Activity。
以下是ActivityStack类的startActivityLocked()方法:
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
insertTaskAtTop(rTask, r); // 如果是新Task,把它放到顶部
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
if (!newTask) { // 如果不需要启动新的Task
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
continue;
}
if (task == r.task) {
if (!startIt) {
...
return; // 在startIt变为false后,退出
}
break; // 找到了Task,跳出循环
} else if (task.numFullscreen > 0) {
startIt = false; // 如果排在前面的Task有全屏的应用,例如播放器,设置为false
}
}
}
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}
task = r.task;
task.addActivityToTop(r); // 把Activity放到找到的Task的顶部
task.setFrontOfTask(); // 把Task放到Task列表的顶部
r.putInHistory();
if (!isHomeStack() || numActivities() > 0) {
// 如果不是Home应用的Stack或者Stack中有Activity,下面省略的一段代码都在调用
// WMS中的方法准备绘制Activity以及切换Activity动画
...
} else {
mWindowManager.prepareAppTransition(newTask
? r.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN
: TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
...
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
}
ActivityStarter类的resumeFocusedStackTopActivityLocked()方法主要的作用的将位于栈顶的Activity显示出来,在该方法中调用了ActivityStack类的resumeTopActivityUncheckedLocked()方法,这个方法又调用了内部方法resumeTopActivityInnerLocked():
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
final ActivityRecord next = topRunningActivityLocked(); // next表示要启动的Activity
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// 如果当前Task没有Activity,显示Home Activity
final String reason = "noMoreActivities";
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
mStackSupervisor.getFocusedStack(), prev, null);
}
ActivityOptions.abort(options);
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
...
return false; // 如果当前的Activity就是要启动的Activity,直接返回
}
final TaskRecord nextTask = next.task;
...
if (mService.isSleepingOrShuttingDownLocked()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
...
return false; // 如果系统正准备休眠或关闭,直接退出
}
if (!mService.mUserController.hasStartedUserState(next.userId)) {
...
return false; // 检查用户Id,为null则退出
}
// 将Activity从Stopping、GoingToSleep、WaitingVisible等队列中移除
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
if (!mStackSupervisor.allPausedActivitiesComplete()) {
return false; // 如果系统还有暂停的Activity,先退出
}
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
// 暂停后台的Activity
final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
// 暂停当前的Activity
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
} else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
...
return true; // 如果系统还有正在暂停的Activity,先退出
}
...
if (prev != null && prev != next) {
if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
&& next != null && !next.nowVisible) {
// 如果Activity还不可见,把前一个Activity加入mWaitingVisibleActivities列表
mStackSupervisor.mWaitingVisibleActivities.add(prev);
} else {
// 如果Activity已经是visible状态,把前一个Activity隐藏起来
if (prev.finishing) {
mWindowManager.setAppVisibility(prev.appToken, false);
}
}
}
...
boolean anim = true;
... // 调用WMS方法来处理Activity显示
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
...
if (!next.visible || next.stopped || lastActivityTranslucent) {
// 如果Activity所在的应用已经存在,只需要把Activity显示出来
mWindowManager.setAppVisibility(next.appToken, true);
}
...
if (next.newIntents != null) {
// 如果前面介绍的几种重启Activity情况,先调用应用的onNewIntent
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
// 调用应用进程Activity的onResume
...
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
...
// 如果Activity所在的应用还没启动,先启动应用
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
resumeTopActivityInnerLocked()方法比较长,整体的逻辑还是比较清晰的。如果Activity所在的应用已经启动,将会调用应用进程的scheduleResumeActivity()方法,最终会导致应用中的Activity对象的onResume()方法执行。如果应用还没有启动,或者刚启动,则调用startSpecificActivityLocked()方法继续处理。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (r.task != null && r.task.stack != null) {
r.task.stack.setLaunchTime(r);
}
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
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);
}
startSpecificActivityLocked()方法中如果发现应用进程没有启动,则调用startProcessLocked()方法来启动进程,否则调用realStartActivityLocked()方法继续执行,realStartActivityLocked()方法中调用了应用进程中的scheduleLaunchActivity()方法。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
...
}
scheduleLaunchActivity()方法将会调用Activity类的onCreate方法。
mService的startProcessLocked()方法用来启动进程,然后它又调用了Process类的静态方法start()方法来启动新进程。应用进程fork出来后将调用ActivityThread的main()方法:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser(); // 初始化应用中需要使用的系统路径
EventLogger.setReporter(new EventLoggingReporter());
// 为应用设置当前用户的CA证书保存位置
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>"); // 设置进程名称
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread(); // 创建ActivityThread对象
thread.attach(false); // 使用参数false调用attach
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler(); // 保证主线程的Handler
}
Looper.loop(); // 进入消息循环
throw new RuntimeException("Main thread loop unexpectedly exited");
}
main()方法主要是初始化环境,然后让线程进入消息循环。在进行消息循环前,main()方法创建了ActivityThread对象,并使用参数false调用了它的attach()方法:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
// 把ApplicationThread对象放到RuntimeInit中
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread); 调用AMS的attachApplication()方法
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {
...
}
}
attach()方法中当参数system的值为false主要做了两件事,一是调用setApplicationObject()方法把对象mAppThread放到了RuntimeInit类中的静态变量MApplicationOBject中。
public static final void setApplicationObject(IBinder app) {
mApplicationObject = app;
}
mAppThread的类型是ApplicationThread,它是ApplicationThread的成员变量,定义和初始化如下:
final ApplicationThread mAppThread = new ApplicationThread();
第二件事是调用AMS的attachApplication()方法,同时将mAppThread作为参数传递到了AMS中,这样AMS就能通过它来调用应用的接口了。
attachApplication()方法只是调用了内部的attachApplicationLocked()方法:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
... // 错误处理
return false;
}
if (app.thread != null) {
handleAppDiedLocked(app, true, true); // 如果app中已经有线程,说明app以前存在,现在是重启
}
final String processName = app.processName;
try {
// 创建监听app死亡的对象
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;
}
... // 对app对象赋值
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
boolean didSomething = false;
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
...
try {
调用应用的bindApplication接口
ProfilerInfo profilerInfo = profileFile == null ? null
: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
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) {
...
}
...
if (normalMode) {
try {
// 处理挂起的Activity
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
if (!badApp) {
try {
// 处理挂起的Service
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
// 发送挂起的广播
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
...
return true;
}
attachApplication()方法首先检查调用者的参数,然后调用ApplicationThread的借口bindApplication(),bindApplication()发送完消息BIND_APPLICATION后就返回了,这样执行过程就转到应用的消息处理代码中了。
调用完bindApplication()接口后,attachApplicationLocked()方法还会调用mStackSupervisor的attachApplicationLocked()方法 。这个方法最主要的工作是调用realStartActivityLocke()方法,前面介绍了realStartActivityLocke()。
除了开启Activity能启动进程外,启动Service、发送广播也可能需要启动进程,因此,这里也调用了mService的attachApplicationLocked()方法和sendPendingBroadcastsLocked()来处理Service启动和广播启动的情况。
处理BIND_APPLICATION消息将调用ActivityThread的handleBindApplication()方法,这个方法中初始化了大部分应用框架的对象:
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
// 创建系统配置对象
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
...
// 设置进程名称和DDMS中的进程名
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
if (data.persistent) {
// 带有persistent标记的进程在低内存的设备上不能使用硬件加速
if (!ActivityManager.isHighEndGfx()) {
if (!("com.android.systemui").equals(data.processName)) {
ThreadedRenderer.disable(false);
}
}
}
...
// 用系统的配置设置应用的时区
TimeZone.setDefault(null);
// 用系统的配置设置应用的地区
LocaleList.setDefault(data.config.getLocales());
synchronized (mResourcesManager) {
// 生成资源管理对象,并用系统配置初始化
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
}
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
// 如果应用没有指定使用设备的density,则把应用中图片的缺省density设为mdpi
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
updateDefaultDensity();
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
...
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
// 设置网络代理
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw e.rethrowFromSystemServer();
}
}
...
// 生成ContextImpl对象
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
// 设置cache目录
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
} else {
Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
+ "due to missing cache directory");
}
final Context deviceContext = appContext.createDeviceProtectedStorageContext();
final File codeCacheDir = deviceContext.getCodeCacheDir();
if (codeCacheDir != null) {
setupGraphicsSupport(data.info, codeCacheDir);
} else {
Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
}
}
NetworkSecurityConfigProvider.install(appContext);
if (ii != null) {
...
} else { // 创建Instrumentation对象
mInstrumentation = new Instrumentation();
}
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
// 如果应用指定使用big heap,则清除dalvik中的限制
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
long startTime = SystemClock.elapsedRealtime();
// 生成Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
CheckTime.checkTime(startTime, "handleBindApplication : makeApplication");
mInitialApplication = app;
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
startTime = SystemClock.elapsedRealtime();
// 安装应用ContentProvider
installContentProviders(app, data.providers);
// 对于带有ContentProvider的应用,需要确保应用的dalivk运行在JIT模式
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
CheckTime.checkTime(startTime, "handleBindApplication : installContentProviders");
}
}
startTime = SystemClock.elapsedRealtime();
try {
// 调用Instrumentation对象的onCreate()方法
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
// 调用Application对象的onCreate()方法
mInstrumentation.callApplicationOnCreate(app);
CheckTime.checkTime(startTime, "handleBindApplication : callApplicationOnCreate");
} 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);
}
}
handleBindApplication()方法的主要功能就是创建应用框架中的各种对象。
以上便是从点击launcher到应用运行的大体流程,包括了应用的冷热启动。如有不恰当的地方,欢迎指正。
参考文献:
深入解析Android5.0系统》刘超
http://blog.csdn.net/qianhaifeng2012/article/details/52039053
http://blog.csdn.net/gaugamela/article/details/53183216