1、使用的是Android 7.1.2的源代码:
https://pan.baidu.com/s/1XcVD68cC_2wKtm8jJkdNQA
przv
2、感谢IT先森的系列博客:
Android应用进程创建流程大揭秘
Android四大组件之bindService源码实现详解
Android四大组件之Activity启动流程源码实现详解概要
Activity启动流程(一)发起端进程请求启动目标Activity
Activity启动流程(二)system_server进程处理启动Activity请求
Activity启动流程(三)-Activity Task调度算法复盘分析
Activity启动流程(四)-Pause前台显示Activity,Resume目标Activity
Activity启动流程(五)请求并创建目标Activity进程
Activity启动流程(六)注册目标Activity进程到system_server进程以及创建目标Activity进程Application
Activity启动流程(七)初始化目标Activity并执行相关生命周期流程
当Zygote创建完一个应用进程之后,得到的仅仅是一个可以运行的载体,但是,Android的四大组件还没有进入到这个新创建的进程之中。
当Zygote进程创建目标Activity进程之后,还需要创建一个运行环境Context,然后创建Application,然后再装载Provider等组件信息。
目标Activity所属的应用进程已经创建好了,接下来,包括如下流程:
伪代码:
ATP.bindApplication()--->
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.bindApplication(...) --->
ApplicationThread.bindApplication(...) --->
ActivityThread.H.sendMessage(H.BIND_APPLICATION,...) --->
ActivityThread.handleBindApplication(...) --->
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//创建LoadedApk
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);//构建ContextImpl
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();//构建Instrumentation
installContentProviders(app, data.providers);//安装ContentProvider
mInstrumentation.callApplicationOnCreate(app);//调用Application的onCreate方法
问题:目标Activity进程是由AMS创建的,为什么还需要将其注册到system_server进程?
答:通过attach的Binder远程调用传递匿名Binder类IApplicationThread给AMS,然后AMS就可以通过上述的匿名Binder来继续对目标Activity进程的相关组件进行调度。
public static void main(String[] args) {
··· ···
Environment.initForCurrentUser();
··· ···
Process.setArgV0("" );
//创建主线程Looper
Looper.prepareMainLooper();
//创建一个新的ActivityThread
ActivityThread thread = new ActivityThread();
//attach到系统进程
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//主线程进入循环状态
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
注意:
ActivityThread就是应用程序的主线程,这种说法是笼统的,因为ActivityThread并非真正意义上的线程,它不是Thread的子类。在ActivityThread对象构建时,会创建一个Handler对象,这个Handler对象所绑定的消息队列就是主线程的消息队列,后面主线程所做的任何事情都是往Handler中发送消息来完成的,所以说Android系统是基于消息驱动的。主线程实现Looper,就是在new ActivityThread()时实现的,即在ActivityThread.main()中构造ActivityThread对象时初始化的Looper。
public final class ActivityThread {
final Looper mLooper = Looper.myLooper();
final H mH = new H();
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
···
}
··· ···
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
··· ···
}
在构造函数初始化时,其上面的变量也都会初始化:
public class One {
private class H{
H(){
System.out.println("One::H():::");
}
}
H mH = new H();
int a = 3;
public One() {
System.out.println("One::One():::" + a);
}
}
public class Two {
public static void main(String args[]) {
One mOne = new One();
}
}
输出结果为:
One::H():::
One::One():::3
final ApplicationThread mAppThread = new ApplicationThread();
//system参数的作用是区别是system_server进程发起的绑定还是普通应用进程发起的绑定
//我们现在是子进程发起的绑定
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
//设置进程名。
android.ddm.DdmHandleAppName.setAppName("" ,
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread); //这里的mAppThread是一个匿名Binder实例
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
··· ···
} else {
//系统进程走这里
}
}
上述流程中,通过AMP借助Binder调用AMS的方法attachApplication,注意这里传递的mAppThread是一个匿名Binder实例,因此可以作为跨进程传递的参数。这里的mAppThread对象存在于应用进程,但会被传递到系统进程,在系统进程看来,此时的mAppThread就是操作应用进程的一个通信工具。后续,系统进程system_server如果想要向应用进程发起跨进程调用,也都需要通过mAppThread这个对象来完成相关的调度。
// [AMS]
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//获取调用进程端pid
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
调用attachApplicationLocked进行下一步的处理,此时多了个参数pid。
注意,在Android源码中带Locked的方法,一般都需要进行加锁操作
在attachApplicationLocked中,会根据pid映射应用进程的ProcessRecord对象,在Android四大组件之Activity(五)——AMS:针对新启动的Activity创建一个新的进程 中的AMS.startProcessLocked中会将通过Process.start生成的pid给put到mPidsSelfLocked中。
// [AMS]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
/*
1、根据PID映射应用进程的ProcessRecord对象
那么此处的ProcessRecord是什么时候创建并加入到mPidsSelfLocked中的呢,这个在该系列博客的五中有详细描述
*/
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {//当获取目标Activity进程的ProcessRecord失败,则会执行清理逻辑,并强制退出
// 获取ProcessRecord对象失败,则做一些清理操作后退出
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
}
}
return false;
}
/*
当下需要将ProcessRecord绑定到一个新的进程
所以需要将之前ProcessRecord所绑定的进程信息清除
这个地方有点难理解,我们可以认为对此处的ProcessRecord进行复用,在复用之前需要做一些清理
*/
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
final String processName = app.processName;
try {
/*
2、注册应用进程的DeathRecipient,当应用进程崩溃时,系统进程可以收到通知
为啥要整这一套呢,主要是因为AMS服务监听到应用进程奔溃以后需要做一些资源包回收和数据结构的调整
关于AppDeathRecipient可以参见大神gityuan的博客http://gityuan.com/2016/10/03/binder_linktodeath/
*/
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
//3、激活ProcessRecord对象
//将目标Activity进程的IApplicationThread匿名Binder代理端绑定到ProcessRecord对象
app.makeActive(thread, mProcessStats);
/****************************************************/
//这里为了演示方便,直接给出源码
//[ProcessRecord.java]
final class ProcessRecord {
IApplicationThread thread;
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
if (thread == null) {
...
}
thread = _thread;
}
}
/****************************************************/
//继续进行其它的对ProcessRecord的赋值
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
//移除进程启动超时消息,就是前面ANR的埋雷机制
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
// 4、获取应用进程的所有Provider
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
//这又是一个ANR埋雷,后续在ContentProvider发布的时候会进行解除
if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
}
...
try {
...
//省略debug和性能优化等相关配置的代码,这里就不赘述了
//5、这里又是老熟人了,一路分析过来见过很多次了,此处发起跨进程调用,将一堆的信息传递给目标Activity应用进程
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
...
} catch (Exception e) {//异常处理
...
}
mPersistentStartingProcesses.remove(app);
mProcessesOnHold.remove(app);//将该ProcessRecord从ProcessesOnHold列表中移除
boolean badApp = false;
boolean didSomething = false;
//此处表示目标Activity进程是正常启动模式,此时肯定是
if (normalMode) {
try {
//6-1、此处是关键啊,检查有没有待启动的activity,假如目标Activity是被冷启动则会在此处流程执行
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
if (!badApp) {
try {
//6-2、检查有没有待启动的service,这个我们再binderService有涉及到过
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
badApp = true;
}
}
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
//6-3、查有没有待启动的receiver
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
badApp = true;
}
}
...
/*
假如启动目标Activity,Service,或者BroadCast任何一个执行失败,
都会kill掉目标Activity进程,并且执行handleAppDiedLocked的处理
*/
if (badApp) {
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
if (!didSomething) {
updateOomAdjLocked();
}
return true;
}
上述代码的主要逻辑:
系统启动时,也经历过这个过程,系统进程对应的包名是“android”,扫描的是framework-res.apk的这个应用的信息。
开始应用进程的自我成长。
此时目标Activity应用进程有了自己的进程名,并且在接下来会构建出Android的运行环境,真正有了Android应用程序的概念,即Application。
新创建的进程处理bindApplication的RPC请求:
//[ActivityThread.java]
private class ApplicationThread extends ApplicationThreadNative {
...
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<String, IBinder> services, Bundle coreSettings) {
//此处缓存的是通过bindApplication传递过来的PKMS,WMS,ALARM_SERVICE代理端
if (services != null) {
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
//将AMS传递过来的参数封装到AppBindData 数据结构中
AppBindData data = new AppBindData();
data.processName = processName;
...
//巧用ActivityThread的主线程的Handler发送消息
sendMessage(H.BIND_APPLICATION, data);
}
...
}
在上述代码中,将system_server进程传递过来的与应用进程相关的信息打包到了AppBindData 类型的变量 data 中,接下来会将上述的相关信息一起组装成Android应用程序运行所必须的构成元素。
//[ActivityThread.java]
private class H extends Handler {
··· ···
public static final int BIND_APPLICATION = 110;
public void handleMessage(Message msg) {
··· ···
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
//[ActivityThread.java]
private void handleBindApplication(AppBindData data) {
...//省略一些相关的参数设置
//虽然说目标Actiivity进程在之间已经fork出来了,但是系统直到此时才是它的开端
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
// 虽然应用进程早就已经创建,但直到这时,才知道进程名是什么
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());
... // 省略应用进程运行信息其它的一些设置代码,譬如语言,时区
//2.1、创建LoadedApk对象,此处是关键,后续会专门分析
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//Android应用默认dpi相关设置
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
updateDefaultDensity();
//设置时间格式
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
...
//StrictMode相关的设置
StrictMode.enableDeathOnNetwork();
//应用进程相关的初始化代码,包含时区、StrictMode、调试模式等相关的设置,感兴趣的小伙们就自行研究吗
...
final InstrumentationInfo ii;
··· ···
//2.2、创建ContextImpl对象;
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
/*
2.3、创建Instrumentation
它也是我们的老熟人了,在前面分析的四大组件相关的生命周期调度中多次看到它了
这里通过ClassLoader直接加载进行构建,在整个Android应用进程中它是唯一的
网上很多博客将Instrumentation说为Android系统里面的一套控制方法或者”钩子“。
这些钩子可以在正常的生命周期(正常是由操作系统控制的)之外控制Android控件的运行
*/
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
··· ···
}
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
...
}
} else {
mInstrumentation = new Instrumentation();
}
//2.4、创建Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//2.5、安装providers,看来providers的安装都前于其它三大组件啊
List<ProviderInfo> providers = data.providers;
installContentProviders(app, providers);
//2.6、这不Instrumentation刚被创建就被排上了用场执行Application.Create回调
mInstrumentation.callApplicationOnCreate(app);
}
在上述代码中:
//[ActivityThread.java]
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
2.1.2 ActivityThread.getPackageInfo(…)
//[ActivityThread.java]
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
private LoadedApk getPackageInfo(ApplicationInfo aInfo, //这个是AMS通过bindApplication传递过来的Activity应用进程AndroidManifest中Application的的相关数据结构
CompatibilityInfo compatInfo,//对ApplicationInfo数据结构的又一层封装
ClassLoader baseLoader, //类加载器,此时为null
boolean securityViolation, //表示隐私,此时为false
boolean includeCode,//功能不详,此时为true
boolean registerPackage) //功能不详,此时为false
{
//多用户情况的判断
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
ref = null;
} else if (includeCode) {//进入此分支,从mPackages查询,由于前面没有创建并且存储过,所以此处获取的为null
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
//直接new出一个
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);//详见2.3.2
//system_server进程会进入此分支,这里不会进入此分支
if (mSystemThread && "android".equals(aInfo.packageName)) {
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}
if (differentUser) {
} else if (includeCode) {
//将前面创建的LoadedApk放入mPackages列表
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
该方法的作用:
//[LoadedApk.java]
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
mActivityThread = activityThread;
setApplicationInfo(aInfo);
/*****************************************************************************/
//这里为了演示方便,直接将源码搬出来!
private void setApplicationInfo(ApplicationInfo aInfo) {
final int myUid = Process.myUid();
aInfo = adjustNativeLibraryPaths(aInfo);
mApplicationInfo = aInfo;
mAppDir = aInfo.sourceDir;
mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
mSplitAppDirs = aInfo.splitSourceDirs;
mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
mOverlayDirs = aInfo.resourceDirs;
mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
mLibDir = aInfo.nativeLibraryDir;
mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
}
/*****************************************************************************/
mPackageName = aInfo.packageName;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
mRegisterPackage = registerPackage;
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
}
在构造方法中记录了Activity运行所在的ActivityThread、Activity所在的应用程序信息、Activity所在应用进程的包名、Activity所在应用进程的库路径、Activity所在应用进程的数据存储路径、类加载器和应用程序所使用的资源等信息。
最终相关Context上下文的操作都是由ContextImpl来执行的。
//[ContextImpl.java]
static ContextImpl createAppContext(ActivityThread mainThread, //这里传入的是ActivityThread的引用
LoadedApk packageInfo) //前面构建的LoadedApk实例对象引用
{
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}
//[ContextImpl.java]
class ContextImpl extends Context {
final ActivityThread mMainThread;
final LoadedApk mPackageInfo;
private final IBinder mActivityToken;
private final String mBasePackageName;
private Context mOuterContext;
//缓存Binder服务
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
private ContextImpl(ContextImpl container,
ActivityThread mainThread,
LoadedApk packageInfo,
IBinder activityToken,
UserHandle user,
boolean restricted,
Display display,
Configuration overrideConfiguration,
int createDisplayWithId) {
mOuterContext = this; //ContextImpl对象
mMainThread = mainThread; // ActivityThread赋值
mPackageInfo = packageInfo; // LoadedApk赋值
mActivityToken = activityToken;//这个通常是Activity在构建其ContextImpl时候传入的
mBasePackageName = packageInfo.mPackageName; //mBasePackageName通常等于应用进程包名
...
}
}
创建ContextImpl的方式有多种, 不同的组件初始化调用不同的方法:
1)Activity: 调用createBaseContextForActivity初始化;
2)Service/Application: 调用createAppContext初始化; -->本节调用的是createAppContext
3)Provider: 调用createPackageContext初始化;
4)BroadcastReceiver: 直接从Application.getBaseContext()来获取ContextImpl对象;
//[Instrumentation.java]
//构造方法啥也没有干,看来是通过其它
public Instrumentation() {
}
final void init(
ActivityThread thread,//持有对ActivityThread实例对象的引用
Context instrContext,
Context appContext,
ComponentName component,
IInstrumentationWatcher watcher,
IUiAutomationConnection uiAutomationConnection) {
mThread = thread;
mMessageQueue = mThread.getLooper().myQueue();
mInstrContext = instrContext;
mAppContext = appContext;
mComponent = component;
mWatcher = watcher;
mUiAutomationConnection = uiAutomationConnection;
}
在一个应用进程中,Instrumentation实例对象都是唯一的。
从2.1中看到,data.info是LoadedApk对象
//[LoadedApk.java]
public Application makeApplication(
boolean forceDefaultAppClass,//该值是从AMS中传递过来的
Instrumentation instrumentation) //此时的instrumentation已经被指定为null
{
/*
1、保证一个LoadedApk对象只创建一个对应的Application对象实例,
和我们章节开始所说的每个应用进程只拥有一个Application相对应
*/
if (mApplication != null) {
return mApplication;
}
...
Application app = null;
/*
获取Application名称,即我们在AndroidManifest中Application的名称
如果我们没有实现自己的Application,通常appClass就是null了
*/
String appClass = mApplicationInfo.className;
//强制给Application一个名称
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//2、获取当前应用的ClassLoader对象
java.lang.ClassLoader cl = getClassLoader();
//system_server进程除外
if (!mPackageName.equals("android")) {
//设置当前线程的Context ClassLoader
initializeJavaContextClassLoader();
}
//3、和2.2.1中一样,根据当前 ActivityThread 对象来创建相应的 ContextImpl 对象
//这里的appContext变量为方法内部变量
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//4、创建Application对象, 并将appContext和创建的Application关联起来
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app); //-->ContextImpl.setOuterContext(...)
} catch (Exception e) {
,,,
}
//这个地方不是很明白,ActivityThread通常不是一个应用进程只有一个,而且Application也是唯一的吗,为啥这里要整个
//存放Application的列表进行存放呢,纳尼
mActivityThread.mAllApplications.add(app);
mApplication = app;//将刚创建的app赋值给mApplication
if (instrumentation != null) {//此时的instrumentation已经被强制位null,所以此分支肯定不会走
...
}
...
return app;
}
//[ContextImpl]
final void setOuterContext(Context context) {
mOuterContext = context;
}
在上述代码中,appContext是makeApplication()方法的内部变量,调用 appContext.setOuterContext(app); 将新创建的 Application 对象 app 保存到 ContextImpl 的成员变量 mOuterContext 的话,方法运行结束变量 appContext 不就销毁了吗,那么作用是什么?
答:因为 Application 对象 app 创建的时候,即
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
持有对 appContext 的引用,而且可以通过getApplication获取唯一的Application实例对象,然后通过这个Application对象可以获取到这里的ContextImpl实例对象,即可以获取到其保存的mOuterContext。
//[Instrumentation.java]
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);//执行attach操作
return app;
}
//[Application]
final void attach(Context context) {
attachBaseContext(context); //Application的mBase
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
attach方法的作用:
在Android原生应用中可以看到许多的Provider:
XXX:/system/priv-app # ls | grep Provider
ContactsProvider
DownloadProvider
ExternalStorageProvider
MediaProvider
MtpDocumentsProvider
SettingsProvider
TelephonyProvider
//[ActivityThread.java]
private void installContentProviders(Context context,
List<ProviderInfo> providers) //注意这里的参数,是AMS传递过来的在AndroidManifest中的注册的Provider信息
{
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
//这个就不分析了,总之会注册到AMS中去
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
// [ActivityThread]
private IActivityManager.ContentProviderHolder installProvider(Context context, IActivityManager.ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
if (holder == null || holder.provider == null) {
Context c = null;
ApplicationInfo ai = info.applicationInfo;
if (context.getPackageName().equals(ai.packageName)) {
c = context;
} else if (mInitialApplication != null &&
mInitialApplication.getPackageName().equals(ai.packageName)) {
c = mInitialApplication;
} else {
//step 1 && 2: 创建LoadedApk和ContextImpl对象
c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);
}
final java.lang.ClassLoader cl = c.getClassLoader();
//step 3: 创建ContentProvider对象
localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
//step 4: ContextImpl都attach到ContentProvider对象
//step 5: 并执行回调onCreate
localProvider.attachInfo(c, info);
} else {
...
}
...
return retHolder;
}
//[Instrumentation.java]
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
本来待启动的应用程序进程为一个赤裸裸的进程,但是
AMS.attachApplicationLocked 执行完 thread.bindApplication 之后,接着执行6