前言
一直想写写插件化,才发现自己连Activity的启动过程都不甚了解。插件化说到底考验的是开发者对于Android 源码的深入理解程度。
万丈高楼从地起,从头开始吧
Actiity启动流程
Activity的一次启动大致会经过如下四个阶段,其中涉及与AMS的Binder通讯,与Zygote的通讯。为此,我每个阶段都准备了一张时序图,
能很好的理清调用思路
1.开始启动
Activity的所有的启动Activity的操作都会经过startActivityForResult,然后会交给Instrumentation去实现转发,
Instrumentation这个类在调试app时起到了很大的作用,它可以追踪Activity和Application的生命周期,如果需要用于测试
可以继承,然后反射注入,在自动化测试时经常用到。
然后我们看到Instrumentation会通过binder向AMS请求。这里会先请求到ActivityManager注册的服务AMS,然后才调用服务的
startActivity来开始请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Instrumentation.java
public ActivityResult execStartActivity ( Context who , IBinder contextThread , IBinder token , Activity target , Intent intent , int requestCode , Bundle options ) {
...
int result = ActivityManager . getService (). startActivity ( whoThread , who . getBasePackageName (), intent ,
intent . resolveTypeIfNeeded ( who . getContentResolver ()),
token , target != null ? target . mEmbeddedID : null ,
requestCode , 0 , null , options );
...
return null ;
}
//ActivityManager.java
private static final Singleton < IActivityManager > IActivityManagerSingleton =
new Singleton < IActivityManager >() {
@Override
protected IActivityManager create () {
final IBinder b = ServiceManager . getService ( Context . ACTIVITY_SERVICE );
final IActivityManager am = IActivityManager . Stub . asInterface ( b );
return am ;
}
};
ActivityManager.getService()获取的其实就是上图ActivityManager中的单例,然后调用startActivity时会将Activity自身所处进程的IApplicationThread传给AMS,这个主要是用于AMS的之后的回调。
层层转发,最后才将任务分发给了ActivityStack(外包既视感!),第一阶段到此结束,对于这个阶段要注意上述的IApplicationThread的传入,
IApplicationThread本身就是一个AIDL的接口,具体实现在ActivityThread中,每一个ActivityThread都会生成一个ApplicationThread,用于
在与AMS通讯的回调使用。其实AMS也是一个AIDL的实现,我们在这一步相当于是获取AIDL,然后将自身的AIDL传给别人,实现一个回调注册。
1
2
3
4
5
6
7
8
9
10
11
12
class ActivityThread {
...
private class ApplicationThread extends IApplicationThread . Stub {
...
}
...
}
public class ActivityManagerService extends IActivityManager . Stub
implements Watchdog . Monitor , BatteryStatsImpl . BatteryCallback {
...
}
2.栈顶Activity退出
AMS在收到一个启动新APP的请求之后做的第一件重要的事,就是将当前Activity置于“休眠状态”,告诉它“我知道你的请求了,你可以下班了”。
从图中我们知道,AMS这边会产生一个ClientTransaction,一个ClientTransaction可以携带多个转化操作,不过这里这个ClientTransaction只
携带一个PauseActivityItem,从命名就可以看出,这个是一个让Activity “Pause” 的操作。
然后将ClientTansaction通过上文所说的IAppicationThread(这里也被说成是Client客户端)传回去。
1
2
3
4
5
6
7
8
9
10
public class ClientTransaction implements Parcelable , ObjectPoolItem {
...
private IApplicationThread mClient ;
...
public void schedule () throws RemoteException {
//回调操作
mClient . scheduleTransaction ( this );
}
...
}
经过Binder操作之后,ActivityThread这边的IApplicationThread就收到回调操作,然后继续任务分发,会将任务分发给ActivityThread中的
H,这个H其实就是一个Handler。ActivityThread在创建的同时也为该进程中创建了一个默认Looper,也就是我们常说的mainLooper,这个H就是ActvityThread为mainLooper准备的配套设施。
最后,传送过来的PauseActivityItem会执行具体的Pause操作,经过Instrumentation的转发,执行栈顶的Activity的performPause,最后也会
调用了我们常见的生命周期回调 onPause。
3.启动新进程
ActivityStack在完成了pause 栈顶Actvity之后,就开始真正启动新应用的步骤了。通过AMS 将具体的启动任务分发到Process的start方法中,
Process调用ZygoteProcess的start方法,然后ZygoteProcess调用startViaZygote进行操作,这一系列转发之后,关键时候来了。ZygoteProcess与
Zygote开始通讯,两者IPC通讯的方式也很直接,使用了Socket完成操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//Process.java
public class Process {
...
public static final String ZYGOTE_SOCKET = "zygote" ;
public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary" ;
public static final ZygoteProcess zygoteProcess = new ZygoteProcess ( ZYGOTE_SOCKET , SECONDARY_ZYGOTE_SOCKET );
...
}
//ZygoteProcess.java
public ZygoteProcess ( LocalSocketAddress primarySocket , LocalSocketAddress secondarySocket ) {
//socket的句柄 为“zygote”
mSocket = primarySocket ;
mSecondarySocket = secondarySocket ;
}
private Process . ProcessStartResult startViaZygote (...) throws ZygoteStartFailedEx {
...
return zygoteSendArgsAndGetResult ( openZygoteSocketIfNeeded ( abi ), argsForZygote );
}
private ZygoteState openZygoteSocketIfNeeded ( String abi ) throws ZygoteStartFailedEx {
...
primaryZygoteState = ZygoteState . connect ( mSocket );
...
}
private static Process . ProcessStartResult zygoteSendArgsAndGetResult ( ZygoteState zygoteState , ArrayList < String > args ) throws ZygoteStartFailedEx {
final BufferedWriter writer = zygoteState . writer ;
final DataInputStream inputStream = zygoteState . inputStream ;
//socket通讯
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 ();
...
}
在Zygote进程这边,会收到socket通讯请求,然后处理请求,这里我们先梳理一下Zygote进程的一些东西。按照
android系统启动了流程,Zygote进程初始化会在ZygoteInit.java文件中来完成。
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ZygoteInit {
public static void main ( String argv []) {
...
ZygoteServer zygoteServer = new ZygoteServer ();
...
//循环处理其他进程请求
caller = zygoteServer . runSelectLoop ( abiList );
//如果是fork子进程,在执行完任务之后就退出
if ( caller != null ) {
caller . run ();
}
}
}
启动ZygoteInit之后,zygoteServer就会一直处于循环等待和处理消息的状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//ZygoteServer.java
Runnable runSelectLoop ( String abiList ) {
while ( true ) {
...
//等待接受请求
ZygoteConnection newPeer = acceptCommandPeer ( abiList );
peers . add ( newPeer );
fds . add ( newPeer . getFileDesciptor ());
...
ZygoteConnection connection = peers . get ( i );
//处理请求
final Runnable command = connection . processOneCommand ( this );
if ( mIsForkChild ) {
if ( command == null ) {
throw new IllegalStateException ( "command == null" );
}
return command ;
}
}
}
}
private ZygoteConnection acceptCommandPeer ( String abiList ) {
//等待
return createNewConnection ( mServerSocket . accept (), abiList );
}
获得消息之后就交给ZygoteConnection来处理具体事务
1
2
3
4
5
6
7
8
9
10
11
12
13
//ZygoteConnection.java
Runnable processOneCommand ( ZygoteServer zygoteServer ) {
//孵化操作
pid = Zygote . forkAndSpecialize ( parsedArgs . uid , parsedArgs . gid , parsedArgs . gids ,
parsedArgs . runtimeFlags , rlimits , parsedArgs . mountExternal , parsedArgs . seInfo ,
parsedArgs . niceName , fdsToClose , fdsToIgnore , parsedArgs . startChildZygote ,
parsedArgs . instructionSet , parsedArgs . appDataDir );
if ( pid == 0 ) {
// in child
...
return handleChildProc ( parsedArgs , descriptors , childPipeFd , parsedArgs . startChildZygote );
}
}
handleChildProc会调用ZygoteInit的静态方法childZygoteInit,childZygoteInit又会调用RuntimeInit的findStaticMain
来真正创建新应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//RuntimeInit.java
protected static Runnable findStaticMain ( String className , String [] argv ,
ClassLoader classLoader ) {
Class <?> cl ;
try {
cl = Class . forName ( className , true , classLoader );
} catch ( ClassNotFoundException ex ) {
throw new RuntimeException (
"Missing class when invoking static main " + className ,
ex );
}
Method m ;
try {
m = cl . getMethod ( "main" , new Class [] { String []. class });
} catch ( NoSuchMethodException ex ) {
throw new RuntimeException (
"Missing static main on " + className , ex );
} catch ( SecurityException ex ) {
throw new RuntimeException (
"Problem getting static main on " + className , ex );
}
int modifiers = m . getModifiers ();
if (! ( Modifier . isStatic ( modifiers ) && Modifier . isPublic ( modifiers ))) {
throw new RuntimeException (
"Main method is not public and static on " + className );
}
return new MethodAndArgsCaller ( m , argv );
}
findStaticMain方法实际就是执行了反射操作,调用的传入类的main方法,而传入的类就是ActivityThread.java
到此才真正启动了应用
这里需要注意的是Zygote的孵化操作,这一部分其实完全需要新开一篇来讲,但是为了完全理解,我就再多嘴一下。
孵化新进程之后,建立应用就不用再重新加载资源,直接使用之前的,这项技术称为COW,如果当前进程是用于孵化新应用的
子进程的话,在新建应用成功之后,当前孵化的Zygote就会退出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ZygoteInit {
public static void main ( String argv []) {
String socketName = "zygote" ;
...
ZygoteServer zygoteServer = new ZygoteServer ();
...
//循环处理其他进程请求
caller = zygoteServer . runSelectLoop ( abiList );
//如果是fork子进程,在执行完任务之后就退出
if ( caller != null ) {
caller . run ();
}
}
}
还有一个地方就是上述Socket实际是由android本地生成的一个通讯管道,这块,目前笔者还不是很清楚,暂时只能记录下来
待后续补上。
4.ActivityThread 初始化
终于走到了最后一步,我们的应用的初始化这这里开始,上一阶段最后,系统反射了ActivityThread.java的main方法
main方法中会生成一个ActivityThread实例,同时准备该进程的mainLooper,和Handler。
1
2
3
4
5
6
7
8
9
10
11
12
13
public final class ActivityThread extends ClientTransactionHandler {
public static void main ( String [] args ) {
...
ActivityThread thread = new ActivityThread ();
thread . attach ( false , startSeq );
if ( sMainThreadHandler == null ) {
sMainThreadHandler = thread . getHandler ();
}
Looper . loop ();
throw new RuntimeException ( "Main thread loop unexpectedly exited" );
}
}
当前的ActivityThread会调用attach来关联到AMS。AMS 会获取当前的ActivityThread的启动资料记录
具体是根据当前进程的pid。
1
2
3
4
5
6
7
8
9
10
11
12
13
private final boolean attachApplicationLocked ( IApplicationThread thread , int pid , int callingUid , long startSeq ) {
ProcessRecord app ;
long startTime = SystemClock . uptimeMillis ();
if ( pid != MY_PID && pid >= 0 ) {
synchronized ( mPidsSelfLocked ) {
//获取启动资料
app = mPidsSelfLocked . get ( pid );
}
} else {
app = null ;
}
...
}
上图中的mPidsSelfLocked的存储操作发生在向Zygote请求fork新进程之后,将请求到的pid和新进程的信息都保存在mPidsSelfLocked中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//ActivityManagerService.java
private boolean startProcessLocked ( String hostingType , String hostingNameStr , String entryPoint ,
ProcessRecord app , int uid , int [] gids , int runtimeFlags , int mountExternal ,
String seInfo , String requiredAbi , String instructionSet , String invokeWith ,
long startTime ) {
...
if ( mConstants . FLAG_PROCESS_START_ASYNC ) {
...
//建立新进程
final ProcessStartResult startResult = startProcess ( app . hostingType , entryPoint ,
app , app . startUid , gids , runtimeFlags , mountExternal , app . seInfo ,
requiredAbi , instructionSet , invokeWith , app . startTime );
//存储新进程信息
handleProcessStartedLocked ( app , startResult , startSeq );
...
return true ;
} else {
...
//建立新进程
final ProcessStartResult startResult = startProcess ( app . hostingType , entryPoint ,
app , app . startUid , gids , runtimeFlags , mountExternal , app . seInfo ,
requiredAbi , instructionSet , invokeWith , app . startTime );
//存储新进程信息
handleProcessStartedLocked ( app , startResult , startSeq );
...
return app . pid > 0 ;
}
}
private boolean handleProcessStartedLocked ( ProcessRecord app , int pid , boolean usingWrapper , long expectedStartSeq , boolean procAttached ) {
...
synchronized ( mPidsSelfLocked ) {
this . mPidsSelfLocked . put ( pid , app );
...
return true ;
}
}
获取到的ProcessRecord app会在后续的用于查找需要启动的Activity的信息,最后在ActivityStackSupervisor的realStartActivityLocked
发起启动Activity的事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
final boolean realStartActivityLocked ( ActivityRecord r , ProcessRecord app , boolean andResume , boolean checkConfig ) throws RemoteException {
...
//准备了Launch和Resume的事务,向ActivityThread发送执行
final ClientTransaction clientTransaction = ClientTransaction . obtain ( app . thread , r . appToken );
clientTransaction . addCallback ( LaunchActivityItem . obtain ( new Intent ( r . intent ),
System . identityHashCode ( r ), r . info ,
mergedConfiguration . getGlobalConfiguration (),
mergedConfiguration . getOverrideConfiguration (), r . compat ,
r . launchedFromPackage , task . voiceInteractor , app . repProcState , r . icicle ,
r . persistentState , results , newIntents , mService . isNextTransitionForward (),
profilerInfo ));
final ActivityLifecycleItem lifecycleItem ;
if ( andResume ) {
lifecycleItem = ResumeActivityItem . obtain ( mService . isNextTransitionForward ());
} else {
lifecycleItem = PauseActivityItem . obtain ();
}
clientTransaction . setLifecycleStateRequest ( lifecycleItem );
mService . getLifecycleManager (). scheduleTransaction ( clientTransaction );
}
之后的过程跟第二步分析的Pause过程大致相同,不再多言
总结
本篇文章着重大致分析Activity的启动的完整流程,其实一个Activity的启动情况很多,不同的生命周期有着不同的
调用流程,这里也就不一一描述了。同时,笔者深感对于Zygote的启动过程和其特有的Socket通讯还有很多迷惑之处,后续会继续
深入分析,继续耕耘。本篇文章调用时序跳转过多,特此留下一张简图,以供参考。