首先附上我的几篇其它文章链接感兴趣的可以看看,如果文章有异议的地方欢迎指出,共同进步,顺便点赞谢谢!!!
Android studio编写第一个NDK工程的过程详解(附Demo下载地址)
面试必备1:HashMap(JDK1.8)原理以及源码分析
面试必备2:JDK1.8LinkedHashMap实现原理及源码分析
Android事件分发机制原理及源码分析
View事件的滑动冲突以及解决方案
Handler机制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源码
Android三级缓存原理及用LruCache、DiskLruCache实现一个三级缓存的ImageLoader
Android系统对四大组件的工作过程进行了很大程度的封装,方便开发者使用,Activity作为Android中四大组件之一,直接跟用户进行交互,对于用户来说activity就是应用的一切,系统对其工作流程当然也做了很多封装,本篇文章将介绍Activity的启动流程,在Android中启动Activity大致分为一下两种场景:
Service、BroadcastReceiver
以及ContentProvider
的工作流程进行源码分析。在此强调一点,本文只着重分析场景二和场景一点击的应用已启动的情况,至于场景一未启动的情况我将会在我的另外一篇博客点击Launcher图标activity都做了哪些事情中详细分析;此外本篇文章是基于Android8.0的源码,与Android 5.0、6.0、7.0等版本中启动Activity的源码有点差异,不同版本只是对其工作流程进行进行了不同封装,但是其工作原理都是一样的,至于想要详细了解其它版本的源码,请自行查阅。
本文篇幅较长,阅读起来可能需要花费较长的时间,为了方便阅读,我将分了四个模块共18步去分析启动流程,大家也可以分模块去理解Activity的启动流程。
Step1: Activity的startActivity方法源码:
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);//调用startActivityForResult
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);//调用startActivityForResult,注意当没有传人Bundle时,requestCode传入-1
}
}
Activity的startActivity的方法有几种重载方法,但是最终都掉用了startActivityForResult
方法,此处强调一点:startActivity
中调用startActivityForResult
方法默认传入的requestCode
为-1
,当requestCode<0的时候,是不起作用的。具体原因在下面startActivityForResult的源码中解释
Step2: Activity的startActivityForResult方法源码
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {//重点关注mParent==null,
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);//交给mInstrumentation.execStartActivity方法启动activity
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
//此处可以看出只有requestCode>=0的时候才起作用,执行mStartedActivity =true
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
//mParent不等于null时,将启动工作交给了`mParent.startActivityFromChild`,但最终还是交给了mInstrumentation.execStartActivity方法
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
//mParent.startActivityFromChild方法的源码
public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
int requestCode, @Nullable Bundle options) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, child,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, child.mEmbeddedID, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}
在startActivityForResult中,因为第一次进来mParent==null,所以我们只需重点关注mParent == null
中的代码,mParent代表的是ActivityGroup, 最开始用来在一个界面中嵌入多个子Activity,但是在API13中已经废弃了, Google推荐我们用Fragment来代替ActivityGroup;将启动流程交给了mInstrumentation.execStartActivity()
方法。
mParent==null
,可以看出将activity的启动工作交给了mInstrumentation.execStartActivity()
方法, 这里的mInstrumentation
是Activity类的成员变量,它的类型是Intrumentation,它用来监控应用程序和系统的交互。mParent.startActivityFromChild
,但startActivityFromChild
最终还是将Activity的启动交给了mInstrumentation.execStartActivity
方法。mInstrumentation.execStartActivity
方法的一个参数mMainThread.getApplicationThread()
,首先mMainThread
是一个ActivityThread
对象,ActivityThread
是应用程序的主线程,getApplicationThread()
的类型是一个ApplicationThread
,它是ActivityThread的一个内部,本质是一个Binder
对象,ActivityManagerService
会使用ApplicationThread
来和ActivityThread
进行进程间通信,通过后面的分析我们将会发现它们两个在activity的启动过程中发挥着重要的作用。mStartedActivity =true
,mStartedActivity
作用是用来判断是否执行Activity的onActivityResult
方法。Step3: mInstrumentation.execStartActivity源码:
/**
* @param who 启动Activity的 上下文
* @param contextThread 为Binder对象,是主进程的context对象
* @param token 也是一个Binder对象,指向了服务端一个ActivityRecord对象;
* @param target 为启动的Activity
* @param intent 启动的Intent对象;
* @param requestCode 请求码
* @param options 参数Bundle对象
* @return
*/
public Instrumentation.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);
}
//mActivityMonitors !=null则直接从集合中便利获取Instrumentation.ActivityResult 的结果
if (mActivityMonitors != null) {
...
省略部分代码,非重点
...
}
}
try {
//重点
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//将启动工作交给ActivityManager.getService().startActivity
int result = ActivityManager.getService()
.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;
}
从上面可以看出mInstrumentation.execStartActivity
将启动activity
的工作交给了ActivityManager.getService().startActivity()
方法,那么问题来了ActivityManager.getService()
是什么呢?那带着这个疑问接着往下看
Step4: ActivityManager.getService()的源码
public static IActivityManager getService() {
//IActivityManagerSingleton.get()方法返回一个IActivityManager
return IActivityManagerSingleton.get();
}
//IActivityManagerSingleton变量的实例化
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
//获取一个关联了系统服务ActivityManagerService的Binder对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//通过IActivityManager.Stub.asInterface(b)获取IActivityManager 的代理对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
抽象类Singleton源码如下:不难看出就是一个单例模式,通过get方法获取单例对象,通过抽象方法create()方法创建单例对象。
public abstract class Singleton {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
分析:
ActivityManager.getService()
通过成员变量IActivityManagerSingleton
的get()
方法返回IActivityManager
对象。IActivityManagerSingleton
的类型是Singleton
即通过Singleton的get()方法获取一个IActivityManagerIActivityManagerSingleton
中create
方法的具体实现可以得出,create
方法先获取一个ActivityManagerService
的Binder
对象,然后通过代理的方式获取IActivityManager
的代理对象,最后通过Binder机制调用代理对象的方法,使得系统服务ActivityManagerService
对应的startActivity
方法被调用。Instrumentation.ActivityResult execStartActivity
方法中就是IActivityManager
的代理对象调用了startActivity方法,通过Binder机制使系统服务ActivityManagerService
的startActivity
方法被调用。因此,启动Activity的工作就交给了系统服务AMS来处理了。Step5: ActivityManagerService的startActivity方法源码
ActivityManagerService的声明
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...
省略部分代码
...
@Override
//Activity的启动工作交给了AMS复写的IActivityManager.Stub的startActivity方法,
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
//启动工作交给startActivityAsUser方法
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, 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 stacks here.
//交给了 mActivityStarter.startActivityMayWait
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
}
分析:这两步很简单,首先AMS的startActivity()
调用---->startActivityAsUser()
方法,startActivityAsUser
接着将启动Activity的工作交给了成员变量mActivityStarter
的startActivityMayWait()
方法。mActivityStarter
的类型是ActivityStarter
,ActivityStarter类主要负责处理Activity的Intent和Flags, 还有关联相关的Stack和TaskRecord。
**此处需要强调一点:**在AMS(ActivityManagerService)中,startActivity()
方法有多个,我们要找它复写的父类IActivityManager.Stub
提供的startActivity()
方法,或者说参数类型以及个数都要和Step3mInstrumentation.execStartActivity()
方法中ActivityManager.getService() .startActivity()
的startActivity
方法一致。
简单总结一下:AMS将Activity的启动工作交给了ActivityStarter的startActivityMayWait
()方法。
为了更加清晰的说明Activity在ActivityStarter、ActivityStackSupervisor、ActivityStack中的启动流程,在这里画了一张图,大家在阅读的时候可按照这个图的思想去理解记忆。
Step6: ActivityStarter的startActivityMayWait()方法源码分析
/**
*注意从上面传下来的参数outResult和globalConfig均为null,看源码是可以忽略相关代码
*/
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
// Refuse possible leaked file descriptors
//Step1:检测intent的合法性
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
boolean componentSpecified = intent.getComponent() != null;
// Save a copy in case ephemeral needs it
final Intent ephemeralIntent = new Intent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
if (componentSpecified
&& intent.getData() != null
&& Intent.ACTION_VIEW.equals(intent.getAction())
&& mService.getPackageManagerInternalLocked()
.isInstantAppInstallerComponent(intent.getComponent())) {
// intercept intents targeted directly to the ephemeral installer the
// ephemeral installer should never be started with a raw URL; instead
// adjust the intent so it looks like a "normal" instant app launch
intent.setComponent(null /*component*/);
componentSpecified = false;
}
/**
* 上面主要是检测intent的合法性=========
*/
/**
* Step2:
* 1.此方法实际上的调用PackageManagerService的resolveIntent
* 2.根据intent的信息查找匹配的activity
*/
//自己点击查看mSupervisor.resolveIntent源码可以发现,最后是通过PackageManagerService的resolveIntent获取rInfo
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
if (rInfo == null) {
UserInfo userInfo = mSupervisor.getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
// Special case for managed profiles, if attempting to launch non-cryto aware
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = UserManager.get(mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = userManager.getProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null)
&& userManager.isUserUnlockingOrUnlocked(parent.id)
&& !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
}
}
// Collect information about the target of the Intent.
/**
* Step3:
* 1.收集Intent所指向的Activity信息,
* 2.当存在多个可供选择的Activity,则直接向用户弹出选择框供用户选择
* 3.设置Intent的Component
*/
//根据rInfo, 去匹配Activity,获取到ActivityInfo
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
ActivityOptions options = ActivityOptions.fromBundle(bOptions);
ActivityStackSupervisor.ActivityContainer container =
(ActivityStackSupervisor.ActivityContainer)iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null &&
container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.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 = globalConfig != null
&& mService.getGlobalConfiguration().diff(globalConfig) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when 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-weight process! Check to see if we already
// have another, different heavy-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))) {
...
省略部分源码
这里主要作用是:如果当前系统中已经存在重量级进程,但不是将要启动的这个 实例化这个重量级的Intent,
并且赋值给当前的Intent,重量级:所谓重量级在这里的意思就是有多个任务被匹配到
...
}
}
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
// Step4重点:启动activity并将启动结果返回,即将Activity的启动工作交给了startActivityLocked方法
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, reason);
Binder.restoreCallingIdentity(origId);
if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
// 如果configuration发生变化,则调用AMS的updateConfigurationLocked进行处理
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Updating to new configuration after starting activity.");
mService.updateConfigurationLocked(globalConfig, null, false);
}
//outResult是最为参数被传递进来,而且传进来为null,所以if内的逻辑将不会执行
if (outResult != null) {
outResult.result = res; //res是调用startActivityLocked返回的结果,在startActivityLocked之后给启动结果赋值
....
省略部分代码
....
}
//通知监听者,activity正在启动,并更新状态
mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
//返回启动结果
return res;
}
}
分析:startActivityMayWait方法:主要作用:获取Activity的启动信息,包括ResolveInfo和ActivityInfo,以及获取CallingPid和CallingUid,将Activity启动任务交给startActivityLocked()
方法。
startActivityMayWait方法的流程有下面几点
startActivityLocked()
,将Activity启动任务交给startActivityLocked()
方法。这里需要注意传入的IApplicationThread caller
:Activity的进程内的ApplicationThread对象。在后面要用到。Step7: ActivityStarter的startActivityLocked()方法源码分析
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
//调用startActivity(),启动activity,并将结果返回
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}
分析:在这个方法里面传递了一些参数给startActivity()
方法,如IApplicationThread caller,Intent,callingPid调用者的进程pid,realCallingPid当前进程pid,startFlags=0等,将Activity的启动工作交给了startActivity()
方法。
Step8: ActivityStarter的startActivity()源码分析
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
//err 表示错误的启动结果,在下面会对其赋,值默认是启动成功
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
//检测caller是否有权限启动activity
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
//调用者没有权限activity
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
/**
* 对IntentFlags为FLAG_ACTIVITY_FORWARD_RESULT这种特殊情况进行特殊处理
* 1.Activity A 启动了Activity B,Activity B又启动了C,A-->B-->C, 这种情况下
* 2.A启动B要求B返回result给A,但是如果B在启动C时,Intent设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志
* 3.那么此时将会交由C向A setResult。
*/
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
if (resultRecord != null && !resultRecord.isInStackLocked()) {
resultRecord = null;
}
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
sourceRecord.resultTo = null;
if (resultRecord != null) {
resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
}
if (sourceRecord.launchedFromUid == callingUid) {
// The new activity is being launched from the same uid as the previous
// activity in the flow, and asking to forward its result back to the
// previous. In this case the activity is serving as a trampoline between
// the two, so we also want to update its launchedFromPackage to be the
// same as the previous activity. Note that this is safe, since we know
// these two packages come from the same uid; the caller could just as
// well have supplied that same package name itself. This specifially
// deals with the case of an intent picker/chooser being launched in the app
// flow to redirect to an activity picked by the user, where we want the final
// activity to consider it to have been launched by the previous app activity.
callingPackage = sourceRecord.launchedFromPackage;
}
}
//...省略部分代码 主要用于检测参数的合法行
final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
//如果检查err不SUCCESS,即有异常情况,那么直接return
if (err != START_SUCCESS) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(
-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
//直接return err ,startActivity到此结束直接
return err;
}
//checkStartAnyActivityPermission:检查启动被启动activity它自己的相关权限
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
resultRecord, resultStack, options);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
/**
* mInterceptor 属于一个拦截类,将信息拦截下来,复制给自己的变量保存
* 然后再重新赋值给这些信息,其实这个值还是和以前一样没有变,相当于备份,但是这样做的好处就是在之后可以拦截器里进行修改
*/
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
options);
intent = mInterceptor.mIntent;
rInfo = mInterceptor.mRInfo;
aInfo = mInterceptor.mAInfo;
resolvedType = mInterceptor.mResolvedType;
inTask = mInterceptor.mInTask;
callingPid = mInterceptor.mCallingPid;
callingUid = mInterceptor.mCallingUid;
options = mInterceptor.mActivityOptions;//拦截其中备份保存相关信息
if (abort) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
return START_SUCCESS;
}
// If permissions need a review before any of the app components can run, we
// launch the review activity and pass a pending intent to start the activity
// we are to launching now after the review is completed.
if (mService.mPermissionReviewRequired && aInfo != null) {
if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
aInfo.packageName, userId)) {
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
callingUid, userId, null, null, 0, new Intent[]{intent},
new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
final int flags = intent.getFlags();
Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
newIntent.setFlags(flags
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
if (resultRecord != null) {
newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
}
intent = newIntent;
resolvedType = null;
callingUid = realCallingUid;
callingPid = realCallingPid;
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
null /*profilerInfo*/);
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
true, false) + "} from uid " + callingUid + " on display "
+ (container == null ? (mSupervisor.mFocusedStack == null ?
DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
(container.mActivityDisplay == null ? DEFAULT_DISPLAY :
container.mActivityDisplay.mDisplayId)));
}
}
}
// If we have an ephemeral app, abort the process of launching the resolved intent.
// Instead, launch the ephemeral installer. Once the installer is finished, it
// starts either the intent we resolved here [on install error] or the ephemeral
// app [on install success].
if (rInfo != null && rInfo.auxiliaryInfo != null) {
intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
callingPackage, verificationBundle, resolvedType, userId);
resolvedType = null;
callingUid = realCallingUid;
callingPid = realCallingPid;
aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
}
//构建ActivityRecord用于存储Activity的各种状态和历史信息。
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
if (r.appTimeTracker == null && sourceRecord != null) {
// If the caller didn't specify an explicit time tracker, we want to continue
// tracking under any it has.
r.appTimeTracker = sourceRecord.appTimeTracker;
}
final ActivityStack stack = mSupervisor.mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
PendingActivityLaunch pal = new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
// This is the second allowed switch since we stopped switches,
// so now just generally allow switches. Use case: user presses
// home (switches disabled, switch to home, mDidAppSwitch now true);
// user taps a home icon (coming from home so allowed, we hit here
// and now allow anyone to switch again).
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
doPendingActivityLaunchesLocked(false);
//如果没有异常会最终会执行到这里交给重载的方法startActivity完成启动过程
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
对startActivity()方法的流程总结一下
mSupervisor.checkStartAnyActivityPermission
检查这个activity自己的相关权限ActivityRecord
的特点:一个ActivityRecord
对应一个Activity
,保存了一个Activity
的所有信息;但是一个Activity
可能会有多个ActivityRecord
,因为Activity
可以被多次启动,这个主要取决于其启动模式。return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
接着向下看重载的startActivity()
方法源码:
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
//重点:调用startActivityUnchecked方法,处理activity的启动
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
if (!ActivityManager.isStartResultSuccessful(result)
&& mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);
return result;
}
重载的startActivity
方法主要就是调用startActivityUnchecked
方法,即把activity的启动工作交给startActivityUnchecked()
。
Step9: ActivityStarter类的startActivityUnchecked方法源码分析
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
/**
* Step1:setInitialState
* 此方法用于初始化数据和校验Intent的flag参数是否为特定的flag
*/
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
/**
* Step2:computeLaunchingTaskFlags:方法主要用于设置Activity的启动模式
*/
computeLaunchingTaskFlags();
/**
* Step3:computeSourceStack方法:就是针对启动模式为FLAG_ACTIVITY_NEW_TASK的时候判断要不要为其重新NEW一个task
*/
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
//Step4:是否将新的Activity插入到现有的Task中,返回null表示否,否则新启动的Activity将插入到该Task的Top位置。
ActivityRecord reusedActivity = getReusableIntentActivity();
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
final int preferredLaunchDisplayId =
(mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
//当eusedActivity不为null的时候,将新的Activity插入到现有的Task
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (mStartActivity.getTask() == null) {
mStartActivity.setTask(reusedActivity.getTask());
}
if (reusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTask().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
// as the first operation, in case the activity will be resumed as a result of later
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
// state.SingleTask启动模式时的处理逻辑 ,清空在它在Activity栈中在它上之上的任务
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
// The above code can remove {@code reusedActivity} from the task, leading to the
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
if (reusedActivity.getTask() == null) {
reusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);
}
//top就是要启动的activty,在deliverNewIntentLocked中将会回调它的onNewIntent方法
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
/**
* Step5:sendPowerHintForLaunchStartIfNeeded
* 根据条件去隐藏其他任务栈
*/
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
/**
* Step6:setTargetStackAndMoveToFrontIfNeeded 将这个activity所在的任务栈移动到前台
*
*/
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
//设置这个任务栈的信息
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
}
}
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
//是否复用activity
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
...省略部分代码 ...
//这部分代码主要用复用activity并回掉onNewIntent方法
return START_DELIVERED_TO_TOP;
}
//标记:是否需要创建新的activity栈
boolean newTask = false;
//...省略部分代码 ,该代码主要是判断是否建新的activity栈,以及创建过程
...代码
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
/**
* Step7: 最后调用 mSupervisor.resumeFocusedStackTopActivityLocked
* 将activity的启动工作交给 mSupervisor.resumeFocusedStackTopActivityLocked方法
*/
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
}
startActivityUnchecked方法小结:
在此方法中做了很多逻辑校验,为了便于阅读,我省略了部分代码,还有此方法中调用的几个**中要方法源码不在这里粘贴分析,**但是在注释中已经简单描述几个方法的作用,例如:setInitialState
、computeLaunchingTaskFlags
、computeSourceStack
、以及deliverNewIntentLocked
方法等等,感兴趣的话可以自行查看。
startActivityUnchecked有以几个重要的点:
computeLaunchingTaskFlags()
这个方法在经过一些逻辑处理之后设置了activity的启动模式SingleTask
启动模式的话,清空栈内在它之上的Activity,即把当前Activity
移动到栈顶,并通过deliverNewIntentLocked()
方法会掉它的onNewIntent
方法ActivityStackSupervisor
类resumeFocusedStackTopActivityLocked
方法。Step10: ActivityStackSupervisor类
resumeFocusedStackTopActivityLocked`方法源码分析
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
// 调用ActivityStack的resumeTopActivityUncheckedLocked,此处交给了ActivityStack去处理
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
//// 调用ActivityStack的resumeTopActivityUncheckedLocked,此处交给了ActivityStack去处理
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
分析:resumeFocusedStackTopActivityLocked
方法就是将activity的启动逻辑交给了ActivityStack
的resumeTopActivityUncheckedLocked
方法处理。即activity的启动逻辑暂时交给了ActivityStack。
那么接着分析ActivityStack的处理逻辑。
Step11:ActivityStack的resumeTopActivityUncheckedLocked
方法源码
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
//调用resumeTopActivityInnerLocked方法去处理
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
// We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
// any necessary pause logic occurs.
mStackSupervisor.checkReadyForSleepLocked();
return result;
}
分析:resumeTopActivityUncheckedLocked
方法逻辑比较简单,主要就是调用resumeTopActivityInnerLocked
方法。
那我们接着向下看resumeTopActivityInnerLocked方法都做了些什么?
Step12:ActivityStack的resumeTopActivityInnerLocked
方法源码
总结一下resumeTopActivityInnerLocked
方法,做的工作比较多,代码篇幅比较长,但是方法中的注释也比较详细,在这我就不做翻译工作了,为了便于理解我省略了部分代码,至于详细源码感兴趣的朋友话可以自行查阅。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
//从栈顶取出要起动的activity信息
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
final ActivityRecord parent = mActivityContainer.mParentActivity;
final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
//如果父栈没有 resumed 则不要resume 这个activity所在的栈 直接return false
if (hasRunningActivity && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
}
...省略部分代码
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
//最终会将启动工作交给StackSupervisor.startSpecificActivityLocked方法,即工作转移到mStackSupervisor
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
这里简单总结一下resumeTopActivityInnerLocked
的作用:判断要启动的Activity所在的栈是否对当前用户不可见,如果不可见就不需要继续执行下去,因为即使把这个Activity启动起来,用户也看不见,还不如先把它保存起来,等到下次可见的时候再启动。若可见,则继续执行。把要启动的Activity添加到栈顶。
Step13: 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.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
//app进程已经在运行,直接去启动
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.
//如果它是一个被标记为在多个进程中运行的平台组件,那么不要添加它,因为它实际上是框架的一部分,所以在进程中作为单独的apk进行跟踪是没有意义的
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//重点:将activity的启动工作转交给realStartActivityLocked方法
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.
}
// 如果进程为app 为null或者有异常,则AMS重新fork一个进程来起来,点击桌面启动图标如果该应用进程未启动,走到这里
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
分析:startSpecificActivityLocked
方法逻辑比较简单,主要负责跟要启动的Activity进程相关的工作,首先由AMS根据参数通过getProcessRecordLocked
方法获取当前APP进程的记录ProcessRecord
,如果获取到ProcessRecord
即应用所在进程已经启动,则最终将activity的启动工作转交给realStartActivityLocked
方法,否则应用进程未启动,则交给AMS的startProcessLocked
方法去启动该进程,本篇文章我只分析应用程序已经启动的情况,至于未启动的情况日后将在另一篇文章应Android8.0用程序的启动流程中分析,接下来我们继续分析realStartActivityLocked
方法。
Step14: ActivityStackSupervisor类的realStartActivityLocked
方法
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
//...代码....先是mWindowManager.updateOrientationFromAppTokens()让窗口管理器根据新的活动顺序重新评估屏幕的方向,
// 紧接着更新这个activity的覆盖配置mService.updateDisplayOverrideConfigurationLocked() ,
// 然后判断是否在启动的时候显示软键盘,然后固定屏幕,这个时候不允许其他的activity启动,
app.hasShownUi = true;
app.pendingUiClean = true;
app.forceProcessStateUpTo(mService.mTopProcessState);
// Because we could be starting an Activity in the system process this may not go across
// a Binder interface which would create a new Configuration. Consequently we have to
// always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
/**
* 重点:核心
* 底层通过Binder机制将activity的启动工作交给了ApplicationThread,即app.thread.scheduleLaunchActivity通过Binder机制使ApplicationThread的scheduleLaunchActivity方法被调用。
* app:是一个ProcessRecord对象
* thread:IApplicationThread类型,ApplicationThread继承了IApplicationThread.Stub
*/
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
//...代码.....
return true;
}
分析realStartActivityLocked小结:
最终是通过app.thread.scheduleLaunchActivity
方法去处理activity的启动,此方法是Activity启动的真正入口,通过这里需要注意的是app.thread调用scheduleLaunchActivity方法,通过Binder机制,使ApplicationThread
的scheduleLaunchActivity
方法被调用。最终activity的启动工作交给了ApplicationThread
类。
ApplicationThread
实现了IApplicationThread.Stub
这个Binder
接口,所以ApplicationThread
本质也是一个Binder。ApplicationThread
也是ActivityThread
的内部类,ApplicationThread
通过Handler机制发送消息控制Activity
、Service
的生命周期,关于Hadler的底层机制可以参考我另外一片博客Handler机制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源码ApplicationThread的结构图,加对ApplicationThread的记忆
Step15: ApplicationThread的scheduleLaunchActivity
方法
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List pendingResults, List pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
//创建了一个ActivityClientRecord对象,用于封装启动Activity需要的一些参数值
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
//调用sendMessage方法将ActivityClientRecord 传递过去
sendMessage(H.LAUNCH_ACTIVITY, r);
}
分析:scheduleLaunchActivity方法逻辑比较简单,通过传递进来的参数创建了一个ActivityClientRecord对象,用于封装启动Activity需要的一些参数值,最后调用sendMessage(H.LAUNCH_ACTIVITY, r);
交给sendMessage方法处理。
Step16: ApplicationThread的sendMessage
方法
此方法有多个重载方法但最后都会执行到下面这个方法
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
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;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
分析:mH
类型是H
,H类是ActivityThread
的内部类,继承了Handler,因此Activity的启动工作就放到了H类的handleMessage
方法中
Step16: H的handleMessage
方法
handleMessage处理了大量和Activity、Service、Window等相关的消息处理操作,这里我们只分析和Activity启动的LAUNCH_ACTIVITY
消息相关操作。
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
//从msg.obj中取出ActivityClientRecord
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//通过getPackageInfoNoCheck方法获取LoadedApk对象,并将该对象存储到 r.packageInfo中
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
//调用handleLaunchActivity方法去启动activity
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
//...代码
}
}
最后启动Activity的工作就交给了ActivityThread的handleLaunchActivity()
方法,继续往下看;
Step17: ActivityThread的handleLaunchActivity()
方法启动Activity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
//如果我们准备在后台进行gc,那么我们就回到活动状态,跳过它。
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.确保使用最新的配置运行
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
//重点 调用performLaunchActivity方法启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//当a 不为null的时候handleResumeActivity,仔细追总源码 会调用 r = performResumeActivity(token, clearHide, reason);
//而performResumeActivity方法中会通过r.activity.performResume(); 回掉activity的onResume方法
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
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.
performPauseActivityIfNeeded(r, reason);
// 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;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
//如果启动的r为null即启动的activity 异常 则 ActivityManager.getService().finishActivity
// 通过Binder机制回掉到AMS的finishActivity,即异常操作交给AMS去停止Activity的启动
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
分析handleLaunchActivity的方法逻辑也比较简单,将Activity的启动工作交给了performLaunchActivity(r, customIntent);
方法。如果启动正常,则会掉activity的onResume方法,如果异常通过Binder机制交给AMS去处理停止启动操作。
Step18: ActivityThread的performLaunchActivity()
方法分析
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
/**
* Step1
* 从ActivityClientRecord中获取带启动Activity的组件信息
* 并创建ComponentName,里面包含了包名,类名相关的信息
* */
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
// 创建ComponentName
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
/**
* Step2:
* 通过createBaseContextForActivity创建ContextImpl
*/
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
/**
* Step3:
* 通过使用mInstrumentation.newActivity方法使用类加载器创建Activity对象
*/
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
/**
* Step4
* 通过LoadedApk的makeApplication方法尝试创建Application对象
*/
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
/**
* Step5:
* 调用activity的attach方法完成一些重要数据的初始化操作
*/
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, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
/**
* Step6:
* 通过mInstrumentation的callActivityOnCreate方法调用Activity的onCreate方法
* Activity的onCreate方法执行表示启动完成
*/
if (r.isPersistable()) {
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;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
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) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
小结:
ActivityThread的performLaunchActivity
方法是Activity的最终启动者,代码中在重要的地方都加了详细注释,这里简单在描述一下performLaunchActivity
主要完成了以下几件事情:
createBaseContextForActivity
方法创建ContextImpl
,ContextImpl
是一种重要的数据结构,它是Context的具体体现,Context中的大部分逻辑都是由ContextImpl完成的;ContextImpl是通过Activity的attach方法和Activity建立关联。mInstrumentation.newActivity
方法创建Activity,而mInstrumentation.newActivity
使方法使用类加载器创建Activity对象。LoadedApk的makeApplication方法
尝试创建Application对象,创建makeApplication
方法过程和创建Activity的过程也是使用类加载器创建的。attach
方法完成一些重要数据的初始化操作。mInstrumentation
的callActivityOnCreate
方法调用Activity的onCreate
方法Activity的onCreate方法执行表示启动完成。接下来再看一下上面几步中出现的方法:
1: ActivityThread的createBaseContextForActivity
方法创建ContextImpl
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
final int displayId;
try {
displayId = ActivityManager.getService().getActivityDisplayId(r.token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
//最终通过ContextImpl的createActivityContext方法去创建ContextImpl对象,至于ContextImpl的操作这里不详细分析了,以后我会写一篇ContextImpl的源码分析
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
// its content on a secondary display if there is one.
//出于调试目的,如果活动的包名包含“debug”的值。“use-second-display”系统属性作为子字符串,如果有子字符串,则在辅助显示中显示其内容。
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
if (id != Display.DEFAULT_DISPLAY) {
Display display =
dm.getCompatibleDisplay(id, appContext.getResources());
appContext = (ContextImpl) appContext.createDisplayContext(display);
break;
}
}
}
return appContext;
}
2: mInstrumentation.newActivity`方法创建Activity
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//最终通过类加载器创建activity
return (Activity)cl.loadClass(className).newInstance();
}
3: LoadedApk类的makeApplication
方法创建Application
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//这里对对mApplication进行了判断,这也就是一个应用只有一个Application对象的原因
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//获取ClassLoader
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//重点 调用mActivityThread.mInstrumentation.newApplication去创建Application对象,
// newApplication和activity创建过程一样,通过类加载机制创建application对象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
//...代码打印异常信息
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
//通过instrumentation的callApplicationOnCreate方法调用的application的onCreate方法
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
//...代码打印异常信息
}
}
//...代码
return app;
}
4: Instrumentation类的newApplication
方法创建Application
static public Application newApplication(Class> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//类加载器创建
Application app = (Application)clazz.newInstance();
//绑定上下文
app.attach(context);
return app;
}
5:Activity的attach
方法初始化一些重要数据
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//创建窗口对象PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
//下面三行是给PhoneWindow注册相关监听
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
//初始化一堆数据
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//设置WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
}
到此为止activity启动过程分析完毕,5.1的小假期也结束了,在此过程中也学到了不少,framework源码比较难理解,需要一遍遍的反复去看直到理解。后续将分别推出Service、BroadcastReceiver
以及ContentProvider
的工作流程进行等源码分析。
如果本文有什么不对的地方请大家指出共同进步,顺便挥挥拇指点赞加关注。