这篇文章结合4.2.2源码分析点击android桌面app图标启动应用程序的过程.
android的桌面程序(launcher)是android系统启动的第一个应用程序,其他的应用程序安装后,会在launcher上创建一个快捷图标,我们点击桌面上的快捷图标就会启动相应的app,接下来我们就来看看从点击图标到app启动起来的这一过程.
Launcher的源代码工程在packages/apps/Launcher2目录下.
第一步:点击图标,onClick()回调方法被调用,在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java中.
public void onClick(View v) {
......
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).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()));
boolean success = startActivitySafely(v, intent, tag);//
....
} else if (tag instanceof FolderInfo) {
....
} else if (v == mAllAppsButton) {
.......
}
}
点击app图标,其实是启动app中默认的Activity,例如在清单配置文件中配置我们应用程序的Activity:
<activity那么这个MainActivity就是这个应用程序默认的Activity.
android:name="com.example.my.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
第二步:接着看startActivitySafely()方法,还是在Launcher.Java文件中.
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
....
success = startActivity(v, intent, tag);
.......
return success;
}
第三步:继续调用startActivity()方法,还是在Launcher.Java文件中.
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
// Only launch using the new animation if the shortcut has not opted out (this is a
// private contract between launcher and may be ignored in the future).
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {//启动的动画,看名字应该是图标放大的动画,这里暂时忽略吧
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
v.getMeasuredWidth(), v.getMeasuredHeight());
startActivity(intent, opts.toBundle());
} else {
....
}
return true;
} catch (SecurityException e) {
......
}
return false;
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);添加这个flag,将在后面决定将这个activity放在哪个task中启动.关于task和这些Intent的flag以及activity的启动模式以后写一篇博客讲解.这里我们只需知道activity启动必须要在一个task中.
第四步:接下来调用到launcher的父类Activity中的startActivity()方法,在frameworks/base/core/java/android/app/Activity.java文件中.
public void startActivity(Intent intent, Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
.....
}
}
第五步:继续调用startActivityForResult() ,上面requestCode参数值为-1表示不需要目标activity结束后返回结果,在Activity.java文件中.
public void startActivityForResult(Intent intent, int requestCode, 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());
}
if (requestCode >= 0) {
//不进来
}
} else {
//不进来
}
}
该函数中出现几个新的变量,来看看:
① mInstrumentation变量是Instrumentation类型,该对象是在启动应用程序过程中最先创建的,一个应用程序中只有一个Instrumentation对象,每个Activity内部都有一个该对象的引用.Instrumentation可以理解为应用进程的管家,ActivityThread要创建或者暂停某个Activity时,是通过这个"管家"进行的,设置好这个管家的好处是可以统计所有的"开销",开销的信息保存在"管家"那里.
② mMainThread变量是ActivityThread类型,它代表的是应用程序的主线程,一个应用程序中只有一个ActivityThread类,应用程序的入口为该类的main()函数.ActivityThread类在main()方法里实例化的,然后传到activity中.
③ mMainThread.getApplicationThread()返回是ApplicationThread类型的mAppThread对象,ApplicationThread其实是Binder类型.是用来和ActivityManagerService进程间通信的,它是在ActivityThread类中创建的.
④ mToken 也是是Binder类型 它是一个Binder对象的远程接口.每个activity有一个mToken与之相关联.
⑤mParent 也是Activity类型,为null.
第六步:ok,继续调用execStartActivity()方法,在frameworks/base/core/java/android/app/Instrumentation.java文件中.
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
.....
try {
intent.setAllowFds(false);
intent.migrateExtraStreamToClipData();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
....
} catch (RemoteException e) {
}
return null;
}
先整理一下参数,根据第五步传过来的值,知道who 就是 activity(launcher)的引用,contextThread是ApplicationThread类型的mAppThread对象,token对应mToken ,target是activity(launcher)的引用,后面requestCode是-1;
这里ActivityManagerNative.getDefault()方法通过binder进程间通信获取了ActivityManagerService系统服务远程接口的引用.关于Binder进程间通信可以参考前面的三篇文章:
intent.resolveTypeIfNeeded(who.getContentResolver())这个方法是获取这个intent的MIME类型,这里假设没有设置MIME类型 即 在上面的清单文件没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。
① target != null ? target.mEmbeddedID : null,这里target不为空,但是mEmbeddedID为空,所以这里也为null.
因此上面接下调用的startActivity(..)的参数就是startActivity(whoThread, intent, null,token, null,-1, 0, null, null, options);
第七步:继续调用startActivity()在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中
public int startActivity(IApplicationThread caller, Intent intent,经过Binder驱动,在ActivityManagerService系统服务端 onTransact(...)就会被调用到
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, String profileFile,
ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
data.writeString(profileFile);
if (profileFd != null) {
data.writeInt(1);
profileFd.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;
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)上面startActivity(...)消息就会发送到ActivityManagerService中了,这里整理一下参数:app为IApplicationThread,resolvedType为null,resultTo为Binder类型(mToken),resultWho为null,requestCode为-1,startFlags为0,profileFile为null,profileFd为null.因此接下startActivity(app, intent, null, resultTo, null, -1, 0, null, null, options).
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
String profileFile = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
? data.readFileDescriptor() : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags,
profileFile, profileFd, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
第八步:调用startActivity(),在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
return startActivityAsUser(caller, intent, resolvedType, resultTo, resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
}
第九步:接着调用startActivityAsUser().在ActivityManagerService.java文件中
public final int startActivityAsUser(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "startActivity", null);
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}
第十步:接着调用startActivityMayWait().在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中
final int startActivityMayWait(IApplicationThread caller, int callingUid,参数outResult和config均为null,此外,表达式(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0为false,因此,这里忽略了无关代码。resolveActivity(intent, resolvedType, startFlags, profileFile, profileFd, userId)方法对参数intent的内容进行解析,得到目标activity的相关信息,保存在aInfo变量中.
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
.....
boolean componentSpecified = intent.getComponent() != null;//这里为true
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
synchronized (mService) {
int callingPid;
if (callingUid >= 0) {
....
} else if (caller == null) {
....
} else {
callingPid = callingUid = -1;//走这里
}
mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;//为false
....
if (mMainStack && aInfo != null &&
(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {//最后条件不满足
....
}
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
startFlags, options, componentSpecified, null);
if (mConfigWillChange && mMainStack) {
....//不进来
}
if (outResult != null) {
.....//不进来
}
return res;
}
}
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, int userId) {
// Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
}
if (aInfo != null) {
....
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
....
}
return aInfo;
}
此外,函数开始的地方调用intent.getComponent()函数的返回值不为null,因此,这里的componentSpecified变量为true.整理一下接下调用的参数
startActivityLocked(caller,intent,null,aInfo,resultTo,null,-1,-1,-1,0,options,true,null);
第十一步:接着调用startActivityLocked().在ActivityStack.java文件中
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
....
}
}
if (err == ActivityManager.START_SUCCESS) {
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
int index = indexOfTokenLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG, "Will send result to " + resultTo + " (index " + index + ")");
if (index >= 0) {
sourceRecord = mHistory.get(index);
if (requestCode >= 0 && !sourceRecord.finishing) {
....
}
}
}
int launchFlags = intent.getFlags();//第三步 addFlag()设置的 NEW_TASK,
if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
&& sourceRecord != null) {
.....
}
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
...
}
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
...
}
if (err != ActivityManager.START_SUCCESS) {
....
}
....
ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
if (outActivity != null) {
...
}
......
err = startActivityUncheckedLocked(r, sourceRecord,
startFlags, true, options);
....
return err;
}
从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了.前面说过,参数resultTo是Launcher这个Activity对应的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。再接下来,创建即将要启动的Activity的相关信息,并保存在r变量中:在frameworks/base/services/java/com/android/server/am/ActivityRecord.java文件中
ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller,
int _launchedFromUid, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified) {
service = _service;
stack = _stack;
appToken = new Token(this);//第七步 ④mToken 类型和这个类型一样 这里的appToken是与将要启动的activity相关的,④mToken是launcher中的
info = aInfo;
launchedFromUid = _launchedFromUid;
userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
intent = _intent;
shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType;
componentSpecified = _componentSpecified;
configuration = _configuration;
resultTo = _resultTo;//传进来是null
resultWho = _resultWho;
requestCode = _reqCode;
state = ActivityState.INITIALIZING;
frontOfTask = false;
launchFailed = false;
stopped = false;
delayedResume = false;
finishing = false;
configDestroy = false;
keysPaused = false;
inHistory = false;
visible = true;
waitingVisible = false;
nowVisible = false;
thumbnailNeeded = false;
idle = false;
hasBeenLaunched = false;
// This starts out true, since the initial state of an activity
// is that we have everything, and we shouldn't never consider it
// lacking in state to be removed if it dies.
haveState = true;
上面的appToken变量很重要
第十二步:调用startActivityUncheckedLocked(),在ActivityStack.java文件中
final int startActivityUncheckedLocked(ActivityRecord r,这个函数的主要作用是是判断是否需要新建一个task来启动activity,这与launchFlag和launchMode有关。由于r.launchMode的值不为ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task,目标activity所在应用是第一次启动,所以这里返回的结果是null,即taskTop为null.接着判断 当前在堆栈顶端的Activity是否就是即将要启动的Activity, 现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity.因此需要创建一个新的Task来启动这个Activity.
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
int launchFlags = intent.getFlags();
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
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) {
...
}
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
....
}
if (sourceRecord == null) {
...
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
...
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
...
}
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
....
}
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// If bring to front is requested, and no result is requested, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
if (r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
if (taskTop != null) {
....
}
}
.....
if (r.packageName != null) {
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
....
}
}
} else {
....
}
boolean newTask = false;
boolean keepCurTransition = false;
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (reuseTask == null) {
// todo: should do better management of integers.
mService.mCurTask++;
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new task " + r.task);
} else {
....
}
newTask = true;
if (!movedHome) {
moveHomeToFrontFromLaunchLocked(launchFlags);
}
} else if (sourceRecord != null) {
....
} else {
....
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked());
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}
第十三步:调用startActivityLocked();在ActivityStack.java文件中 参数分别为r,true,true,false,options
private final void startActivityLocked(ActivityRecord r, boolean newTask,这个函数将要启动启动的activity放入到序列mHistory中,然后做task切换,因为launcher跟目标activity不在同一任务中.
boolean doResume, boolean keepCurTransition, Bundle options) {
final int NH = mHistory.size();
int addPos = -1;
if (!newTask) {
.....
}
// Place a new activity at top of stack, so it is next to interact
// with the user.
if (addPos < 0) {
addPos = NH;
}
// If we are not placing the new activity frontmost, we do not want
// to deliver the onUserLeaving callback to the actual frontmost
// activity
if (addPos < NH) {
...
}
.....
mHistory.add(addPos, r);
r.putInHistory();
r.frontOfTask = newTask;
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: starting " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
mService.mWindowManager.prepareAppTransition(newTask
? WindowManagerPolicy.TRANSIT_TASK_OPEN
: WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
r.updateOptionsLocked(options);
mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
r.task.taskId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.info.flags);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
// to reset it to make sure we apply affinities to move any
// existing activities from other tasks in to it.
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags()
&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
}
if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
ActivityRecord prev = mResumedActivity;
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
if (prev.task != r.task) prev = null;
// (2) The current activity is already displayed.
else if (prev.nowVisible) prev = null;
}
mService.mWindowManager.setAppStartingWindow(
r.appToken, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
r.labelRes, r.icon, r.windowFlags,
prev != null ? prev.appToken : null, showStartingIcon);
}
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
r.task.taskId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.info.flags);
ActivityOptions.abort(options);
}
if (VALIDATE_TOKENS) {
..
}
if (doResume) {
resumeTopActivityLocked(null);
}
}
第十四步:resumeTopActivityLocked()继续,ActivityStack.java文件中,参数为null:
final boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
}
第十五步:resumeTopActivityLocked();继续,ActivityStack.java文件中,参数为nul,nulll:
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);//
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
.....
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
.....
}
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
if ((mService.mSleeping || mService.mShuttingDown)
&& mLastPausedActivity == next
&& (next.state == ActivityState.PAUSED
|| next.state == ActivityState.STOPPED
|| next.state == ActivityState.STOPPING)) {
.....
}
// 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) {
...
}
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
mStoppingActivities.remove(next);
mGoingToSleepActivities.remove(next);
next.sleeping = false;
mWaitingVisibleActivities.remove(next);
next.updateOptionsLocked(options);
if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything
// until that is done.
if (mPausingActivity != null) {
.....
}
// 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) {
...
}
// We need to start pausing the current activity so the top one
// can be resumed...
if (mResumedActivity != null) {
if (next.app != null && next.app.thread != null) {
...
}
startPausingLocked(userLeaving, false);
return true;
}
.....
return true;
}
函数先通过调用topRunningActivityLocked函数获得堆栈顶端的Activity,这里就是要启动的MainActivity了(第十三步添加进去的),保存在next变量中。 接下来把mUserLeaving的保存在本地变量userLeaving中,然后重新设置为false,在上面mUserLeaving的值为true,因此,这里的userLeaving为true。这里的mResumedActivity为Launcher,因为Launcher是当前正被执行的Activity。我们知道启动一个新的activity首先要暂停正在运行的activity.
第十六步:startPausingLocked(),ActivityStack.java文件中,参数为true,false:
private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
if (mPausingActivity != null) {
......
}
ActivityRecord prev = mResumedActivity;
if (prev == null) {
.....
}
....
mResumedActivity = null;
mPausingActivity = prev;
mLastPausedActivity = prev;
prev.state = ActivityState.PAUSING;
prev.task.touchActiveTime();
prev.updateThumbnail(screenshotActivities(prev), null);
mService.updateCpuStats();
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags);
if (mMainStack) {
mService.updateUsageStats(prev, false);
}
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
}
} else {
...
}
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!mService.mSleeping && !mService.mShuttingDown) {
mLaunchingActivity.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
}
}
...
}
这个函数对一些变量进行赋值,后面的需要用到.然后就去暂停launcher activty
第十七步:schedulePauseActivity();frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中,
这里又是Binder进程间通信了.参数token就是第五步mToken(与launcher这个activity相关的),其他几个参数false,true,false
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) 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);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
经过Binder驱动
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)第十八步 : schedulePauseActivity() 在frameworks/base/core/java/android/app/ActivityThread.java中
throws RemoteException {
switch (code) {
case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
IBinder b = data.readStrongBinder();
boolean finished = data.readInt() != 0;
boolean userLeaving = data.readInt() != 0;
int configChanges = data.readInt();
schedulePauseActivity(b, finished, userLeaving, configChanges);//这里就到launcher ActivityThread中去了
return true;
}
public final void schedulePauseActivity(IBinder token, boolean finished,第十九步 : queueOrSendMessage(),ActivityThread.java中
boolean userLeaving, int configChanges) {
queueOrSendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,//这里是PAUSE_ACTIVITY
token,
(userLeaving ? 1 : 0),
configChanges);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { synchronized (this) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; mH.sendMessage(msg); } }
mH是Handler类型,ActivityThread.java成员变量,这里将相关数据封装消息发送到主线程的消息队列.
第二十步:handleMessage(),ActivityThread.java中
case PAUSE_ACTIVITY:第二十一步 :: 继续 handlePauseActivity() ,在ActivityThread.java中
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);//??
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
ActivityClientRecord r = mActivities.get(token);//
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {//这里为true
performUserLeavingActivity(r);//
}
r.activity.mConfigChangeFlags |= configChanges;
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.
try {
ActivityManagerNative.getDefault().activityPaused(token);//
} catch (RemoteException ex) {
}
}
}
首先performUserLeavingActivity 会导致onUserInteraction(),onUserLeaveHint()会先后被调用,这两个回调平时我们应该没怎么重写.
第二十二步:先调用performPauseActivity(),ActivityThread.java中
final Bundle performPauseActivity(IBinder token, boolean finished,第二十三步:performPauseActivity() ,ActivityThread.java中
boolean saveState) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState) : null;
}
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState) {
if (r.paused) {
.....
}
Bundle state = null;
if (finished) {
...
}
try {
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
state = new Bundle();
state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);//
r.state = state;
}
// Now we are idle.
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);//
....
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
.....
return state;
}
OnSaveInstanceState()可能被回调(targetSdkVersion<android.os.Build.VERSION_CODES.HONEYCOMB会调用), OnPause()被调用 注意这里是launcher应用的activity.这两个回调应该常见吧.
第二十四步:接着看第二十一步的activityPaused(),frameworks/base/core/java/android/app/ActivityManagerNative.java中.
launcher执行完暂停之后,通过Binder进程间通信,告诉ActivityManagerService可以启动目标Activity.
public void activityPaused(IBinder token) throws RemoteException经过Binder驱动
{
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();
}
case ACTIVITY_PAUSED_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
activityPaused(token);//
reply.writeNoException();
return true;
}
第二十五步:activityPaused() ,frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中
public final void activityPaused(IBinder token) {第二十六步:activityPaused(),frameworks/base/services/java/com/android/server/am/ActivityStack.java中
final long origId = Binder.clearCallingIdentity();
mMainStack.activityPaused(token, false);//
Binder.restoreCallingIdentity(origId);
}
final void activityPaused(IBinder token, boolean timeout) { ... ActivityRecord r = null; synchronized (mService) { int index = indexOfTokenLocked(token); if (index >= 0) { r = mHistory.get(index); mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); if (mPausingActivity == r) {//这里在第十六步中设置的,mPausingActivity就是launcher对应的 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r + (timeout ? " (due to timeout)" : " (pause complete)")); r.state = ActivityState.PAUSED; completePauseLocked();// } else { .... } } } }第二十七步:completePauseLocked() ,ActivityStack.java中
private final void completePauseLocked() {
ActivityRecord prev = mPausingActivity;
....
if (prev != null) {
....
mPausingActivity = null;
}
if (!mService.isSleeping()) {
resumeTopActivityLocked(prev);//
} else {
.....
}
}
...
}
函数首先把mPausingActivity变量清空,因为现在不需要它了,然后调用resumeTopActivityLokced进一步操作,它传入的参数即为代表Launcher这个Activity的ActivityRecord
第二十八步:resumeTopActivityLocked(),ActivityStack.java中
final boolean resumeTopActivityLocked(ActivityRecord prev) {第二十九步: resumeTopActivityLocked() ,ActivityStack.java中 .
return resumeTopActivityLocked(prev, null);
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
...
ActivityRecord next = topRunningActivityLocked(null);
....
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
...
}
next.delayedResume = false;
....
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
...
return false;
}
.....
if ((mService.mSleeping || mService.mShuttingDown)
.....
}
// We need to start pausing the current activity so the top one
// can be resumed...
if (mResumedActivity != null) {
.....
return true;
}
....
if (next.app != null && next.app.thread != null) {
...
} else {
...
startSpecificActivityLocked(next, true, true);//---------------------------------
}
return true;
}
我们知道,当前在堆栈顶端的Activity为我们即将要启动的MainActivity,这里通过调用topRunningActivityLocked将它取回来,保存在next变量中。之前最后一个Resumed状态的Activity,即Launcher,到了这里已经处于Paused状态了(第二十六步设置的),因此,mResumedActivity为null。最后一个处于Paused状态的Activity为Launcher,因此,这里的mLastPausedActivity就为Launcher(第十六步设置的)。前面我们为MainActivity创建ActivityRecord后,它的app域一直保持为null。最终调用startSpecificActivityLocked进行下一步操作。
第三十步:startSpecificActivityLocked(),ActivityStack.java中
private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);
....
if (app != null && app.thread != null) {
try {
app.addPackage(r.info.packageName);
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false);
}
注意,这里由于是第一次启动应用程序的Activity,所以下面语句:取回来的app为null。在Activity应用程序中的AndroidManifest.xml配置文件中,我们没有指定Application标签的process属性,系统就会默认使用package的名称。函数最终执行ActivityManagerService.startProcessLocked函数进行下一步操作。
第三十一步:startProcessLocked(), frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中
ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid);
} else {
...
}
....
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
...
if (app == null) {
app = newProcessRecordLocked(null, info, processName, isolated);
....
mProcessNames.put(processName, app.uid, app);
..
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName);
}
// If the system is not ready yet, then hold off on starting this
// process until it is.
.....
startProcessLocked(app, hostingType, hostingNameStr);
return (app.pid != 0) ? app : null;
}
这里再次检查是否已经有以process + uid命名的进程存在,在我们这个情景中,返回值app为null,因此,后面会创建一个ProcessRecord,并存保存在成员变量mProcessNames中,最后,调用另一个startProcessLocked函数进一步操作:
第三十二步:startProcessLocked(),ActivityManagerService.java中
private final void startProcessLocked(ProcessRecord app,这里主要是调用Process.start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数,这就是为什么我们前面说每一个应用程序都有一个ActivityThread实例来对应的原因。
String hostingType, String hostingNameStr) {
.....
try {
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
if (Environment.isExternalStorageEmulated()) {
if (pm.checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
.......
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
.....
}
} catch (RuntimeException e) {
..
}
}
第三十三步:main(),frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {这个函数在进程中创建一个ActivityThread实例(对应第五步②),然后调用它的attach函数,接着就进入消息循环了,直到最后进程退出。
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
第三十四步:attach(),在ActivityThread.java中
private void attach(boolean system) {
sThreadLocal.set(this);
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {
.....
}
......
}
函数attach最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象,它的作用是用来进行进程间通信的。final ApplicationThread mAppThread = new ApplicationThread();ActivityThread类的成员变量(对应第五步③).
第三十五步:attach(),在ActivityManagerNative.java中
public void attachApplication(IApplicationThread app) throws RemoteException经过binder驱动
{
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();
}
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
第三十六步 :attachApplication(),在ActivityManagerService.java中
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
第四三十七步:attachApplication(),在ActivityManagerService.java中
private final boolean attachApplicationLocked(IApplicationThread thread,在前面( 第三十一步 ),已经创建了一个ProcessRecord,这里首先通过pid将它取回来,放在app变量中,然后对app的其它成员进行初始化.这里先后调用两个方法,bindApplication(),realStartActivityLocked()分别来看看。都是是通过Binder进程间通信.
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
.....
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
.....
}
// Tell the process all about itself.
if (localLOGV) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app);
.......
app.thread = thread;
....
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
if (!normalMode) {
Slog.i(TAG, "Launching preboot mode app: " + app);
}
if (localLOGV) Slog.v(
TAG, "New app record " + app
+ " thread=" + thread.asBinder() + " pid=" + pid);
try {
.....
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
.....
} catch (Exception e) {
.....
}
......
// See if the top visible activity is waiting to run in this process...
ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (mHeadless) {
....
} else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
...
}
} else {
...
}
}
.......
return true;
}
第三十八步:bindApplication(),在ApplicationThreadNative.java中.
public final void bindApplication(String packageName, ApplicationInfo info,经过Binder驱动
List<ProviderInfo> providers, ComponentName testName, String profileName,
ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle testArgs,
IInstrumentationWatcher testWatcher, int debugMode, boolean openGlTrace,
boolean restrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(packageName);
info.writeToParcel(data, 0);
data.writeTypedList(providers);
if (testName == null) {
data.writeInt(0);
} else {
data.writeInt(1);
testName.writeToParcel(data, 0);
}
data.writeString(profileName);
if (profileFd != null) {
data.writeInt(1);
profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
data.writeInt(autoStopProfiler ? 1 : 0);
data.writeBundle(testArgs);
data.writeStrongInterface(testWatcher);
data.writeInt(debugMode);
data.writeInt(openGlTrace ? 1 : 0);
data.writeInt(restrictedBackupMode ? 1 : 0);
data.writeInt(persistent ? 1 : 0);
config.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeMap(services);
data.writeBundle(coreSettings);
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
case BIND_APPLICATION_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
String packageName = data.readString();
ApplicationInfo info =
ApplicationInfo.CREATOR.createFromParcel(data);
List<ProviderInfo> providers =
data.createTypedArrayList(ProviderInfo.CREATOR);
ComponentName testName = (data.readInt() != 0)
? new ComponentName(data) : null;
String profileName = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
? data.readFileDescriptor() : null;
boolean autoStopProfiler = data.readInt() != 0;
Bundle testArgs = data.readBundle();
IBinder binder = data.readStrongBinder();
IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
int testMode = data.readInt();
boolean openGlTrace = data.readInt() != 0;
boolean restrictedBackupMode = (data.readInt() != 0);
boolean persistent = (data.readInt() != 0);
Configuration config = Configuration.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
HashMap<String, IBinder> services = data.readHashMap(null);
Bundle coreSettings = data.readBundle();
bindApplication(packageName, info,
providers, testName, profileName, profileFd, autoStopProfiler,
testArgs, testWatcher, testMode, openGlTrace, restrictedBackupMode,
persistent, config, compatInfo, services, coreSettings);
return true;
}
第三十九步 :bindApplication(),在ActivityThread.java中.这里已经到目标activity所在进程来了
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
boolean persistent, Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfileFile = profileFile;
data.initProfileFd = profileFd;
data.initAutoStopProfiler = false;
queueOrSendMessage(H.BIND_APPLICATION, data);
}
第四十步 :queueOrSendMessage(),在ActivityThread.java中
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
第四十一步 :handleMessage(),在ActivityThread.java中
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
第四十二步 :handleBindApplication(),在ActivityThread.java中
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
.....
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
....
if (data.instrumentationName != null) {
.....
} else {
mInstrumentation = new Instrumentation();
}
....
// 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 {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
.....
// 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) {
....
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
.....
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
这里主要做了两件事,创建了Instrumentation对象(第五步①),创建Application对象,调用其onCreate()方法.如果有需要的话我们可以自定义Application对象继承Application类,在清单配置文件里<applicationandroid:name=".MyApplication"> name属性里写自己的application对象.
好了回到第三十七步 第二个函数.
第四十三步:realStartActivityLocked(),在ActivityManagerService.java中
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),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
....
} catch (RemoteException e) {
....
}
r.launchFailed = false;
if (updateLRUListLocked(r)) {
Slog.w(TAG, "Activity " + r
+ " being launched, but already in LRU list");
}
if (andResume) {
// As part of the process of launching, ActivityThread also performs
// a resume.
r.state = ActivityState.RESUMED;
if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
+ " (starting new instance)");
r.stopped = false;
mResumedActivity = r;
r.task.touchActiveTime();
if (mMainStack) {
mService.addRecentTaskLocked(r.task);
}
completeResumeLocked(r);
checkReadyForSleepLocked();
if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
} else {
// This activity is not starting in the resumed state... which
// should look like we asked it to pause+stop (but remain visible),
// and it has done so and reported back the current icicle and
// other state.
if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
+ " (starting in stopped state)");
r.state = ActivityState.STOPPED;
r.stopped = true;
}
// Launch the new version setup screen if needed. We do this -after-
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
if (mMainStack) {
mService.startSetupActivityLocked();
}
return true;
}
接下来通过Binder进程间通信,这里最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中,注意,这里的第二个参数r,是一个ActivityRecord类型的Binder对象,用来作为这个Activity的token值。
第四十四步:scheduleLaunchActivity(),在ApplicationThreadNative.java中
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
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);
compatInfo.writeToParcel(data, 0);
data.writeBundle(state);
data.writeTypedList(pendingResults);
data.writeTypedList(pendingNewIntents);
data.writeInt(notResumed ? 1 : 0);
data.writeInt(isForward ? 1 : 0);
data.writeString(profileName);
if (profileFd != null) {
data.writeInt(1);
profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
data.writeInt(autoStopProfiler ? 1 : 0);
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Intent intent = Intent.CREATOR.createFromParcel(data); IBinder b = data.readStrongBinder(); int ident = data.readInt(); ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); Configuration curConfig = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); Bundle state = data.readBundle(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; boolean isForward = data.readInt() != 0; String profileName = data.readString(); ParcelFileDescriptor profileFd = data.readInt() != 0 ? data.readFileDescriptor() : null; boolean autoStopProfiler = data.readInt() != 0; scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, state, ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler); return true; }
第四十五步 :scheduleLaunchActivity(),在ActivityThread.java中.在目标activity所在的进程中
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
第四十六步 :queueOrSendMessage(),在ActivityThread.java中
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
第四十七步 :queueOrSendMessage(),在ActivityThread.java中
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {第四十八步 :handleMessage(),在ActivityThread.java中
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { .... ActivityClientRecord r = (ActivityClientRecord)msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break;
第四十九步 :handleLaunchActivity(),在ActivityThread.java中
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {首先看performLaunchActivity()函数.
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
if (r.profileFd != null) {
.....
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out
// paused, because it needs to be visible but isn't in the
// foreground. We accomplish this by going through the
// normal startup (because activities expect to go through
// onResume() the first time they run, before their window
// is displayed), and then pausing it. However, in this case
// we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just
// retain the current state it has.
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
// when pausing, so we can not have them save their state
// when restarting from a paused state. For HC and later,
// we want to (and can) let the state be saved as the normal
// part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null);
} catch (RemoteException ex) {
// Ignore
}
}
}
第五十步:performLaunchActivity(),在ActivityThread.java中
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
...
}
ComponentName component = r.intent.getComponent();
if (component == null) {
....
}
if (r.activityInfo.targetActivity != null) {
...
}
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);//创建了activity
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
....
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//这里直接取回来,第四十二步已经创建好了
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
..
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
mInstrumentation.callActivityOnCreate(activity, r.state);//会调用到activity的onCreat()
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();//会调用到activity的onStart()
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);//可能会调用activity的onRestoreInstanceState()
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
mInstrumentation.callActivityOnPostCreate(activity, r.state);
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
..
}
return activity;
}
这里首先创建Activity对象,
然后调用attach()函数给它的内部变量赋值.r.parent, r.embeddedID都为null 对应第五步⑤,第六步①.
接着会分别会调用到Activity的onCreat(),onStart(),onRestoreInstanceState()(可能会被调用)这些方法大家很熟悉吧.
好了,回到四十九步看第二个方法.
第五十一步:handleResumeActivity(),在ActivityThread.java中
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
if (localLOGV) Slog.v(
TAG, "Resume " + r + " started activity: " +
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);//添加到wms 然后显示界面
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
......<span style="font-family: Arial, Helvetica, sans-serif;"> return r;</span><span style="font-family: Arial, Helvetica, sans-serif;"> }</span>
performResumeActivity()方法最终会调用activity的onResume()方法,这时activity算是完全启动了,接下就是请求显示界面了.
好了分析到此.
最后总结一下:
用户在Launcher程序里点击应用图标时,会通知ActivityManagerService启动应用的默认Activity,ActivityManagerService发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。应用进程接下来通知ActivityManagerService应用进程已启动,ActivityManagerService保存应用进程的一个代理对象(applicationthread),这样ActivityManagerService可以通过这个代理对象控制应用进程,然后ActivityManagerService通知应用进程创建入口Activity的实例,并执行它的生命周期方法.
,