启动Activity一般有多种方式,常见的有三种:
-
在Launcher桌面点击app图标
-
调用startActivity启动一个Activity
-
命令am start启动
这三种方式在服务端的处理方式基本相同,客户端的请求方式也差别不大,理解其中之一就可以类推到其他方式。本文结合案例分析在Launcher桌面点击app图标启动应用的方式,再简要给出其他两种方式的区别。
案例
应用名称为TestLaunchApp,包含A和B两个Activity,A为入口类,点击按钮跳转到B
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
42
43
|
packagecom.example.startapptest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
publicclassAextendsActivity{
privatefinalstaticStringTAG="StartAppTest";
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG,"A"+"--------------onCreate()");
setContentView(R.layout.a_layout);
}
@Override
protectedvoidonResume(){
// TODO Auto-generated method stub
Log.i(TAG,"A"+"--------------onResume()");
super.onResume();
}
@Override
protectedvoidonPause(){
// TODO Auto-generated method stub
Log.i(TAG,"A"+"--------------onPause()");
super.onPause();
}
publicvoidfuncA(View view){
startActivity(newIntent("com.feeyan.www.b_activity"));
}
@Override
publicvoidonBackPressed(){
// TODO Auto-generated method stub
finish();
super.onBackPressed();
}
}
|
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
|
packagecom.example.startapptest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
publicclassBextendsActivity{
privatefinalstaticStringTAG="StartAppTest";
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG,"B"+"--------------onCreate()");
setContentView(R.layout.b_layout);
}
@Override
protectedvoidonResume(){
Log.i(TAG,"B"+"--------------onResume()");
super.onResume();
}
@Override
protectedvoidonPause(){
// TODO Auto-generated method stub
Log.i(TAG,"B"+"--------------onPause()");
super.onPause();
}
publicvoidfuncB(View view){
startActivity(newIntent("com.feeyan.www.a_activity"));
finish();
}
}
|
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
|
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<Button
android:id="@+id/button_a_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:onClick="funcA"
android:text="@string/button_a_text"
android:textSize="20sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="154dp"
android:text="@string/page_a_text"
android:textSize="30sp"/>
</RelativeLayout>
|
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
|
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<Button
android:id="@+id/button_b_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:onClick="funcB"
android:text="@string/button_b_text"
android:textSize="20sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/button_b_id"
android:layout_centerHorizontal="true"
android:layout_marginBottom="140dp"
android:text="@string/page_b_text"
android:textSize="30sp"/>
</RelativeLayout>
|
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
42
43
44
45
|
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.startapptest"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="21"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".A"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="com.feeyan.www.a_activity">
</action>
<category android:name="android.intent.category.DEFAULT">
</category>
</intent-filter>
</activity>
<activity
android:name=".B"
android:label="@string/app_name">
<intent-filter>
<action android:name="com.feeyan.www.b_activity">
</action>
<category android:name="android.intent.category.DEFAULT">
</category>
</intent-filter>
</activity>
</application>
</manifest>
|
当点击A中的按钮时,跳转到B,先暂停A,A从前台转入到后台,开始执行B的onCreate、onResume方法,B被调入到栈顶,B现在可见,日志为:
1
2
3
4
5
|
I/StartAppTest(26256):A--------------onCreate()
I/StartAppTest(26256):A--------------onResume()
I/StartAppTest(26256):A--------------onPause()
I/StartAppTest(26256):B--------------onCreate()
I/StartAppTest(26256):B--------------onResume()
|
启动一个Activity的标志是开始执行生命周期onCreate方法,转入到后台的标志是onPause方法,正在运行、可见的标志是onResume方法,本文将从源码着手,分析启动activity的过程。
1. 在Launcher桌面点击app图标启动入口Activity
本文基于android5.1.1源码,在Launcher主页面当点击图表时,调用过程为:
onClick—->……—->startActivitySafely—->startActivity(v, intent, tag)—->startActivity(intent, optsBundle);
源码:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
intent设置了FLAG_ACTIVITY_NEW_TASK标志,表示开启一个新任务,在新任务中启动activity,本案例没有特殊的动画设置,optsBundle为null。
framework层客户端
过程1 frameworks\base\core\java\android\app\Activity.java
startActivity所属的对象是this,表示当前启动类Launcher对象,下一步执行到Activity的startActivity方法,过程为:
startActivity(Intent intent, @Nullable Bundle options)
—-> startActivityForResult(intent, -1)
—-> startActivityForResult(intent, requestCode, null)
注:由于源码较长,本文不贴上全部源码,只给出方法名称、部分代码以及源码路径
action为字符串“com.feeyan.www.b_activity”,requestCode等于-1,如果>=0, B被启动后会返回到A中,且A中的onActivityResult()方法会被调用。即便是调用startActivity,还是会调到 startActivityForResult,只不过此时requestCode是-1了。
mParent:如果不为空,表示当前Activity有子类,本案例没有子类,为空,进程执行到:
1
2
3
4
|
Instrumentation.ActivityResult ar=
mInstrumentation.execStartActivity(
this,mMainThread.getApplicationThread(),mToken,this,
intent,requestCode,options);
|
要搞懂源码,最关键的就是弄清楚参数的具体含义,源码中参数有时候多达十几个,如果不清楚参数的来龙去脉,无从分析。
this:当前进程还是在Launcher所在的进程,this就是Launcher类的一个对象。
mMainThread.getApplicationThread():返回一个ApplicationThread对象类型,也是一个IBinder对象类型,,mMainThread是ActivityThread的一个对象,代表当前Launcher主线程对象
mToken:也是一个IBinder对象类型
requestCode仍为-1,options为null
过程2 frameworks\base\core\java\android\app\Instrumentation.java
1
2
3
4
5
|
publicActivityResult execStartActivity(
Context who,IBinder contextThread,IBinder token,Activity target,
Intent intent,intrequestCode,Bundle options){
......
}
|
this对象传给execStartActivity,该函数的第一个形参who是Context类型,第4个形参target是Activity类型,其实际类型都是Launcher对象,只是名字起的不一样,这就是一种共识,代表着某种含义,读者看到名字就能猜得着其用意。
1
| IApplicationThread whoThread=(IApplicationThread)contextThread; |
contextThread既是IBinder对象,也是IApplicationThread对象,此处向上转型为IApplicationThread对象,
1
2
3
4
5
|
intresult=ActivityManagerNative.getDefault()
.startActivity(whoThread,who.getBasePackageName(),intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token,target!=null?target.mEmbeddedID:null,
requestCode,0,null,options);
|
ActivityManagerNative实现了IActivityManager接口,调用getDefault方法最终返回ActivityManagerService的代理类ActivityManagerProxy的一个对象,于是,startActivity便转入到ActivityManagerProxy对象中开始执行。
过程3 frameworks\base\core\java\android\app\ActivityManagerNative.java
1
2
3
4
5
|
publicintstartActivity(IApplicationThread caller,StringcallingPackage,Intent intent,
StringresolvedType,IBinder resultTo,StringresultWho,intrequestCode,
intstartFlags,ProfilerInfo profilerInfo,Bundle options)throwsRemoteException{
......
}
|
分析参数时,结合实际参数来看,否则单独看形参不能确定具体含义。
caller:前面传过来的值,代表ApplicationThread对象
callingPackage:由who.getBasePackageName()的值传递而来,who是Context对象,getBasePackageName()的实现在ContextImple中,返回当前启动类的包名,就是Launcher的包名
resolvedType:解析当前发送的Intent的MIME数据类型,本案例没有为intent设置type、data属性,因此,intent.resolveTypeIfNeeded(who.getContentResolver())返回null
resultTo:Ibinder对象,具体含义后面继续看
resultWho:由target != null ? target.mEmbeddedID : null得来,target是activity对象即启动类Launcher对象,不为空,该语句返回mEmbeddedID,一个id号,这个值必须要从Launcher这个apk启动中获得,在Launcher启动后,代表Launcher启动类的对象是一个ActivityClientRecord对象,该对象所属的类路径为:
frameworks\base\core\java\android\app\ActivityThread.java
该对象的scheduleLaunchActivity方法中,有一句:
ActivityClientRecord r = new ActivityClientRecord();
在ActivityClientRecord的构造方法中会把embeddedID初始化为null,因此mEmbeddedID为空
startFlags:整型值,已经初始化为0,具体作用后面分析
profilerInfo:为null,具体作用后面分析
这些参数都会被打包到持久化类Parcel的对象data中,把data作为transact的参数进行跨进程传递:
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
该方法通过binder通信机制会传递到ActivityManagerNative的onTransact方法,在onTransact方法中,根据发送命令START_ACTIVITY_TRANSACTION找到case处理语句,把data中的数据取出来赋给相应的变量,继续调用:
1
2
|
intresult=startActivity(app,callingPackage,intent,resolvedType,
resultTo,resultWho,requestCode,startFlags,profilerInfo,options);
|
startActivity最终会调用到服务端ActivityManagerService中。此时,进程也从启动类Launcher所在的进程切换到了服务端进程。从ActivityManagerNative.getDefault().startActivity一直到ActivityManagerService的startActivity方法,主要由binder通信实现,该过程相当复杂,但binder通信不属于本文重点,而且binder机制贯穿于整个Android系统、内核、驱动部分,本文如再遇到binder通信机制,直接给出最终被调用的类及方法。
在进入到服务端之前,看看客户端到底做了哪些工作?
主要是获得了一些必要的参数:IApplicationThread对象、启动类包名、Intent的MIME数据类型、IApplicationToken.Stub类型对象resultTo等,除了这些,没有其他特殊的操作了,其实最关键的操作还是在服务端进行的,这就是为何本文一开始提到无论哪种启动方式,客户端都是大同小异。
framework层服务端
过程4 frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
startActivity—->startActivityAsUser—->mStackSupervisor.startActivityMayWait
1
2
3
|
mStackSupervisor.startActivityMayWait(caller,-1,callingPackage,intent,
resolvedType,null,null,resultTo,resultWho,requestCode,startFlags,
profilerInfo,null,null,options,userId,null,null);
|
这几步没有太多的操作,获得了一个用户id,用来作一些检测
过程5 frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
1
2
3
4
5
6
7
8
|
finalintstartActivityMayWait(IApplicationThread caller,intcallingUid,
StringcallingPackage,Intent intent,StringresolvedType,
IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,
IBinder resultTo,StringresultWho,intrequestCode,intstartFlags,
ProfilerInfo profilerInfo,WaitResult outResult,Configuration config,
Bundle options,intuserId,IActivityContainer iContainer,TaskRecord inTask){
......
}
|
先看多了哪些参数:
voiceSession:IVoiceInteractionSession对象类型,被初始化null。IVoiceInteractionSession本是一个aidl远程接口,定义了任务栈启动taskStarted、任务栈结束taskFinished等方法
voiceInteractor:IVoiceInteractor对象类型,被初始化为null。IVoiceInteractor也是一个aidl远程接口
outResult:WaitResult对象类型,被初始化为null。WaitResult是IActivityManager的内部类,实现了Parcelable接口,主要用来保存启动Activity后返回的结果信息
config:Configuration对象类型,被初始化为null。Configuration描述了所有设备相关的配置信息,比如,本地语言、屏幕大小、屏幕方向、输入法模式,可以通过Resources的getConfiguration获得改对象
iContainer:IActivityContainer对象类型,被初始化为null。IActivityContainer也是一个aidl远程接口
inTask:TaskRecord对象类型,被初始化为null。TaskRecord很重要,会经常用到此类,描述一个任务栈,每个任务栈可以包含多个Activity对象,每个TaskRecord对象都有一个当前栈ActivityStack的引用,每个栈可以对应多个TaskRecord对象
除了这些多余的参数,其他参数都是从客户端传递而来。
1
| booleancomponentSpecified=intent.getComponent()!=null; |
getComponent方法返回一个ComponentName对象,该对象表示通过intent要启动的组件类,本案例就对应A这个Activity,ComponentName对象一般用包名和类名标识一个组件,因此,componentSpecified为true
1
| intent=newIntent(intent); |
根据客户端传递过来的Intent对象重新构建一个Intent对象,这样做是不要破坏客户端传递来的Intent对象
1
2
3
4
5
6
7
|
ActivityInfo aInfo=resolveActivity(intent,resolvedType,startFlags,
profilerInfo,userId);
ActivityInfo resolveActivity(Intent intent,StringresolvedType,intstartFlags,
ProfilerInfo profilerInfo,intuserId){
......
}
|
resolveActivity方法开始解析Intent对象,返回intent对应的目标Activity类的ActivityInfo对象,ActivityInfo类专门用来描述AndroidManifest.xml中Activity、Receiver组件信息的,本案例返回的就是A这个类对应的信息,ActivityInfo的成员变量name就是类名称,packageName就是包名称,对应本案例分别为com.example.startapptest.A和com.example.startapptest
1
2
3
4
5
6
7
8
|
if(callingUid>=0){
callingPid=-1;
}elseif(caller==null){
callingPid=realCallingPid;
callingUid=realCallingUid;
}else{
callingPid=callingUid=-1;
}
|
callingUid传过来时为-1,call又不为空,进程执行else字句callingPid = callingUid = -1;
1
2
3
4
5
6
7
8
|
ActivityContainer container=(ActivityContainer)iContainer;
finalActivityStack stack;
if(container==null||container.mStack.isOnHomeDisplay()){
stack=getFocusedStack();
}else{
stack=container.mStack;
}
|
iContainer为空,那么container也为空,调用getFocusedStack获得当前正在前台的栈,也就是Launcher所在的栈。
1
2
3
4
|
if(aInfo!=null&&
(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE)!=0){
......
}
|
aInfo虽然不为空,但aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE却为0,因为没有设置这种属性,因此跳过该if语句,开始执行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
intres=startActivityLocked(caller,intent,resolvedType,aInfo,
voiceSession,voiceInteractor,resultTo,resultWho,
requestCode,callingPid,callingUid,callingPackage,
realCallingPid,realCallingUid,startFlags,options,
componentSpecified,null,container,inTask);
finalintstartActivityLocked(IApplicationThread caller,
Intent intent,StringresolvedType,ActivityInfo aInfo,
IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,
IBinder resultTo,StringresultWho,intrequestCode,
intcallingPid,intcallingUid,StringcallingPackage,
intrealCallingPid,intrealCallingUid,intstartFlags,Bundle options,
booleancomponentSpecified,ActivityRecord[]outActivity,ActivityContainer container,
TaskRecord inTask){
......
}
|
callingPid:int型变量,看字面意思与pid相关,具体含义后面再看
callingUid:int型变量,看字面意思与uid相关,具体含义后面再看
realCallingPid:启动类所在进程的pid,本案例是Launcher
realCallingUid:启动类所在进程的uid,本案例是Launcher
componentSpecified:为true,表明intent对应的目标Activity类存在
outActivity:ActivityRecord数组名称,初始化为null,ActivityRecord是一个动态生成的对象,代表Activity在历史栈中的记录,ActivityRecord包含了Activity所有信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ProcessRecord callerApp=null;
if(caller!=null){
callerApp=mService.getRecordForAppLocked(caller);
if(callerApp!=null){
callingPid=callerApp.pid;
callingUid=callerApp.info.uid;
}else{
Slog.w(TAG,"Unable to find app for caller "+caller
+" (pid="+callingPid+") when starting: "
+intent.toString());
err=ActivityManager.START_PERMISSION_DENIED;
}
}
|
mService是ActivityManagerService对象,通过getRecordForAppLocked方法获得启动类所在进程的进程记录对象ProcessRecord。参数caller是IApplicationThread对象,前文提到过,实际是ApplicationThread对象,代表Launcher类的主线程,caller在ActivityManagerService和ActivityThread两个进程之间完成通信,现在终于明白了,为何在startActivity时会带着这样一个参数:服务端通过该参数获得客户端进程信息,该参数起到桥梁作用。
callerApp不为空,分别获得启动类进程的pid和uid保存到callingPid、callingUid中,这个callingPid和之前的realCallingPid获得的值一样,都是Launcher进程pid
1
2
3
4
5
6
7
8
9
10
11
12
|
ActivityRecord sourceRecord=null;
ActivityRecord resultRecord=null;
if(resultTo!=null){
sourceRecord=isInAnyStackLocked(resultTo);
if(DEBUG_RESULTS)Slog.v(
TAG,"Will send result to "+resultTo+" "+sourceRecord);
if(sourceRecord!=null){
if(requestCode>=0&&!sourceRecord.finishing){
resultRecord=sourceRecord;
}
}
}
|
定义了两个ActivityRecord变量sourceRecord、resultRecord,用来对应启动类和目标类。上文提到,resultTo属于IBinder对象,属于启动方的对象。isInAnyStackLocked方法根据启动类的标记resultTo对象在列表栈中找出对应的栈,再在栈顶找到Activity记录保存到sourceRecord中。
1
| finalintlaunchFlags=intent.getFlags(); |
上文提到,intent一开始在客户端就被设置了FLAG_ACTIVITY_NEW_TASK标志,getFlags方法便取出该标志,保存到launchFlags变量中。
1
2
3
|
ActivityRecordr=newActivityRecord(mService,callerApp,callingUid,callingPackage,
intent,resolvedType,aInfo,mService.mConfiguration,resultRecord,resultWho,
requestCode,componentSpecified,this,container,options);
|
创建一个ActivityRecord对象,这个ActivityRecord对象具体有什么作用?看看参数具体含义
前4个参数代表了启动类Launcher,第5~7参数(Intent,resolvedType, aInfo)代表了目标类
mService.mConfiguration表示系统配置,resultRecord代表目标类,resultWho代表启动类的一个id号,为空
componentSpecified为true
this:代表当前ActivityStackSupervisor对象
从参数来看,该类既包含启动类的属性,又包含目标类属性,推测该类应该用来表达目标类,后面可以证明。
startActivityLocked方法的作用:获得启动类进程信息、pid、uid,创建ActivityRecord类对象sourceRecord保存启动类信息,创建ActivityRecord对象r,暂时推测代表目标类,具体含义后面分析。进程继续调用:
1
2
|
err=startActivityUncheckedLocked(r,sourceRecord,voiceSession,voiceInteractor,
startFlags,true,options,inTask);
|
开始调用下一步操作,第一个参数就是刚才创建的ActivityRecord对象;第二个参数是启动类对象,不为空;
1
2
3
4
5
|
finalintstartActivityUncheckedLocked(ActivityRecordr,ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,intstartFlags,
booleandoResume,Bundle options,TaskRecord inTask){
......
}
|
1
2
|
finalIntent intent=r.intent;
finalintcallingUid=r.launchedFromUid;
|
r.intent就是传递而来的intent对象,r.launchedFromUid就是启动类Launcher的uid
1
2
3
|
finalbooleanlaunchSingleTop=r.launchMode==ActivityInfo.LAUNCH_SINGLE_TOP;
finalbooleanlaunchSingleInstance=r.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE;
finalbooleanlaunchSingleTask=r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK;
|
这三个变量代表目标类的启动模式,本案例就是A的启动模式,没有任何设置,默认为Standard模式,因而这三个变量都是false
1
| mUserLeaving=(launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION)==0; |
FLAG_ACTIVITY_NO_USER_ACTION:当启动目标Activity时Intent设置了此标志,前台正在行的Activity在暂停之前(执行onPaused方法)不会回调onUserLeaveHint方法。NO_USER_ACTION表示非用户操作,如果设置了此标志,表示非用户行为时不会回调onUserLeaveHint。比如,闹钟响了、来电话了,这属于非用户操作,如果设置了此标志,就不会回调onUserLeaveHint,相反,如果是用户操作行为比如按下HOME按键,返回键等,就会回调onUserLeaveHint。本案例中发送给A的Intent没有设置该标志,mUserLeaving为true,表明不是非用户操作行为。
1
2
|
ActivityRecord notTop=
(launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)!=0?r:null;
|
Intent没有设置FLAG_ACTIVITY_PREVIOUS_IS_TOP,notTop为空
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
if(sourceRecord!=null){
if(sourceRecord.finishing){
// If the source is finishing, we can't further count it as our source. This
// is because the task it is associated with may now be empty and on its way out,
// so we don't want to blindly throw it in to that task. Instead we will take
// the NEW_TASK flow and try to find a task for it. But save the task information
// so it can be used when creating the new task.
if((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)==0){
Slog.w(TAG,"startActivity called from finishing "+sourceRecord
+"; forcing "+"Intent.FLAG_ACTIVITY_NEW_TASK for: "+intent);
launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
newTaskInfo=sourceRecord.info;
newTaskIntent=sourceRecord.task.intent;
}
sourceRecord=null;
sourceStack=null;
}else{
sourceStack=sourceRecord.task.stack;
}
}else{
sourceStack=null;
}
|
sourceRecord不为空,变量finishing为空,因为此时启动类Launcher还在前台,没有进入到销毁列表中,进程执行else语句,得到启动类所在的栈对象并保存到sourceStack中。
1
2
3
4
5
6
7
8
9
|
if(((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0&&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK)==0)
||launchSingleInstance||launchSingleTask){
// If bring to front is requested, and no result is requested and we have not
// been given an explicit task to launch in to, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
if(inTask==null&&r.resultTo==null){
......
|
Intent没有设置FLAG_ACTIVITY_MULTIPLE_TASK,resultTo和startActivityLocked参数中resultTo不是一个意思,前者是在startActivityLocked函数中创建的ActivityRecord对象resultRecord,代表目标类一方,被初始化为空,而后者代表启动类一方,不能混淆。
1
2
3
4
|
ActivityRecord intentActivity=!launchSingleInstance?
findTaskLocked(r):findActivityLocked(intent,r.info);
if(intentActivity!=null){
......
|
启动A时没有设置启动模式,采用是默认的标准模式,因此launchSingleInstance为false,调用findTaskLocked(r)在当前栈顶中查询是否有目标类,如果有,就返回该类,否则,返回空。因为首次启动A,因此栈中肯定没有A,返回空保存到intentActivity变量中,这样的话,if语句不成立。如果栈中有实例,再次启动时就会执行这段代码。
1
2
3
4
5
6
7
8
9
|
if(r.packageName!=null){
ActivityStack topStack=getFocusedStack();
ActivityRecord top=topStack.topRunningNonDelayedActivityLocked(notTop);
if(top!=null&&r.resultTo==null){
if(top.realActivity.equals(r.realActivity)&&top.userId==r.userId){
......
}else{
......
}
|
目标类包名肯定不为空,执行if条件,getFocusedStack返回当前栈,topRunningNonDelayedActivityLocked返回当前ActivityRecord对象保存到top中,肯定不为空;top.realActivity表示启动类,r.realActivity表示目标类,本案例前者是Launcher,后者是A,两者肯定不相等,因此if语句不成立,跳过此段。如果成立的话,就会在当前栈中找到已存在的实例继续使用。
既然当前栈中没有已存在实例,那么只能新创建一个任务栈,继续看:
1
2
3
4
5
6
7
8
|
booleannewTask=false;
booleankeepCurTransition=false;
TaskRecord taskToAffiliate=launchTaskBehind&&sourceRecord!=null?
sourceRecord.task:null;
// Should this be considered a new task?
if(r.resultTo==null&&inTask==null&&!addingToTask
&&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){
......
|
此if语句成立,launchTaskBehind为空,那么taskToAffiliate也为空
1
2
|
newTask=true;
targetStack=adjustStackFocus(r,newTask);
|
newTask代表新建一个任务的标志,设为true;adjustStackFocus获得一个ActivityStack保存到targetStack变量作为目标类的栈;
1
2
3
4
5
6
7
8
9
|
if(reuseTask==null){
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo!=null?newTaskInfo:r.info,
newTaskIntent!=null?newTaskIntent:intent,
voiceSession,voiceInteractor,!launchTaskBehind/* toTop */),
taskToAffiliate);
if(DEBUG_TASKS)Slog.v(TAG,"Starting new activity "+r+" in new task "+
r.task);
}
|
createTaskRecord创建TaskRecord对象并放到栈顶,然后再放到目标类ActivityRecord的task变量中
1
2
3
4
5
6
|
targetStack.mLastPausedActivity=null;
targetStack.startActivityLocked(r,newTask,doResume,keepCurTransition,options);
if(!launchTaskBehind){
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r,"startedActivity");
}
|
调用startActivityLocked进行下一步操作
startActivityUncheckedLocked函数非常复杂,最关键的就是查询是否有已存在的TaskRcord作为目标类的任务栈,如果栈中有就复用,否则就创建一个新的TaskRcord对象作为目标类的任务栈。该函数涉及到了FLAG标志,启动模式的判断等,其目的就是找到一个合适的任务栈,为何要找到这个栈,就是因为Activity在执行时以栈这个数据结构来管理。
过程6 frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
1
2
|
finalvoidstartActivityLocked(ActivityRecordr,booleannewTask,
booleandoResume,booleankeepCurTransition,Bundle options)
|
第一个参数对应目标类对象记录,newTask为true,表示新建了一个任务栈,doResume为true,keepCurTransition为false。
1
2
|
TaskRecord rTask=r.task;
finalinttaskId=rTask.taskId;
|
r.task就是在startActivityUncheckedLocked中创建的目标类的RaskRecord对象,取出来保存到rRask变量中
1
2
3
4
5
6
7
|
if(!r.mLaunchTaskBehind&&(taskForIdLocked(taskId)==null||newTask)){
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
insertTaskAtTop(rTask);
mWindowManager.moveTaskToTop(taskId);
}
|
mLaunchTaskBehind在上文得知为空,taskForIdLocked在历史栈中查询是否含有id号为目标类所在的栈id,如果有,表明目标类之前已经被创建过,现在开始复用该对象,属于非首次启动,否则为首次启动对象,本案例首次启动A,因此,此函数返回null;newTask传递过来为true,if语句成立,调用insertTaskAtTop函数把新创建的TaskRecord对象插入到列表mTaskHistory的尾部,也就是插入到历史栈顶;
1
2
3
|
if(doResume){
mStackSupervisor.resumeTopActivitiesLocked(this,r,options);
}
|
过程7 frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
1
2
|
booleanresumeTopActivitiesLocked(ActivityStack targetStack,ActivityRecord target,
Bundle targetOptions)
|
this对象表示当前对象ActivityStack,此ActivityStack是新建的对象,不是Launcher所在的ActivityStack,是在startActivityUncheckedLocked中的adjustStackFocus方法获得的,目的就是把新创建的任务插入到该ActivityStack对象中,这个对象就代表了目标类所属的栈
第二个参数r就表示目标类对象记录,第三个参数依然为null
1
2
3
|
if(isFrontStack(targetStack)){
result=targetStack.resumeTopActivityLocked(target,targetOptions);
}
|
isFrontStack判断新获得的ActivityStack对象位于栈顶,判断为真,执行if语句,调用resumeTopActivityLocked(target, targetOptions)
过程8 frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
1
2
3
|
finalbooleanresumeTopActivityLocked(ActivityRecord prev,Bundle options){
......
}
|
第一个参数prev表示目标类ActivityRecord对象,第二个传递过来为空
1
2
3
4
5
6
7
8
|
try{
// Protect against recursion.
mStackSupervisor.inResumeTopActivity=true;
......
result=resumeTopActivityInnerLocked(prev,options);
}finally{
mStackSupervisor.inResumeTopActivity=false;
}
|
继续调用resumeTopActivityInnerLocked方法,再调用resumeTopActivityInnerLocked
1
2
3
|
finalbooleanresumeTopActivityInnerLocked(ActivityRecord prev,Bundle options){
......
}
|
1
2
3
4
5
6
7
|
// Find the first activity that is not finishing.
finalActivityRecord next=topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
finalbooleanuserLeaving=mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving=false;
|
topRunningActivityLocked方法找到栈顶的ActivityRecord对象,此处对应着A
mStackSupervisor.mUserLeaving的值在过程5中被设置为true,此处取出来赋值给userLeaving,表明是用户操作行为(按下返回键,HOME按键等);无论是true还是false,此处还是再复位一下,重新设置为false
1
2
3
4
5
|
booleandontWaitForPause=(next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING)!=0;
booleanpausing=mStackSupervisor.pauseBackStacks(userLeaving,true,dontWaitForPause);
if(mResumedActivity!=null){
pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);
}
|
目标类A没有设置FLAG_RESUME_WHILE_PAUSING标志,dontWaitForPause为false
pauseBackStacks函数返回false赋给pausing变量,mResumedActivity表示当前正在前台运行的Activity,就是Launcher,不为空,进程调用startPausingLocked继续执行
1
2
3
4
5
6
|
pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);
finalbooleanstartPausingLocked(booleanuserLeaving,booleanuiSleeping,booleanresuming,
booleandontWait){
......
}
|
startPausingLocked开始暂停当前Activity,如果成功,返回true,否则false
4个参数分别为false,false,true,false
1
2
3
4
|
ActivityRecord prev=mResumedActivity;
mResumedActivity=null;
mPausingActivity=prev;
mLastPausedActivity=prev;
|
mResumedActivity代表Launcher,先赋值给prev再置空;prev赋值给mPausingActivity,表明即将要暂停的Activity是Launcher,mLastPausedActivity也赋值为prev,表示刚刚暂停的Activity是哪个
1
2
3
4
5
6
|
if(prev.app!=null&&prev.app.thread!=null){
......
prev.app.thread.schedulePauseActivity(prev.appToken,prev.finishing,
userLeaving,prev.configChangeFlags,dontWait);
......
}
|
prev.app表示Launcher进程信息,不为空;prev.app.thread是一个IApplicationThread对象,对应Launcher也不为空,进程继续调用schedulePauseActivity方法,此处是一个Binder进程间通信,下一步调用到ApplicationThread对象的schedulePauseActivity方法中,ApplicationThread是ActivityThread内部类
过程9 frameworks\base\core\java\android\app\ActivityThread.java
1
2
3
4
5
6
7
8
|
publicfinalvoidschedulePauseActivity(IBinder token,booleanfinished,
booleanuserLeaving,intconfigChanges,booleandontReport){
sendMessage(
finished?H.PAUSE_ACTIVITY_FINISHING:H.PAUSE_ACTIVITY,
token,
(userLeaving?1:0)|(dontReport?2:0),
configChanges);
}
|
finished传递过来为false,因为Launcher此时还没有执行生命周期方法onPause()、onDestory(),因此没有进入finishing状态,那么,sendMessage的第一个参数值为H.PAUSE_ACTIVITY
sendMessage把消息发送到队列中等待执行,执行方法是Handler的handleMessage方法,通过命令PAUSE_ACTIVITY可以得到执行程序:
1
2
3
4
5
6
7
|
casePAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"activityPause");
handlePauseActivity((IBinder)msg.obj,false,(msg.arg1&1)!=0,msg.arg2,
(msg.arg1&2)!=0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
|
继续调用handlePauseActivity方法
1
2
3
4
|
privatevoidhandlePauseActivity(IBinder token,booleanfinished,
booleanuserLeaving,intconfigChanges,booleandontReport){
......
}
|
finished为false,userLeaving传递过来为true,configChanges为0,dontReport为false
1
| ActivityClientRecordr=mActivities.get(token); |
token对应启动类Launcher,此处获得Launcher的ActivityRecord对象
1
2
3
|
if(userLeaving){
performUserLeavingActivity(r);
}
|
调用performUserLeavingActivity方法,performUserLeavingActivity的最终调用过程为:
performUserLeavingActivity—->
mInstrumentation.callActivityOnUserLeaving(r.activity) —->
activity.performUserLeaving() —->
onUserInteraction()
onUserLeaveHint()
意味着,如果是用户操作的主动行为,比如返回按键,遥控器上下左右按键,HOME按键灯,会调用Activity的
onUserInteraction和onUserLeaveHint方法,如果是按键,触摸、轨迹球被分发到Activity时,onUserInteraction会被回调;onUserLeaveHint的作用是当Activity即将进入到后台前被回调,起到提示作用
performUserLeavingActivity执行完后,进程继续调用
1
2
3
4
5
6
7
8
|
performPauseActivity(token,finished,r.isPreHoneycomb());
finalBundle performPauseActivity(ActivityClientRecordr,booleanfinished,
booleansaveState){
.....
mInstrumentation.callActivityOnPause(r.activity);
r.paused=true;
}
|
performPauseActivity方法中继续调用callActivityOnPause方法,参数r.activity代表启动类Launcher
过程9.1 frameworks\base\core\java\android\app\Instrumentation.java
1
2
3
|
publicvoidcallActivityOnPause(Activity activity){
activity.performPause();
}
|
过程9.1.1 frameworks\base\core\java\android\app\Activity.java
1
2
3
4
5
6
7
8
9
|
finalvoidperformPause(){
mDoReportFullyDrawn=false;
mFragments.dispatchPause();
mCalled=false;
onPause();
mResumed=false;
......
mResumed=false;
}
|
最终调用到Activity的performPause方法,再调用生命周期方法onPause()意味着启动类处于暂停状态了,这一步执行完后返回到performPauseActivity中,执行r.paused = true把启动类的ActivityClientRecord的paused置为true,表示启动类此时已经处于暂停状态了。再返回到handlePauseActivity中,继续执行performPauseActivity后面的语句
1
| ActivityManagerNative.getDefault().activityPaused(token); |
这一步通过Binder进程间通信机制进入到ActivityManagerService的activityPaused方法中
过程9.2 frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
1
2
3
4
5
|
publicfinalvoidactivityPaused(IBinder token){
......
stack.activityPausedLocked(token,false);
.....
}
|
过程10 frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
1
2
3
|
finalvoidactivityPausedLocked(IBinder token,booleantimeout){
......
}
|
mPausingActivity表示启动类Launcher,r是Launcher的ActivityRecord对象,if条件为真,进程继续调用completePauseLocked(true)方法
1
2
3
|
privatevoidcompletePauseLocked(booleanresumeNext){
......
}
|
既然启动类都已经暂停了,那下一步工作是不是就是把目标类启动起来呢?如果是的话,应该会执行生命周期onResume方法,这只是猜测,具体详细看方法的执行过程
参数resumeNext传递过来为true
prev.finishing属性为false,这个属性一直没有设置
mPausingActivity = null;
如果启动类已经stop,就把mPausingActivity设为null
进程继续执行到:
1
2
3
4
|
finalActivityStack topStack=mStackSupervisor.getFocusedStack();
if(!mService.isSleepingOrShuttingDown()){
mStackSupervisor.resumeTopActivitiesLocked(topStack,prev,null);
}
|
当前系统处于非睡眠和关机状态,if条件为真,进程开始调用resumeTopActivitiesLocked方法
过程11 frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
1
2
3
4
|
booleanresumeTopActivitiesLocked(ActivityStack targetStack,ActivityRecord target,
Bundle targetOptions){
......
}
|
要清楚方法具体做了什么,一定要先弄清楚参数的含义
形参targetStack的实参是topStack,通过mStackSupervisor.getFocusedStack获得,即当前获得焦点的栈,此处,启动类已经暂停,那么当前栈就是目标类所在的栈,prev是启动类
又调用了resumeTopActivityLocked方法
1
2
3
|
if(isFrontStack(targetStack)){
result=targetStack.resumeTopActivityLocked(target,targetOptions);
}
|
过程12 frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
1
2
3
|
finalbooleanresumeTopActivityLocked(ActivityRecord prev,Bundle options){
......
}
|
继续调用resumeTopActivityInnerLocked方法
1
2
3
|
finalbooleanresumeTopActivityInnerLocked(ActivityRecord prev,Bundle options){
......
}
|
再次进入到此方法时,mResumedActivity为空,因为这是在过程8中startPausingLocked方法内设置的,表明启动类Launcher已经不在是当前运行的Activity,因此
1
2
3
4
|
if(mResumedActivity!=null){
if(DEBUG_STATES)Slog.d(TAG,"resumeTopActivityLocked: Pausing "+mResumedActivity);
pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);
}
|
这个语句就不再成立,进程跳过此句继续执行
1
2
3
4
5
6
7
8
9
|
if(next.app!=null&&next.app.thread!=null){
......
mStackSupervisor.startSpecificActivityLocked(next,true,false);
......
}else{
......
mStackSupervisor.startSpecificActivityLocked(next,true,false);
......
}
|
next就是目标类A,此时A的一些栈等信息已经构建,但是A得进程还没有创建,正常情况下,启动一个新的应用程序一般会创建一个新的进程,应用程序在此进程中执行,特殊情况下可以通过AndroidManifest中process属性执行指定应用程序在某个进程中执行,本文没有设置process属性,默认为启动一个新的进程,本文后面会分析到。由此可知,A还没有进程信息,if语句不成立,进程转到else语句执行
过程13 frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
1
2
3
4
|
voidstartSpecificActivityLocked(ActivityRecordr,
booleanandResume,booleancheckConfig){
......
}
|
1
2
3
4
5
6
7
8
9
|
ProcessRecord app=mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid,true);
if(app!=null&&app.thread!=null){
......
realStartActivityLocked(r,app,andResume,checkConfig);
......
}
mService.startProcessLocked(r.processName,r.info.applicationInfo,true,0,
"activity",r.intent.getComponent(),false,false,true);
|
此时A进程还没有创建,所以app为空,跳过if语句,开始调用startProcessLocked方法
假如A的应用程序已经启动,然后在A中启动B,B是A应用程序的一个Activity,那么此时进程已经创建,app就不会为空,进程会调用realStartActivityLocked方法
过程14 frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
1
2
3
4
5
6
7
8
9
|
finalProcessRecord startProcessLocked(StringprocessName,
ApplicationInfo info,booleanknownToBeDead,intintentFlags,
StringhostingType,ComponentName hostingName,booleanallowWhileBooting,
booleanisolated,booleankeepIfLarge){
returnstartProcessLocked(processName,info,knownToBeDead,intentFlags,hostingType,
hostingName,allowWhileBooting,isolated,0/* isolatedUid */,keepIfLarge,
null/* ABI override */,null/* entryPoint */,null/* entryPointArgs */,
null/* crashHandler */);
}
|
1
2
3
4
5
6
7
8
9
|
finalProcessRecord startProcessLocked(StringprocessName,ApplicationInfo info,
booleanknownToBeDead,intintentFlags,StringhostingType,ComponentName hostingName,
booleanallowWhileBooting,booleanisolated,intisolatedUid,booleankeepIfLarge,
StringabiOverride,StringentryPoint,String[]entryPointArgs,Runnable crashHandler){
......
}
|
该方法中会为A创建ProcessRecord信息,然后继续调用
1
2
|
startProcessLocked(
app,hostingType,hostingNameStr,abiOverride,entryPoint,entryPointArgs);
|
1
2
3
4
5
6
7
8
9
|
privatefinalvoidstartProcessLocked(ProcessRecord app,StringhostingType,
StringhostingNameStr,StringabiOverride,StringentryPoint,String[]entryPointArgs){
......
Process.ProcessStartResult startResult=Process.start(entryPoint,
app.processName,uid,uid,gids,debugFlags,mountExternal,
app.info.targetSdkVersion,app.info.seinfo,requiredAbi,instructionSet,
app.info.dataDir,entryPointArgs);
......
}
|
此方法中会调用进程的start方法创建一个新的进程,具体是通过zygote进程的来fork一个新的进程,成为子进程,子进程共享父进程资源,几乎和父进程一样。当子进程创建好后,系统会分配一个进程号PID给新进程并返回,否则抛出异常
1
2
3
4
5
6
7
8
9
10
11
12
|
publicstaticfinalProcessStartResult start(finalStringprocessClass,
finalStringniceName,
intuid,intgid,int[]gids,
intdebugFlags,intmountExternal,
inttargetSdkVersion,
StringseInfo,
Stringabi,
StringinstructionSet,
StringappDataDir,
String[]zygoteArgs){
......
}
|
第一个参数processClass为新创建的进程的入口类即android.app.ActivityThread.java
niceName:新创建的进程的进程名字,用ps命令可以查看到该名字,一般情况下,应用程序的进程名就是包名
如果进程创建成功,待方法start执行完后,系统就会转到ActivityThread.java的main方法入口开始执行,注意这个流程,和我们通常看到的方法调用方法是不一样的。
过程15 frameworks\base\core\java\android\app\ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
publicstaticvoidmain(String[]args){
......
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread=newActivityThread();
thread.attach(false);
if(sMainThreadHandler==null){
sMainThreadHandler=thread.getHandler();
}
if(false){
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG,"ActivityThread"));
}
Looper.loop();
thrownewRuntimeException("Main thread loop unexpectedly exited");
}
|
prepareMainLooper方法创建了looper对象和MessageQueue消息队列;创建了并初始化ActivityThread对象,同时也创建并初始化了ApplicationThread对象mAppThread
1
2
3
4
5
6
|
thread.attach(false);
privatevoidattach(booleansystem){
......
finalIActivityManager mgr=ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);
}
|
获得ActivityManagerProxy对象,调用该对象的attachApplication方法,通过binder通信,最终调用到ActivityManagerService的attachApplication方法
过程16 frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
1
2
3
4
5
|
publicfinalvoidattachApplication(IApplicationThread thread){
synchronized(this){
......
}
}
|
1
2
3
4
|
privatefinalbooleanattachApplicationLocked(IApplicationThread thread,
intpid){
......
}
|
先通过pid获得ProcessRecord对象,该对象上一步创建过,不为空
1
2
3
4
5
6
7
8
9
|
app.makeActive(thread,mProcessStats);
app.curAdj=app.setAdj=-100;
app.curSchedGroup=app.setSchedGroup=Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground=null;
updateProcessForegroundLocked(app,false,false);
app.hasShownUi=false;
app.debugging=false;
app.cached=false;
app.killedByAm=false;
|
初始化该ProcessRecord对象
1
2
3
4
5
6
7
8
9
10
11
|
// See if the top visible activity is waiting to run in this process...
if(normalMode){
try{
if(mStackSupervisor.attachApplicationLocked(app)){
didSomething=true;
}
}catch(Exceptione){
Slog.wtf(TAG,"Exception thrown launching activities in "+app,e);
badApp=true;
}
}
|
这段话就是真正开始启动目标Activity了,本案例就是A
注:在这段话后面分别有:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// Find any services that should be running in this process...
if(!badApp){
try{
Slog.i("zhulf","---------------------601");
didSomething|=mServices.attachApplicationLocked(app,processName);
}catch(Exceptione){
Slog.wtf(TAG,"Exception thrown starting services in "+app,e);
badApp=true;
}
}
// Check if a next-broadcast receiver is in this process...
if(!badApp&&isPendingBroadcastProcessLocked(pid)){
try{
didSomething|=sendPendingBroadcastsLocked(app);
}catch(Exceptione){
// 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;
}
}
|
用来启动Service、发送广播,此处作为一个备注,如果要分析启动Service、广播,研究这两段语句,本文只研究启动Activity,因此,详细看attachApplicationLocked方法
过程17 frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
1
2
3
|
booleanattachApplicationLocked(ProcessRecord app)throwsRemoteException{
......
}
|
1
2
3
|
if(realStartActivityLocked(hr,app,true,true)){
didSomething=true;
}
|
1
2
3
4
5
|
finalbooleanrealStartActivityLocked(ActivityRecordr,
ProcessRecord app,booleanandResume,booleancheckConfig)
throwsRemoteException{
......
}
|
hr就是目标类ActivityRecord对象,app是进程名字
1
2
|
mService.updateLruProcessLocked(app,true,null);
mService.updateOomAdjLocked();
|
调整进程LRU算法;参与管理进程
1
2
3
4
5
|
app.thread.scheduleLaunchActivity(newIntent(r.intent),r.appToken,
System.identityHashCode(r),r.info,newConfiguration(mService.mConfiguration),
r.compat,r.launchedFromPackage,r.task.voiceInteractor,app.repProcState,
r.icicle,r.persistentState,results,newIntents,!andResume,
mService.isNextTransitionForward(),profilerInfo);
|
app.thrad是IApplicationThread对象,此处就是ApplicationThreadProxy对象接口,这里也是Binder通信过程,调用ApplicationThreadProxy的scheduleLaunchActivity方法,通过binder通信转到ApplicationThread对象的scheduleLaunchActivity方法,该方法在ActivityThread对象中
过程18 frameworks\base\core\java\android\app\ActivityThread.java
1
2
3
4
5
6
7
8
|
publicfinalvoidscheduleLaunchActivity(Intent intent,IBinder token,intident,
ActivityInfo info,Configuration curConfig,CompatibilityInfo compatInfo,
Stringreferrer,IVoiceInteractor voiceInteractor,intprocState,Bundle state,
PersistableBundle persistentState,List<ResultInfo>pendingResults,
List<ReferrerIntent>pendingNewIntents,booleannotResumed,booleanisForward,
ProfilerInfo profilerInfo){
....
}
|
该方法创建了目标类对应的ActivityClientRecord对象,而后初始化该对象,作为sendMessage参数发送到消息队列待处理
1
2
3
4
5
6
|
caseLAUNCH_ACTIVITY:{
finalActivityClientRecordr=(ActivityClientRecord)msg.obj;
r.packageInfo=getPackageInfoNoCheck(
r.activityInfo.applicationInfo,r.compatInfo);
handleLaunchActivity(r,null);
}
|
1
2
3
|
privatevoidhandleLaunchActivity(ActivityClientRecordr,Intent customIntent){
......
}
|
该方法分为两个部分,先调用performLaunchActivity,再调用handleResumeActivity,最后还有finishActivity
先看performLaunchActivity
1
2
3
|
privateActivity performLaunchActivity(ActivityClientRecordr,Intent customIntent){
......
}
|
1
| ActivityInfo aInfo=r.activityInfo; |
从目标类ActivityClientRecord对象中取出ActivityInfo对象,ActivityInfo对象包含了Activity、receiver对象信息
1
| ComponentName component=r.intent.getComponent(); |
再根据Intent获得组件对象component,组件包含了启动类名称和包名称
1
2
3
|
java.lang.ClassLoader cl=r.packageInfo.getClassLoader();
activity=mInstrumentation.newActivity(
cl,component.getClassName(),r.intent);
|
通过Java反射机制找到目标类文件,再创建目标类的一个对象赋值给activity。从此处可知,原来Android中Activity对象是在启动时创建的,系统已经帮助程序员写好了new Activity对象的动作,无需程序员自行new对象,这解决了一开始学习android时总是搞不清楚Activity对象是从什么时候创建的的困惑,因此,Android并不关注组件的创建过程,而把关注点落在了组件的生命周期上。
1
| Application app=r.packageInfo.makeApplication(false,mInstrumentation); |
makeApplication方法也是利用反射机制找到应用程序Application类并创建一个对象,并调用Application对象的onCreate方法,这就是为什么应用一启动后,Application的onCreate比Activity的onCreate先执行的原因!
1
2
3
4
5
|
Context appContext=createBaseContextForActivity(r,activity);
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);
|
createBaseContextForActivity方法中会调用createActivityContext创建ContextImpl对象,ContextImpl实现了Context,也就同时创建了上下文管理者Context对象,这也解决了为什么在写程序时总是能够获得Context对象的原因
attach方法把Context对象、Instrumentation对象等和Activity关联起来
1
| mInstrumentation.callActivityOnCreate(activity,r.state); |
通过Instrumentation对象的callActivityOnCreate方法进入到Instrumentation对象中,Instrumentation对象就是监控所有用户和系统之间的交互操作,比如onCreate、onResume等
过程19 frameworks\base\core\java\android\app\Instrumentation.java
1
2
3
4
5
|
publicvoidcallActivityOnCreate(Activity activity,Bundle icicle){
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
|
继续调用performCreate方法
过程20 frameworks\base\core\java\android\app\Activity.java
1
2
3
4
5
|
finalvoidperformCreate(Bundle icicle){
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
|
最终调用Activity的onCreate方法开始生命周期
再返回到handleLaunchActivity中,进程继续执行到handleResumeActivity方法
1
2
3
4
|
ActivityClientRecordr=performResumeActivity(token,clearHide);
r.activity.performResume();
mInstrumentation.callActivityOnResume(this);
activity.onResume();
|
这四步写在一个代码段,可以看到最终调用了Activity的onResume方法,目标类A启动起来了并成为可见状态
到此处为止,在Launcher中启动Activity的过程就分析完了。
整个过程相当复杂,涉及到很多动态对象,进程间通信,栈的管理等,可以不必要理解每句代码,但是清楚整个流程做了哪些核心的动作是有必要的:
1. 过程5
resolveActivity方法中调用了包管理器PackageManager的resolveIntent方法解析启动目标类的Intent对象,获得解析后的对象ActivityInfo,为何要获得这个对象,这个对象有有什么作用?
在AndroidManifest.xml中Activity和receiver标签包含了很多属性,比如主题、启动模式、屏幕方向,输入法设置,进程名称等,ActivityInfo就是对应目标类Activity的一个动态对象,该对象包含了这些属性信息。该对象的作用用来构建目标类对应的ActivityRecord对象,该对象也是一个动态对象,是历史栈中的一条记录,在内存中对应目标类。
这样就明白一个问题:启动activity时有显示和隐式,对于隐式方式,只需要在目标类中intetn-filter中增加一个action,然后启动类通过这个action即可启动目标类,这是如何做到的?实际上是通过包管理器PackageManager解析intent,查找到匹配的action对应的目标类的。
2. 过程8
startPausingLocked方法是进入到暂停启动类过程的标志,逐步调用prev.app.thread.schedulePauseActivity,然后又binder通信进入到ApplicationThread对象的schedulePauseActivity方法,在此方法中,发送消息给启动类Launcher主线程ActivityThread,ActivityThread利用handler循环处理消息,调用handlePauseActivity方法处理,最终调用到Activity的生命周期方法onPause暂停启动类
3. 过程14
Process对象的start方法开启了一个新的进程作为目标类的主线程,由此,目标类开始从ActivityThread的main方法开支执行,然后由
mgr.attachApplication(mAppThread);
语句通过binder通信进入到ActivityManagerService中,并传递了ApplicationThread对象,该对象传入到ActivityManagerService中后构建目标类进程信息,然后ActivityManagerService负责启动目标类,最终通过该对象又通过Binder通信返回到ApplicationThread对象中,然后ApplicationThread对象又发送消息给目标类主线程ActivityThread对象,该对象循环处理来自ActivityManagerService的消息,进而调用Activity的生命周期方法onCreate、onResume。其中,IApplicationThread远程接口对象起着非常关键作用,他在主线程对象ActivityThread与Activity管理器ActivityManagerService对象之间起着通信桥梁作用。
ActivityManagerService是Activity Manager(注意,分开大写,代表Framework层的核心模块,该模块包含了ActivityManagerService、ActivityStack、Binder接口等)的核心部分,负责启动Activity、Service、发送Broadcast Receiver、启动ContentProvider;调整进程调度算法,管理任务栈、检查权限等一些列核心功能。
2. 调用startActivity启动一个Activity
在应用程序内启动Activity,和应用程序外启动最根本的不同在于不会新创建进程,也就是说,过程13中,不会执行startProcessLocked方法,而执行realStartActivityLocked方法,过程13~过程16可以省略不看,此时在同一个进程中;除此之外,就是栈的获取不一样,用startActivity方法启动可能不会新建栈,直接使用已有的栈,而Launcher启动时一般会新建栈。
3. 命令am start启动
这种方法适合调试时使用,在串口中直接采用
am start -n xxx/.yyy
即可启动应用程序,包名是xxx,入口类名是yyy
am 这个可执行程序对应的源码目录位置:
1
| framework\base\cmds\am\src\com\android\commands\am\Am.java |
当执行这条命令时,先从main方法开始执行
1
2
3
|
publicstaticvoidmain(String[]args){
(newAm()).run(args);
}
|
Am继承了BaseCommand类,run方法在BaseCommand中定义,在run方法中又调用了onRun()方法,系统运行时具体类型是Am,这样就调到了Am的onRun方法。onRun中先执行:
1
| mAm=ActivityManagerNative.getDefault(); |
获得ActivityManagerService的代理类ActivityManagerProxy的一个对象
1
2
3
4
|
Stringop=nextArgRequired();
if(op.equals("start")){
runStart();
}
|
判断参数是否有start这个字符串,如果有,就调用runStart方法,本文启动Activity当然含有start参数
在runStart方法中,会执行这一句
1
2
|
res=mAm.startActivityAsUser(null,null,intent,mimeType,
null,null,0,mStartFlags,profilerInfo,null,mUserId);
|
这一步会继续调用ActivityStackSupervisor的startActivityMayWait方法,与上文的“过程4”一样,后面的步骤基本上差不多。
不管哪种方式启动,在服务端的操作基本上相同,区别就在于是否复用当前栈还是新创建一个栈,是否新建一个进程作为目标类的进程等;在客户端,区别在于启动Activity的方式不同,第三种命令启动方式缺少了startActivity部分。
http://blogread.cn/it/article/8026