目录
- 概述
- 总结
- 详细过程
- 重要类说明
概述
在冷启动过程中,“当为App创建完进程”之后,就需要“激活处于焦点栈栈顶的待启动Activity”。关于冷启动过程的前两步操作,《为目标App启动做准备》、《启动App进程》 的流程请点击查看。
由于“App进程内部操作”部分内容比较多一些,所以这部分的内容被分成了2个小章节来分析。
第一节:也就是本节是从“App进程启动完毕之后,从ActivityThread.main()开始” 至 “App进程接收到AMS通过scheduleLaunchActivity()发起的 LAUNCH_ACTIVITY 消息”为止。
第二节:《App启动流程:App进程内部操作-2》,则从“App接收到LAUNCH_ACTIVITY开始” 至 “通过Activity.handleResumeActivity()真正完成待启动Activity的实例化并执行其View树的绘制”为止。
当前源码的分析是基于 Android8.0。
总结
1:当Zygote进程创建并初始化完App进程后,就会通过反射执行ActivityThread.main()对main线程进行初始化。
2:通过ActivityManager.getService()获取AMS服务在本进程的BInder 代理,而后通过这个代理对象通知AMS执行attachApplication()操作。
这是一次IPC操作,从App进程切换至system_server进程
3:AMS接收到App进程发起的“attachApplication()操作”操作后会执行如下操作:
3.1:根据 调用者进程的pid,获取记录此进程信息的ProcessRecord。
3.2:注册“Binder服务死亡通知”,App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源。
3.3:把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。并重置此ProcessRecord中一些参数。
3.4:通过App进程的ApplicationThread服务在system_server进程的Binder代理对象,执行bindApplication()来通知App进程继续后续“绑定”操作。
这是一次IPC操作,从system_server进程切换至App进程
4:App进程接收到AMS发起的bindApplication()操作后会执行如下操作:
4.1:通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
4.2:通过Handler消息机制,向App进程的主线程发一个“BIND_APPLICATION”消息,使操作切换至主线程继续后续执行。
5:App进程会通过handleBindApplication()处理bindApplication()操作。 具体所做的事情如下:
5.1:设置App进程名、为低内存设备关闭硬件加速功能、如果系统的版本号低于3.1,则更换AsyncTask的内部的线程池实现方法、系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求、初始化http代理、创建全局唯一Instrumentation实例 等。
5.2:通过LoadedApk.makeApplication()创建App进程的唯一Application实例,回调Application的attachBaseContext()、onCreate()。
App进程执行完bindApplication()操作后,又会回到system_server进程继续后续操作。
这些操作包括如下部分:
6.1:从“焦点栈”中获取“处于栈顶的待启动Activity对应的ActivityRecord”。
6.2:通知App进程执行“scheduleLaunchActivity()”操作,在App进程进行待启动Activity的实例化、各种生命周期方法的执行、相应PhoneWindow维护的View树的绘制等操作。
这是一次IPC操作,从system_server进程切换至App进程
7:App 进程接收到LLAUNCH_ACTIVITY消息之后,会在App进程内部的handleLaunchActivity()对待启动Activity进行激活等初始化操作。 具体操作如下:
7.1:从空闲消息处理器列表中 移除 “在主线程空闲时,执行强制GC操作的空闲消息处理器” 。
7.2:在创建待启动Activity之前,先获取WMS服务在本进程的Binder代理并保存至WindowManagerGlobal。
7.3:通过performLaunchActivity()初始化ContextImpl实例、对目标Activity进行初始化、执行Activity的绑定操作、执行Activity的相应生命周期方法、等Activity执行完Resume之后,才开始对Activity的View树进行App进程内部的测量、摆放、绘制等操作。并通过ViewRootImpl内部的“编舞者来接收IO硬件产生的“Vsync”刷新信号,进而对PhoneView维护的视图树进行周期性的刷新操作。
7.4:根据AMS传递给App 进程的startsNotResumed,来决定是否需要“禁止Resume待启动Activity,如果禁止就会执行该Activity的pasue操作”。
7.5:如果初始化Activity实例失败,告诉AMS需要 “移除” 此Activity对应保存在AMS 服务中的Activity栈中的ActivityRecord。
详细过程
当Zygote进程创建并初始化完App进程后,就会通过反射执行ActivityThread.main()对main线程进行初始化。
1.1.ActivityThread.main()
main()方法是子进程执行其主线程初始化的唯一入口。
源码
public static void main(String[] args) {
//开始记录ActivityThread的初始化事件
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
......
//为主线程创建Looper
Looper.prepareMainLooper();
//初始化App进程内的ActivityThread唯一实例
ActivityThread thread = new ActivityThread();
//见小节[1.2]
thread.attach(false);
//sMainThreadHandler就是ActivityThead.H类的实例
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//ActivityThread初始化完毕之后,结束记录该事件的耗时
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//启动主线程Looper,开始处理消息
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
1.2.ActivityThread.attach()
总结
1:通过ViewRootImpl.addFirstDrawHandler()注册“View树的首次绘制完毕回调事件”。
2:通过ViewRootImpl.addConfigCallback()注册“手机配置信息发生更改之后的回调事件。”
3:通过ActivityManager.getService()获取AMS服务在本进程的BInder 代理,而后通过这个代理对象通知AMS执行attachApplication()操作。
源码
private void attach(boolean system) {
//把当前ActivityThread实例对象赋值给sCurrentActivityThread 属性。使用的时候方便通过currentActivityThread()获取。
sCurrentActivityThread = this;
//用于区分“当前进程是否是系统进程”。
mSystemThread = system;
if (!system) {
//见小节[1.2.1]
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
......
//见小节[1.3]
final IActivityManager mgr = ActivityManager.getService();
try {
//见小节[2.1]
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
} else {
//是系统进程的话,设置该进程的name为“system_process”。
//可以启动一个模拟器或者刷root之后,打开可debug的进程之后,显示的那个“system_process”。如果要调试FrameWorker层的代码的话,那么此进程就是要debug的那个进程。
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
......
}
......
//见小节[1.2.2]
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
null /* compat */)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell everyone about it.
if (mPendingConfiguration == null
|| mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
mPendingConfiguration = globalConfig;
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}
1.2.1.ViewRootImpl.addFirstDrawHandler():
总结:
1:注册“View树绘制第一帧时的回调事件”。
2:在View树绘制第一帧时,用于通知注册了此事件的被观察者,View开始绘制第一帧了。
源码
public static void addFirstDrawHandler(Runnable callback) {
synchronized (sFirstDrawHandlers) {
if (!sFirstDrawComplete) {
sFirstDrawHandlers.add(callback);
}
}
}
private void draw(boolean fullRedrawNeeded) {
......
//通知那些注册了“绘制第一帧”事件的被观察者,开始绘制第一帧了
if (!sFirstDrawComplete) {
synchronized (sFirstDrawHandlers) {
sFirstDrawComplete = true;
final int count = sFirstDrawHandlers.size();
for (int i = 0; i< count; i++) {
mHandler.post(sFirstDrawHandlers.get(i));
}
}
}
......
}
1.2.2.ViewRootImpl.addConfigCallback():添加当手机自身的配置信息发生改变之后(横竖屏切换、字体大小发生了更改等等)的回调事件。
Configuration:该类表示的是“设备的配置信息”。该类定义了许多与手机本身相关的配置信息。
1.orientation:表示当前手机的屏幕状态(横竖屏就是用这个来判断)。
2.densityDpi:屏幕密度(eg:440dpi)。
3.appBounds:屏幕大小。
4.screenLayout:该参数是一个“复合值”。具体的存储的信息如下:
4.1.屏幕整体大小:可通过该值与相应的mask进行位运算获得当前屏幕是“SMALL”、“NORMAL”、“LARGE”、“XLARGE”。
4.2.屏幕布局:表示当前屏幕中的元素是“从左往右布局”还是“从右往左布局”。取值范围为:“SCREENLAYOUT_LAYOUTDIR_LTR”、“SCREENLAYOUT_LAYOUTDIR_RTL”。
4.3.屏幕是否是圆形。
5.fontScale:字体的缩放比率。
源码
public static void addConfigCallback(ConfigChangedCallback callback) {
synchronized (sConfigCallbacks) {
sConfigCallbacks.add(callback);
}
}
1.3.ActivityManager.getService():获取AMS服务在本进程的Binder代理。
源码
public static IActivityManager getService() {
//调用IActivityManagerSingleton.get()会触发IActivityManagerSingleton中声明的create()。
//见小节[1.3.1]
return IActivityManagerSingleton.get();
}
1.3.1.Singleton.create()
源码
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
//见小节[1.3.2]
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//见小节[1.3.7]
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
1.3.2.ServiceManager.getService():获得相应系统服务在本进程的 IBinder 引用。
总结:
1:如果ServiceManager内部的HashMap缓存了此Binder服务的话,则返回。
2:如果没有,则通过getIServiceManager().getService()
重新与system_server进程建立连接,获取相应服务在本进程的Binder代理。
3:这个Binder代理对象与系统服务对象不是一个。因为AMS运行在system_server进程,此对象运行在 App进程。采用“进程隔离”的方式,每个进程都有自己的 虚拟内存地址空间,且每个进程被分配的虚拟内存地址都不一样,这就导致每个进程可访问的内存区域是不一样的,进程之间没有交集,这就避免了 “修改进程A内存区域会影响到进程B内存中的数据”。
源码
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
//此时,从本地服务缓存中获取的AMS服务的本地代理肯定为 null。
//因为这些系统服务的本地代理还没有通过 initSerivceCache()缓存起来。
if (service != null) {
return service;
} else {
//见小节[1.3.3]、[1.3.6]
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
1.3.3.ServiceManager.getIServiceManager():获取ServiceManager内部保存的IServiceManager实例。
总结:
1:如果IServiceManager实例已经初始化过了,则直接返回此实例。
2:如果还没初始化过,则需要先初始化然后返回此类实例。
源码
private static IServiceManager getIServiceManager() {
//非首次调用,则返回此类实例
if (sServiceManager != null) {
return sServiceManager;
}
// 初始化IServiceManager类实例
//见小节[1.3.4]、[1.3.5]
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
1.3.4.BinderInternal.getContextObject():获取一个IServiceManager,通过它可以获取到一些其它系统服务。
总结:
1:该方法是一个native方法,用于获取“IServiceManager类型的实例”。
2:该IServiceManager接口的实例可以用来“查询其它服务”。
源码
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
1.3.5.ServiceManagerNative.asInterface():获取一个IServiceManager类型的IBinder服务。
Binder使用上的简单介绍
1:Binder这种IPC方式采用的是CS架构。
2:IBinder表示“此类是可以用来进行IPC通信的,它提供了IPC通信的能力”。
2.1:Binder类实现了IBidner接口,实现了 “onTransact()”。
2.2:通常我们所提供的服务类要继承Binder,重写 OnTransact() 方法用于根据自己的业务处理来自Client端的请求。
总结
1:首先,判断通过“BinderInternal.getContextObject()”获得的IBinder服务是否是当前进程所创建,如果是直接返回此IBInder 服务。
2:如果不是,则返回一个 ServiceManagerProxy,把服务端在本进程的IBinder服务实例保存到这个代理对象中。这样做是为了 方便以后通过此IBinder实例与服务的所属进程进行通信。
源码
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
//根据“descriptor”从本进程中查找该Binder服务。
//1:如果此IBinder服务所属者是当前进程的话,则返回该服务。
//2:如果不是,则返回ServiceManagerProxy。其中“obj”是服务端进程的IBinder服务在本进程的一个实例。
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
//把IBinder服务在本进程的一个实例保存至ServiceManagerProxy中。
//方便以后通过此IBinder实例与服务的所属进程进行通信。
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
1.3.6.IServiceManager.getService():通过Binder IPC方式,根据name从system_server进程获取系统服务在本地进程的Binder代理对象。
源码
/**
* Retrieve an existing service called @a name from the
* service manager. Blocks for a few seconds waiting for it to be
* published if it does not already exist.
*/
public IBinder getService(String name) throws RemoteException;
1.3.7.IActivityManager.Stub.asInterface():
总结:
1:把获取的IBinder对象封装到AMS服务在子进程的Binder代理对象中。
2:此代理对象的实际类型为 IActivity.Stub.Proxy。
3:此代理对象与AMS对象一样都实现了IActivityManager接口,此接口定了AMS向外提供了哪些操作。这样做的好处是“在使用的时候,就可以直接知道可以使用AMS提供的哪些方法了”。
说明:
1:从8.0开始,AMS这种用于IPC通信的系统服务的实现方式改为AIDL 来实现。
2:8.0之前AMS内提供的 用于处理进程间操作的业务 全部是在ActivityManagerNative内部来实现,而从8.0开始采用AIDL之后,AMS直接继承自IActivityService.Stub原来处理进程间操作的业务全部挪到AMS来中完成。
因为看不到IActivityService.Stub的内部实现,所以以下代码就摘抄了一个AS编译的AIDL文件生成的的asInterface()实现(通过AIDL方式编译的此方法的实现格式是一样)。
public static sj.IMyAidlInterface asInterface(android.os.IBinder obj) {
//判断IBinder服务是否为空
if ((obj==null)) {
return null;
}
//查询此服务是否是本进程创建的
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof sj.IMyAidlInterface))) {
return ((sj.IMyAidlInterface)iin);
}
//此服务不是本进程创建的话,则返回与之对应的Proxy对象。
return new sj.IMyAidlInterface.Stub.Proxy(obj);
}
......
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
2.1.ActivityManagerService.attachApplication()
总结:
1:通过ActivityManager.getService()获取AMS服务在本进程的Binder代理对象后,调用该代理对象的attachApplication()
就会进行一次进程切换。
2:App进程会被阻塞住,一直等到system_server进程内部的AMS.attachApplication()执行完毕为止。
参数说明:
IApplicationThread threa:App进程的ApplicationThread唯一实例。关于ApplicationThread的介绍请查看本章-重要类说明
。
源码
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//获取调用者进程的pid(已经启动的App进程的id)。
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
//见小节[2.2]
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
2.2.ActivityManagerService.attachApplicationLocked()
总结:
1:根据 调用者进程的pid,获取记录此进程信息的ProcessRecord。如果获取的ProcessRecord为null的话,则表示“之前创建App进程那步出现了问题(ProcessRecord用于记录App运行在的进程信息)”,这种情况直接返回不再继续后续操作。
2:注册“Binder服务死亡通知”。这里的“服务端”指的是App进程的ApplicationThread实例(ApplicationThread继承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服务端角色)。App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源(eg:重置此进程对应的ProcessRecord中的数据,进程被kill掉之后其ProcessRecord并不会从mPidsSelfLocked缓存中移除)。
3:把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。并重置此ProcessRecord中一些参数。
4:通过App进程的ApplicationThread服务在system_server进程的Binder代理对象,执行bindApplication()来通知App进程继续后续“绑定”操作。
4.1:如果执行“bindApplication()”之后的绑定操作失败了则:取消掉已经注册的 Binder服务死亡通知。调用startProcessLocked()再通知Zygote进程重新走一遍fork子进程流程。
源码
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// 根据调用者进程的pid,获取记录此进程信息的ProcessRecord.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
......
//如果获取的ProcessRecord为null的话,则表示“之前创建App进程那步出现了问题(ProcessRecord用于记录App运行在的进程信息)”,这种情况直接返回不再继续后续操作。
return false;
}
......
try {
//注册“Binder服务死亡通知”。
//这里的“服务端”指的是App进程的ApplicationThread实例(ApplicationThread继承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服务端角色。App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源(eg:重置此进程对应的ProcessRecord中的数据,进程被kill掉之后其ProcessRecord并不会从mPidsSelfLocked缓存中移除)。)
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
......
return false;
}
......
//把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。
app.makeActive(thread, mProcessStats);
//ProcessRecord一些参数的重置操作。
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
......
try {
......
//不清楚ProcessRecord中ActiveInstrumentation类型的 instr是做什么的。
//但是无论此属性是否为null,AMS服务都会通过App进程的ApplicationThread服务在system_server进程的Binder代理对象执行bindApplication()来通知App进程继续后续操作。
if (app.instr != null) {
//见小节[2.4]
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated), //见小节[2.3]
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated), //见小节[2.3]
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
......
} catch (Exception e) {
//如果此操作出现了问题导致抛出了异常情况。
app.resetPackageList(mProcessStats);
//取消掉已经注册的 Binder服务死亡通知。
app.unlinkDeathRecipient();
//调用startProcessLocked()再通知Zygote进程重新fork一个新的子进程。
startProcessLocked(app, "bind fail", processName);
return false;
}
boolean badApp = false;
boolean didSomething = false;
//See if the top visible activity is waiting to run in this process...
//激活处于“焦点栈栈顶的待启动Activity”
//见小节[3.1]
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
......
}
}
......
return true;
}
2.3.getCommonServicesLocked.getCommonServicesLocked():获得一些公共的系统服务。
总结:
1:获得一些公共的系统Binder服务。
1.1:如果isolated为true的话,则只把PMS服务的IBinder对象回传给App进程。
1.2:如果isolated为fasle的话,则把PMS、WMS、AlarmManagerService(闹钟服务)的IBinder对象回传给App进程。
2:获得的这些服务,会通过Binder这种IPC方式回传给App进程,App进程接收到AMS发起的binderApplication()请求后,会首先通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
源码
private HashMap getCommonServicesLocked(boolean isolated) {
//如果 isolated为true的话,则只把系统服务中的“PMS”对应的Binder对象存储到Map中。
if (isolated) {
if (mIsolatedAppBindArgs == null) {
mIsolatedAppBindArgs = new HashMap<>();
mIsolatedAppBindArgs.put("package", ServiceManager.getService("package"));
}
return mIsolatedAppBindArgs;
}
if (mAppBindArgs == null) {
mAppBindArgs = new HashMap<>();
//如果 isolated为false的话,则把系统服务中的“PMS、WMS、AlarmManagerService”对应的Binder对象存储到Map中。
mAppBindArgs.put("package", ServiceManager.getService("package"));
mAppBindArgs.put("window", ServiceManager.getService("window"));
mAppBindArgs.put(Context.ALARM_SERVICE,
ServiceManager.getService(Context.ALARM_SERVICE));
}
return mAppBindArgs;
}
2.4.ApplicationThread.bindApplication()
总结:
1:通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
2:通过Handler消息机制,向App进程的主线程发一个“BIND_APPLICATION”消息,使操作切换至主线程继续后续执行。
3:该操作是一次IPC过程,涉及到进程切换,从AMS所在的system_server进程切换至App进程。AMS要想主动发起与App进程的通信,就得借助于Binder这种IPC方式,因为ApplicationThread承担的是服务端的角色,客户端发起的请求,服务端接收后都会把这些操作扔到Bidner线程池中执行,这样做的好处是提高了服务端的“并发”性能。
源码
public final void bindApplication(String processName, ApplicationInfo appInfo,
List providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
if (services != null) {
//通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
//见小节[2.5]
ServiceManager.initServiceCache(services);
}
AppBindData data = new AppBindData();
......
//见小节[2.6]
sendMessage(H.BIND_APPLICATION, data);
}
2.5.ServiceManager.initServiceCache():更新系统服务在App进程的Binder缓存。
源码
public static void initServiceCache(Map cache) {
if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
}
2.6.ActivityThread.handleBindApplication()
总结:
1:做一些准备操作。 记录进程的开始时间、设置App进程名、为低内存设备关闭硬件加速功能、如果系统的版本号低于3.1,则更换AsyncTask的内部的线程池实现方法、系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求、初始化http代理、创建全局唯一Instrumentation实例 等。
2:通过LoadedApk.makeApplication()创建App进程的唯一Application实例。
源码
private void handleBindApplication(AppBindData data) {
......
//记录进程的开始时间。
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
......
//设置App进程名
Process.setArgV0(data.processName);
//设置App进程在ddms模块显示的进程名
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
if (data.persistent) {
//为 低内存设备关闭硬件加速功能,这是为了节省资源开销。
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(false);
}
}
......
// 如果系统的版本号低于3.1,则设置AsyncTask的内部的线程池实现方法。
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
......
//系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求,如果开始了会抛出NetworkOnMainThreadException”。
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
//??
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
StrictMode.enableDeathOnFileUriExposure();
}
......
//如果App可debug调试的话,则进行debug调试的相关设置
if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
......
}
// 根据App是否可debug调试,来设置是否可以trace进程信息。
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
if (isAppDebuggable && data.enableBinderTracking) {
Binder.enableTracing();
}
//初始化http代理
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
// In pre-boot mode (doing initial launch to collect password), not
// all system is up. This includes the connectivity service, so don't
// crash if we can't get it.
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw e.rethrowFromSystemServer();
}
}
......
// 创建全局唯一Instrumentation实例,该mInstrumentation会在Activity创建完毕执行其attach()时保存至Activity内部。
if (ii != null) {
try {
//创建Instrumentation实例
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {}
......
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
......
} else {
mInstrumentation = new Instrumentation();
}
......
try {
//创建App进程的唯一Application实例
//见小节[2.7]
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//回调Instrumentation.onCreate()
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
......
//回调Application的onCreate()生命周期方法
try {
//见小节[2.8]
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
......
}
2.7.LoadedApk.makeApplication()
总结:
1:该方法做事是:创建Applicaton实例并执行该实例的attachBaseContext()与onCreate()生命周期方法。
2:判断App进程的Application是否实例化了,如果已经创建了则返回该Application。
3:系统采用反射的方式实例化Applation实例,第一步就是先指定“实例化Application的类的全限定名”。
4:通过Instrumentation.newApplication()初始化Application实例并回调其attachBaseContext()。
5:保存创建完毕的Application实例。
6:通过Instrumentation.callApplicationOnCreate()回调Application的onCreate()。
源码
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//判断App进程的唯一Application是否创建了,如果创建则直接返回。
//一个进程只有一个Application实例。
if (mApplication != null) {
return mApplication;
}
//记录 创建Application花费的时间
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
//指定“实例化Application的类的全限定名”。
//ApplicationInfo记录的是Manifest文件中中的属性信息。
//如果“未指定自定义Applcation”或者 “强制使用默认的Application”来初始化Application实例的话,则使用默认Application来
初始化
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
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实例。
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//见小节[2.7.1]
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
......
}
mActivityThread.mAllApplications.add(app);
//保存创建完毕的Application实例
mApplication = app;
//传入的instrumentation为null,不走这里
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
}
......
return app;
}
2.7.1.Instrumentation.newApplication()
总结:实例化Application实例并回调Application的attachBaseContext()生命周期方法。
源码
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
2.8.Instrumentation.callApplicationOnCreate()
总结:实例化Application实例并回调Application的attachBaseContext()生命周期方法。
源码
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
3.1.ActivityStackSupervisor.attachApplicationLocked()
总结:从“焦点栈”中获取“处于栈顶的待启动Activity对应的ActivityRecord”并激活此ActivityRecord描述的App进程的Activity。
1:一个ActivityDisplay实例表示一块屏幕,一个ActivityDisplay实例中存储了多个ActivityStack实例。
2:遍历每个ActivityDisplay中的ActivityStack集合,找到ActivityDisplay中的那个“焦点栈(ActivityStackSupervisor.mFocusedStack)”。
3:找到“焦点栈”之后,调用其topRunningActivityLocked()从其内部保存TaskRecord列表中找到“处于栈顶的待启动Activity对应的ActivityRecord”。
4:调用ActivityStackSupervisor.realStartActivityLocked()激活处于焦点栈的待启动Activity。
源码
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
//获取App进程名
final String processName = app.processName;
boolean didSomething = false;
//遍历ActivityDisplay集合。
//一个ActivityDisplay实例表示一块屏幕,一个ActivityDisplay实例中存储了多个ActivityStack实例。
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
//遍历每个ActivityDisplay中的ActivityStack集合。
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
//找到ActivityDisplay中的那个“焦点栈”。
if (!isFocusedStack(stack)) {
continue;
}
//从“焦点栈”中获取“处于栈顶的待启动Activity”。
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
//待启动Activity对应的ActivityRecord信息只是添加到了AMS中的“Activity栈”中(具体是保存到ActivityTask中的TaskRecord列表中)。
//该Activity实例还没有在App进程进行实例化,此时“ActivityRecord中保存的用于描述其所属进程的ProcessRecord还未被赋值”。所以ActivityRecord.app为null。
//检查“待启动Activity是否未被添加到所属进程”、“App进程的uid与待启动Activity在Manifest中声明的uid一致”、“App进程名与从Manifest文件中解析出的进程名一致”这3个条件是否都满足。
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//见小节[3.2]
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
3.2.ActivityStackSupervisor.realStartActivityLocked()
总结:
1:检查是否“所有的ActivityStack中的mPausingActivity表示的正在处于暂停状态的Activity执行完毕暂停操作了”。如果还有ActivityStack种的Activity正在执行暂停操作的话,则先不会执行待启动 Activity 的激活操作。
2:把描述App进程信息的ProcessRecord对象保存至ActivityRecord中。
3:通知App进程执行“ scheduleLaunchActivity()”操作,在App进程进行待启动Activity的实例化、各种生命周期方法的执行、相应PhoneWindow维护的View树的绘制等操作。**
源码
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
//检查是否“所有的ActivityStack中的mPausingActivity表示的正在处于暂停状态的Activity执行完毕暂停操作了”
if (!allPausedActivitiesComplete()) {
......
return false;
}
......
//把描述App进程信息的ProcessRecord对象保存至ActivityRecord中。
r.app = app;
......
try {
......
//见小节[3.3]
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);
......
} catch (RemoteException e) {
......
}
......
//andResume为true,走这里
//见小节[4.1]
if (andResume) {
stack.minimalResumeActivityLocked(r);
} else {
......
r.state = PAUSED;
}
......
return true;
}
3.3.ApplicationThread.scheduleLaunchActivity()
总结:通过Binder IPC方式,通知App进程执行待启动Activity的启动操作。
1:缓存AMS传递给App进程的参数信息(eg:startsNotResumed被赋值为了false,该值表示“是否需要禁止Resume待启动Activity”。如果禁止就会执行该Activity的pasue操作。true:禁止,false:不禁止)。
1:ApplicationThread作为Binder通信的服务端,其内部操作是通过Handler消息机制,向App进程的主线程发一个“LAUNCH_ACTIVITY”消息,使操作切换至主线程继续后续执行。
2:该操作是一次IPC过程,涉及到进程切换,从AMS所在的system_server进程切换至App进程。AMS要想主动发起与App进程的通信,就得借助于Binder这种IPC方式,因为ApplicationThread承担的是服务端的角色,客户端发起的请求,服务端接收后都会把这些操作扔到Bidner线程池中执行,这样做的好处是提高了服务端的“并发”性能。
源码
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) {
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;
//该值为false,在AMS所在的system_server通过Binder请求App进程的时候,notResumed为赋值为了“!andResume”,而andResume为true。
//该值表示“是否禁止Resume待启动Activity”,如果禁止就会执行该Activity的pasue操作。true:禁止,false:不禁止。
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
由于文章字数过长,请查看App启动流程:App进程内部操作-2。
重要类说明
ApplicationThread
- 从Android8.0开始,很多用于Binder IPC的类改用AIDL的方式实现,其中ApplicationThread的实现也发生了改变。
- 该类由原来继承自
ApplicationThreadNative
改为在8.0版本继承自IApplicationThread.Stub
。但是不管怎么变,我们可以知道 ApplicationThread还是用来做IPC通信的,且它在Binder这种CS架构中担任的是 服务端角色。
ServiceManager
- IServiceManager sServiceManager:该IServiceManager接口的实例可以用来“查询其它服务”(eg:从system_server进程获取AMS服务的本进程代理)。
- HashMap
sCache:用于缓存系统服务在本进程的Binder代理对象。 - initServiceCache():缓存系统服务在App进程的Binder服务。当App冷启动完毕后,会执行“AMS.attachApplication()”,在该方法内部经过层层调用,会通过传入的App进程内唯一的ApplicationThread实例通过Binder这种IPC方式,回调执行子进程的 bindApplication() 用于“初始化App进程的唯一Application实例”。在初始化之前,会首先执行 SystemService.initServiceCache()缓存系统服务在App进程的Binder服务”。
- getService():获取系统服务在本进程的Binder代理对象。
1:如果ServiceManager内部的HashMap缓存了此Binder服务的话,则返回。
2:如果没有,则通过getIServiceManager().getService()
通过Binder驱动获取Native层ServiceManager的Binder服务后,再通过ServiceManager获取已向其注册的相应Binder服务在本进程的Binder代理对象。
3:这个Binder代理对象与系统服务对象不是一个。因为AMS运行在system_server进程,此对象运行在 App进程。采用“进程隔离”的方式,每个进程都有自己的 虚拟内存地址空间,且每个进程被分配的虚拟内存地址都不一样,这就导致每个进程可访问的内存区域是不一样的,进程之间没有交集,这就避免了 “修改进程A内存区域会影响到进程B内存中的数据”。
Instrumentation
作用:
1:用于检测,Application、Activity各个生命周期方法的执行。
之所以能检测,是因为在Instrumentation内部的相应方法内部,会执行Application、Activity相应生命周期方法的执行。
也可以说“Application、Activity各个生命周期方法的执行是通过Instrumentation中的相应方法来触发的”。
2:用于检测,Activity启动结果是否成功。
Activity 通过Intent进行跳转的操作,被封装到该类的execStartActivity()中去进一步执行。
2.1:在启动目标Activity时会通过执行该类的execStartActivity()。
2.2:首先,通过AMS.startActivity()启动目标Activity。不论启动是否成功,都会返回一个int类型的result。
2.3:其次,会通过checkStartActivityResult()来检查Activity启动结果。
返回的启动结果在[-100,-1]范围的话,则会根据实际的res值抛出相应的异常,用于提示此次启动Activity具体是因为什么问题而导致启动失败了。
(像是常见的,Activity没有在manifest文件注册导致的抛出ActivityNotFoundException的原因等)。
3:其他使用场景:
3.1:自定义检测器(这个好像是用于Android 测试的),可以监听Application、Activity的各个生命周期方法调用。
就像该类的说明一下,此类是“实现应用程序检测代码的基类”。
要想自定义“检测器的话”,可以在Manifest文件中通过
3.2:可以Hook Instrumentation来达到监听Application、Activity 的目的。因为它在App进程中是唯一的,Application、Activity各个生命周期方法的执行是通过Instrumentation中的相应方法来触发的。所以说Instrumentation作为Hook点来说是比较“稳定”的,因为它在App进程中只有一个实例。
ActivityClientRecord :
- 在App进程每个Acticity组件都有一个该类的对象来对已启动Activity组件进行描述。
- 该类与ActivityRecord相对应。
- 该类存储在App进程,而ActivityRecord则存储在SystemServer进程中的AMS中的Activity栈结构中。
Activity
重要属性:
1:mStartedActivity
作用:该属性表示“是否启动了其他Activity”。该属性只有在Activity的几个startXX()(
startActivityForResult()、startActivityIfNeeded()、startActivityForResultAsUser()等等)方法被重置为true,默认值为false。
1:如果mStartedActivity为true,则表示启动了其他Activity,进一步则会使当前Activity不可见。
2:如果为false,则表示可见。