App启动流程:App进程内部操作-1
目录
- 概述
- 总结
- 详细过程
- 重要类说明
概述
在冷启动过程中,“当为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<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@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<String, IBinder> 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<ProviderInfo> 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<String, IBinder> 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文件中<application>中的属性信息。
//如果“<application>未指定自定义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<ActivityStack> 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<ResultInfo> pendingResults, List<ReferrerIntent> 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<String, IBinder> 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文件中通过<instrumentation>指定具体的自定义检测器。
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,则表示可见。