文章在http://gityuan.com/2016/03/12/start-activity/基础上修改而来
一. 简述
本文基于android7.0代码,分析Activity的启动流程
startActivity的流程与startService启动过程分析相近,但比多了stack/task以及UI的相关内容以及Activity的生命周期的管理。
Activity启动发起后,通过Binder最终交由system进程中的AMS来完成,则启动流程如下图(6.0的流程图)
下面就开始我们的分析
[-> Activity.java]
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent,@Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1,options);
} else {
// Note we want to go through thiscall for compatibility with
// applications that may haveoverridden the method.
startActivityForResult(intent, -1);
}
}
[-> Activity.java]
public voidstartActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent,requestCode, null);
}
public voidstartActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this,mMainThread.getApplicationThread(), mToken, this,
intent, requestCode,options);
...
}
execStartActivity()方法的参数:
[-> Instrumentation.java]
public ActivityResult execStartActivity(
Context who, IBinder contextThread,IBinder token, Activity target,
Intent intent, int requestCode,Bundle options) {
android.util.SeempLog.record_str(377,intent.toString());
IApplicationThread whoThread =(IApplicationThread) contextThread;
Uri referrer = target != null ?target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result =ActivityManagerNative.getDefault()
.startActivity(whoThread,who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ?target.mEmbeddedID : null,
requestCode, 0, null,options);
//检查activity是否启动成功
checkStartActivityResult(result,intent);
} catch (RemoteException e) {
throw newRuntimeException("Failure from system", e);
}
return null;
}
ActivityManagerNative.getDefault()返回的是ActivityManagerProxy对象. 此处startActivity()的共有10个参数, 下面说说每个参数传递AMP.startActivity()每一项的对应值:
[-> ActivityManagerNative.java :: ActivityManagerProxy]
classActivityManagerProxy implements IActivityManager
{
public int startActivity(IApplicationThreadcaller, String callingPackage, Intent intent,
String resolvedType, IBinderresultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfoprofilerInfo, 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;
}
...
}
AMP经过binder IPC,进入ActivityManagerNative(AMN)。接下来程序进入了system_server进程,开始继续执行。先前的操作都是在启动Activity的进程里执行。
[-> ActivityManagerNative.java]
@Override
public boolean onTransact(int code, Parceldata, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b =data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage =data.readString();
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();
ProfilerInfo profilerInfo =data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data): null;
Bundle options = data.readInt() !=0
?Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app,callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode,startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
此时startActivity执行的是AMS的startActivity方法
[-> ActivityManagerService.java]
@Override
public final intstartActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfoprofilerInfo, Bundle bOptions) {
return startActivityAsUser(caller,callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public final intstartActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfoprofilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId =mUserController.handleIncomingUser(Binder.getCallingPid(),Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY,"startActivity", null);
// TODO: Switch to user app stackshere.
return mActivityStarter.startActivityMayWait(caller, -1,callingPackage, intent,
resolvedType, null, null,resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null,bOptions, false, userId, null, null);
}
此处mActivityStarter类型为ActivityStarter,此类为7.0新加类,用于Activity的启动管理
当程序运行到这里时, AS.startActivityMayWait的各个参数取值如下:
再来看看这个方法的源码:
[-> ActivityStarter.java]
final intstartActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intentintent, String resolvedType,
IVoiceInteractionSessionvoiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho,int requestCode, int startFlags,
ProfilerInfo profilerInfo,IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, booleanignoreTargetSecurity, int userId,
IActivityContainer iContainer,TaskRecord inTask) {
// Refuse possible leaked filedescriptors
if (intent != null &&intent.hasFileDescriptors()) {
throw newIllegalArgumentException("File descriptors passed in Intent");
}
mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
boolean componentSpecified =intent.getComponent() != null;
// Save a copy in case ephemeral needsit
final Intent ephemeralIntent = newIntent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
//收集Intent所指向的Activity信息, 当存在多个可供选择的Activity,则直接向用户弹出resolveActivity
ResolveInfo rInfo = mSupervisor.resolveIntent(intent,resolvedType, userId);
...
// Collect information about the targetof the Intent.
ActivityInfo aInfo =mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
ActivityOptions options =ActivityOptions.fromBundle(bOptions);
ActivityStackSupervisor.ActivityContainercontainer =
(ActivityStackSupervisor.ActivityContainer)iContainer;
synchronized (mService) {
if (container != null &&container.mParentActivity != null &&
container.mParentActivity.state!= RESUMED) {
// Cannot start a childactivity if the parent is not resumed.
returnActivityManager.START_CANCELED;
}
final int realCallingPid =Binder.getCallingPid();
final int realCallingUid =Binder.getCallingUid();
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}
final ActivityStack stack;
if (container == null ||container.mStack.isOnHomeDisplay()) {
stack = mSupervisor.mFocusedStack;
} else {
stack = container.mStack;
}
stack.mConfigWillChange = config !=null && mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION)Slog.v(TAG_CONFIGURATION,
"Starting activitywhen config will change = " + stack.mConfigWillChange);
final long origId =Binder.clearCallingIdentity();
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weightprocess! Check to see if we already
// have another, differentheavy-weight process running.
if(aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final ProcessRecord heavy =mService.mHeavyWeightProcess;
if (heavy != null&& (heavy.info.uid != aInfo.applicationInfo.uid
||!heavy.processName.equals(aInfo.processName))) {
int appCallingUid =callingUid;
if (caller != null) {
ProcessRecordcallerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
appCallingUid =callerApp.info.uid;
} else {
Slog.w(TAG,"Unable to find app for caller " + caller
+" (pid=" + callingPid + ") when starting: "
+intent.toString());
ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target =mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, "android",
appCallingUid,userId, null, null, 0, new Intent[] { intent },
new String[] {resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
|PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = newIntent();
if (requestCode >=0) {
// Caller isrequesting a result.
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
newIntentSender(target));
if(heavy.activities.size() > 0) {
ActivityRecord hist =heavy.activities.get(0);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
hist.task.taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setFlags(intent.getFlags());
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
resolvedType = null;
caller = null;
callingUid =Binder.getCallingUid();
callingPid =Binder.getCallingPid();
componentSpecified =true;
rInfo =mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
aInfo = rInfo != null ?rInfo.activityInfo : null;
if (aInfo != null) {
aInfo =mService.getActivityInfoForUser(aInfo, userId);
}
}
}
}
final ActivityRecord[] outRecord =new ActivityRecord[1];
//[见流程2.8]
int res = startActivityLocked(caller, intent,ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession,voiceInteractor,
resultTo, resultWho,requestCode, callingPid,
callingUid, callingPackage,realCallingPid, realCallingUid, startFlags,
options,ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
return res;
}
该过程主要功能:通过resolveActivity来获取ActivityInfo信息, 找到相应的Activity组件,并保存到intent对象,然后再进入startActivityLocked()
ASS代表ActivityStackSupervisor
[-> ActivityStackSupervisor.java]
ActivityInfo resolveActivity(Intentintent, String resolvedType, int startFlags,
ProfilerInfo profilerInfo, intuserId) {
final ResolveInfo rInfo = resolveIntent(intent,resolvedType, userId);
return resolveActivity(intent, rInfo, startFlags,profilerInfo);
}
ResolveInfo resolveIntent(Intent intent, StringresolvedType, int userId) {
return resolveIntent(intent,resolvedType, userId, 0);
}
ResolveInfo resolveIntent(Intent intent, StringresolvedType, int userId, int flags) {
try {
returnAppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | flags
|ActivityManagerService.STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
}
return null;
}
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo,int startFlags,
ProfilerInfo profilerInfo) {
final ActivityInfo aInfo = rInfo !=null ? rInfo.activityInfo : null;
if (aInfo != null) {
// Store the found target back intothe intent, because now that
// we have it we never want to dothis again. For example, if the
// user navigates back to thispoint in the history, we should
// always restart the exact sameactivity.
intent.setComponent(newComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't debug things in the systemprocess
if (!aInfo.processName.equals("system")){
... //对于非system进程,根据flags来设置相应的debug信息
//推测是在启动进程里面设置
return aInfo;
}
ActivityManager类有如下4个flags用于调试:
[->ActivityStarter.java]
AS.StartActivityLocked代码较长,所以就不贴上具体代码了但是主要的工作为:
· 获取调用者的进程信息和调用Activity
· 为启动Activity做一些检查工作,比如检查Component,ActivityInfo…以及权限检查
· 创建ActivityRecord
· 获取当前的stack,执行checkAppSwitchAllowedLocked [见流程2.8.1]
· 处理pendind Activity的启动,这些Activity是由于appswitch禁用从而被hold的等待启动activity [见流程2.8.2]
[->ActivityStarter.java]
boolean checkAppSwitchAllowedLocked(intsourcePid, int sourceUid,
int callingPid, int callingUid,String name) {
if (mAppSwitchesAllowedTime <SystemClock.uptimeMillis()) {
return true;
}
int perm = checkComponentPermission(
android.Manifest.permission.STOP_APP_SWITCHES, sourcePid,
sourceUid, -1, true);
if (perm ==PackageManager.PERMISSION_GRANTED) {
return true;
}
// If the actual IPC caller isdifferent from the logical source, then
// also see if they are allowed tocontrol app switches.
if (callingUid != -1 &&callingUid != sourceUid) {
perm = checkComponentPermission(
android.Manifest.permission.STOP_APP_SWITCHES,callingPid,
callingUid, -1, true);
if (perm ==PackageManager.PERMISSION_GRANTED) {
return true;
}
}
Slog.w(TAG, name + " request from" + sourceUid + " stopped");
return false;
}
当mAppSwitchesAllowedTime时间小于当前时长,或者具有STOP_APP_SWITCHES的权限,则允许app发生切换操作.
其中mAppSwitchesAllowedTime,在AMS.stopAppSwitches()
的过程中会设置为:mAppSwitchesAllowedTime =SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME
. 禁止app切换的timeout时长为5s(APP_SWITCH_DELAY_TIME = 5s).
当发送5秒超时或者执行AMS.resumeAppSwitches()
过程会将mAppSwitchesAllowedTime设置0, 都会开启允许app执行切换的操作.另外,禁止App切换的操作,对于同一个app是不受影响的,有兴趣可以进一步查看checkComponentPermission
过程.
[->ActivityStarter.java]
final voiddoPendingActivityLaunchesLocked(boolean doResume) {
while(!mPendingActivityLaunches.isEmpty()) {
final PendingActivityLaunch pal =mPendingActivityLaunches.remove(0);
final boolean resume = doResume&& mPendingActivityLaunches.isEmpty();
try {
final int result =startActivityUnchecked(
pal.r, pal.sourceRecord,null, null, pal.startFlags, resume, null, null);
postStartActivityUncheckedProcessing(
pal.r, result,mSupervisor.mFocusedStack.mStackId, mSourceRecord,
mTargetStack);
} catch (Exception e) {
Slog.e(TAG, "Exceptionduring pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
}
}
}
mPendingActivityLaunches
记录着所有将要启动的Activity, 是由于在startActivityLocked
的过程时App切换功能被禁止, 也就是不运行切换Activity, 那么此时便会把相应的Activity加入到mPendingActivityLaunches
队列. 该队列的成员在执行完doPendingActivityLaunchesLocked
便会清空.
启动mPendingActivityLaunches中所有的Activity, 由于doResume =false, 那么这些activtity并不会进入resume状态,而是设置delayedResume = true, 会延迟resume.
[->ActivityStarter.java]
同样ActivityStarter的startActivityUnchecked代码也非常多,主要工作如下:
在ActivityInfo.java中定义了4类Launch Mode:
还有几个常见的flag含义:
最后还有:设置FLAG_ACTIVITY_NEW_TASK的几个情况:
[->ActivityStack.java]
[->ActivityStackSupervisor.java]
[->ActivityStack.java]
[->ActivityStack.java]
[->ActivityStackSupervisor.java]
voidstartSpecificActivityLocked(ActivityRecord r,
boolean andResume, booleancheckConfig) {
// Is this activity's applicationalready 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 isa platform component that is marked
// to run in multiple processes,because this is actually
// part of the framework sodoesn't make sense to track as a
// separate apk in theprocess.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//真正的启动Activity【见流程2.14】
realStartActivityLocked(r, app,andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exceptionwhen starting activity "
+r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception wasthrown -- fall through to
// restart the application.
}
//当进程不存在则创建进程 [见流程2.13.1]
mService.startProcessLocked(r.processName, r.info.applicationInfo, true,0,
"activity",r.intent.getComponent(), false, false, true);
}
[->ActivityManagerService.java]
AMS.startProcessLocked()就是系统开始创建进程的入口,关于系统创建进程的流程也是值得深究的。
当Zygote进程收到创建进程的消息之后,通过fork方法,创建出一个新的进程,创建结束后会在这个新的进程里创建属于它的ActivityThread,然后执行了ActivityThread的attach方法,通过这个方法建立与系统进程的联系,这里暂且不讨论过多与创建进程相关的东西,当做完以上操作时便会执行到2.14
[->ActivityStackSupervisor.java]
我们回溯到ASS.realStartActivityLocked[流程2.13],如果在启动Activity或者其他android的组件时,有承载它的进程,则直接执行该方法继续Activity的创建流程,如果没有则为其创建相应的进程,然后还会继续执行本方法
[->ApplicationThreadProxy.java]
public final voidscheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, ConfigurationcurConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo,String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state,PersistableBundle persistentState,
List<ResultInfo>pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, booleanisForward, ProfilerInfo profilerInfo) throws RemoteException {
......
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION,data, null,
IBinder.FLAG_ONEWAY);
.......
}
[-> ApplicationThreadNative.java]
case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION:
{
......
scheduleLaunchActivity(intent, b,ident, info, curConfig, overrideConfig, compatInfo,
referrer, voiceInteractor, procState,state, persistentState, ri, pi,
notResumed, isForward,profilerInfo);
return true;
}
[-> ApplicationThread.java]
这里的代码比较容易理解,主要通过Android的Handler消息机制发送一个消息给承载将要启动此Activity的进程,告诉它我们要开始启动Activity了
[-> ActivityThread.java ::H]
执行handleLaunchActivity,详细见[流程2.19]
[-> ActivityThread.java]
private voidhandleLaunchActivity(ActivityClientRecord r, Intent customIntent, Stringreason) {
........
//初始化wms
WindowManagerGlobal.initialize();
//最终回调目标Activity的onCreate[见流程2.23]
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = newConfiguration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//最终回调目标Activity的onStart,onResume.
handleResumeActivity(r.token,false, r.isForward,
!r.activity.mFinished&& !r.startsNotResumed, r.lastProcessedSeq, reason);
.......
}
[-> ActivityThread.java]
private ActivityperformLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.......
Activity activity = null;
......
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);
......
return activity;
}
创建Activity对象
创建Application对象
调用Activity的attach方法对Activity的一些成员变量进行了初始化(上下文,线程,标题。。。),特别是mWindow初始化为PhoneWindow这个类的实例。在初始化了Window之后,来到我们最熟悉的onCreate方法,我们一般在这个方法中会调用setContentView指定该Activity的布局文件[这里涉及Activity界面的加载和绘制],然后继续[流程2.21]
[-> ActivityThread.java]
AT. handleResumeActivity主要回调Activity的onstart和onresume方法,主要处理和Activity的显示相关的操作,详细参见[Activity界面的加载和绘制]
到这里就已经简单的介绍了startActivity的整个启动流程,其中的一些过程或许也有疏漏,还请见谅。
然后我们要启动的Activity的就start起来了,从onCreate—onStart—onResume,Activity界面的绘制……
完毕