主目录见:Android高级进阶知识(这是总目录索引)
今天开始我们将渐渐进入Framework的学习,然后进而为以后的插件化做准备,要学会如何开发一套插件化框架,显然这是第一步,我们今天就来讲讲应用程序内启动Activity的流程,首先呢,我先把整个流程的图给大家看看,以便于大家学习源码的时候能有一个对照:
从图中可以看出,我们的中间跨进程交互都是用的AIDL的知识,如果大家不了解AIDL的话,那么我推荐看下从framework分析AIDL生成文件这篇文章或者看下更基础点的文章,大家自己决定,想必大家看完应该会知道。
一.目标
分析源码当然得有目标,我们的目标很明确:
1.了解整套Activity的启动过程;
2.为插件化框架开发做准备知识。
二.启动流程分析
我们先来明确下应用程序Activity启动的两个主要方式:
1.在Home桌面点击应用程序图标启动程序即launcher启动程序的主Activity。
2.在应用程序中调用startActivity()和startActivityForResult()来启动另外一个Activity。这个应用程序可以位于同个应用程序或者其他应用程序。
我们今天主要是讲第二种方式
public class MainActivity extends Activity implements OnClickListener {
......
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,TargetActivity.class);
startActivity(intent);
}
}
1.因为MainActivity继承了Activity所以我们看Activity的startActivity()方法,然后经过startActivityForResult和execStartActivity最终会调用到Instrumentation的execStartActivity:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
//省略掉自动测试所添加的ActivityMonitor类相关代码
.........
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//获取远程AMS(ActivityManagerService)
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//检查Activity启动是否成功
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
这里我们要注意这里面传的参数,这样我们接下来要走的话不会迷失:
whoThread:Binder对象,是主进程的Context对象;
token:一个Binder对象,指向了服务端一个ActivityRecord对象;
target:目标Activity即要启动的Activity;
options:要传输的Bundle对象,里面携带数据。
2 .我们程序这里的ActivityManagerNative.getDefault()这里获取到的是ActivityManagerService的远程接口的代理即ActivityManagerProxy对象(如果不清楚可以看下AIDL的相关知识),所以这里的就是调用ActivityManagerProxy的startActivity方法:
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,resultWho,profilerInfo均为null,参数caller为ApplicationThread类型的Binder实体,resultTo是为一个Binder实体的远程接口,参数requestCode为-1,startFlags为0,options为null。最后通过ActivityManagerProxy对象调用startActivity方法的实质是调用BinderProxy.transact向Binder驱动发送START_ACTIVITY_TRACSACTION命令。然后我们应用程序就到AMS中了。
3.过Binder驱动程序就进入到ActivityManagerService的startActivity方法来了,我们来看看AMS的startActivity方法:
@Override
public final 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());
}
4.我们看到这个方法又调用了内部的startActivityAsUser然后会调用ActivityStarter(这个类是新版的android我这里版本是android-25才有的)的一系列方法:startActivityMayWait=>startActivityLocked=>startActivityUnchecked然后会到达ActivityStackSupervisor类的resumeFocusedStackTopActivityLocked方法接着到达ActivityStack类的resumeTopActivityUncheckedLocked=>resumeTopActivityInnerLocked接着又会走到ActivityStack类的resumeTopActivityInnerLocked方法然后会先调用startPausingLocked来停掉前面一个Activity即前一个Activity要先执行onPause方法:
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean dontWait) {
........
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
........
}
5.这里的prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity(ApplicationThreadProxy.schedulePauseActivity)来通知前面一个Activity进入Paused状态。我们这里指的这里也是一个AIDL交互,我们不详细说明,我们直接看ActivityThread中的schedulePauseActivity方法:
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
int seq = getLifecycleSeq();
if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
+ " operation received seq: " + seq);
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
configChanges,
seq);
}
6.这里的sendMessage是发送一条消息,主要是发送到内部类H里面的handleMessage方法里面这里的消息code是PAUSE_ACTIVITY:
case PAUSE_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
7.这样程序就调用了handlePauseActivity方法:
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
..........
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
8.我们看到程序通过AIDL( ActivityManagerNative.getDefault()获取的是AMS的远程代理)调用到AMS的activityPaused方法:
@Override
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
9.我们看到这里调用了ActivityStack的activityPausedLocked方法:
final void activityPausedLocked(IBinder token, boolean timeout) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Activity paused: token=" + token + ", timeout=" + timeout);
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
completePauseLocked(true, null);
return;
} else {
..........
}
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
10.我们看到程序这里会调用completePauseLocked方法来停止然后接着调用ActivityStackSupervisor类的resumeFocusedStackTopActivityLocked方法接着到达ActivityStack类的resumeTopActivityUncheckedLocked=>resumeTopActivityInnerLocked接着又会走到ActivityStack类的resumeTopActivityInnerLocked方法然后又转到ActivityStackSupervisor类的startSpecificActivityLocked:
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, true);
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)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// 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, true);
}
11.前面首先会判断要启动的Activity的进程是否启动起来了,如果已经启动起来了会直接调用realStartActivityLocked,进行Activity的启动就可以了。但是如果我们配置了process这个属性,由于这是我们第一次启动Activity,所以进程还是没有开启的,所以我们程序会调用AMS的startProcessLocked方法:
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
null /* entryPoint */, null /* entryPointArgs */);
}
我们认真注意传进来的参数分别是什么值其中entryPoint为null,然后我们直接看另一个startProcessLocked方法:
ActivityManagerService.startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs){
......
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
......
}
所以在调用上面方法的时候这里因为entryPoint传过来的是null的,所以我们的entryPoint是为android.app.ActivityThread的值,这个时候我们通过Process.start()传入的第一个参数是android.app.ActivityThread,这个参数在我们进程启动完成之后,来决定后续代码的执行 。
12.我们知道android的进程是通过zygote孵化出来的,而ActivityManagerService是运行在System进程,Zygote是运行在Zygote进程中的。Process.start方法的实现是在zygoteSendArgsAndGetResult函数最终实现的,是向socket服务端写数据,把创建进程的请求通过socket通讯方式来让zygote的管理进程创建新进程。在向zygote进程发送的通信请求时,需要组装数据,具体实现我们看Process类的start方法:
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList argsForZygote = new ArrayList();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
//省略参数拼装的一些方法
.............
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
以上的方法省略了一些拼装参数的方法,程序最终调用zygoteSendArgsAndGetResult()方法来向socket服务端发送创建进程的请求,这样zygote就会来创建新的进程。
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)
throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
13.这里就会向我们的zygote发送一个创建进程请求。然后创建新的进程就会在zygote进行,这里我们不过多去解析zygote怎么创建新的进程。最后程序会在ActivityStackSupervisor的attachApplicationLocked方法里面调用realStartActivityLocked方法:
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);
......
}
14.这里的app.thread是ApplicationThread,所以这里会调用ApplicationThread的scheduleLaunchActivity方法最后调用到ActivityThread的handleLaunchActivity方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
.......
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
.......
} 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,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
15.我们看到上面方法里面会调用performLaunchActivity方法,这个方法就是真正启动Activity了,我们看下这个具体方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
//这里调用Instrumentation的newActivity来创建一个新的Activity
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
} catch (Exception e) {
......
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
........
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
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;
if (r.isPersistable()) {
//这个方法里面会调用目标Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
.......
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
......
}
return activity;
}
16.我们看到这个方法就是真正创建Activity的地方了,首先会调用Instrumentation的newActivity方法:
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
17.这里很容易看懂就是用类加载器加载一个新的class,然后返回他的实例。到这一步Activity的实例也就被创建出来了,接着我们看会调用Activity的onCreate方法,这个会在Instrumentation的callActivityOnCreate方法里面:
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
我们看到这个方法里面会调用activity的performCreate方法,这个方法如下:
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
到这里我们的Activity就启动完毕了,如果你中间有什么过程不懂的可以参照我们前面画的图来对照,基本流程就知道了,也不至于被绕晕。
总结:这次的Activity启动讲解主要是让大家有个流程上的认识,到时如果在插件化框架上有用到我会认真把某一个地方拿出来讲解,如果有讲解的不对的地方欢迎大家指出哈,希望大家共同进步。