抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在安卓系统启动流程浅析中,最后由ActivityThread初始化应用的 Application 类。依旧以15的r3版本为例

ActivityThread.main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
...
Looper.prepareMainLooper();//为主线程创建一个 主 Looper(消息循环器),并将其设置为主线程的默认 Looper。
...
ActivityThread thread = new ActivityThread();//创建线程并将当前线程附加到ActivityThread,参数false表示不使用新线程
thread.attach(false, startSeq);//调用了thread.attach()方法

if (sMainThreadHandler == null) {//Handler 初始化
sMainThreadHandler = thread.getHandler();
}
...
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//跟踪
Looper.loop();//启动当前线程的消息循环
...
}

ActivityThread.attach()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//frameworks/base/core/java/android/app/ActivityThread.java   
private void attach(boolean system, long startSeq) {
//system 参数用于指示当前调用是否属于系统进程,startSeq 是一个与当前进程启动相关的唯一标识符(序列号)
sCurrentActivityThread = this;
mConfigurationController = new ConfigurationController(this);
mSystemThread = system;
mStartSeq = startSeq;
mDdmSyncStageUpdater.next(Stage.Attach);

if (!system) {//非系统进程进入此分支
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());//初始化RuntimeInit.mApplicationObject值
final IActivityManager mgr = ActivityManager.getService();//获取 ActivityManager 服务(AMS)的远程接口
try {
mgr.attachApplication(mAppThread, startSeq);//**重点**
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {// 系统进程进入此分支
...
//创建应用进程的主 Context 实例
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
//创建应用程序实例(Application 对象),并初始化它。
mInitialApplication = context.mPackageInfo.makeApplicationInner(true, null);
mInitialApplication.onCreate();
...
}

ActivityManagerService.attachApplication()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();//获取当前调用者的进程 ID(PID)。
final int callingUid = Binder.getCallingUid();//获取当前调用者的用户 ID(UID)
//清除当前线程的调用身份(即进程 ID 和用户 ID),返回唯一标识符以便后续恢复调用者身份
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);//执行核心的绑定逻辑,重点分析
Binder.restoreCallingIdentity(origId);//恢复之前保存的调用身份(即进程 ID 和用户 ID)。
}
}

attachApplicationLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private void attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
long bindApplicationTimeNanos;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);//根据pid获取application record
}
...
if (app.getIsolatedEntryPoint() != null) {// 检查是否有隔离入口点
thread.runIsolatedEntryPoint(app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
} else {//绑定流程
boolean isSdkInSandbox = false;//是否运行在沙盒 SDK 中。
ComponentName instrumentationName = null;//指定 Instrumentation 类名。
Bundle instrumentationArgs = null;// 测试时的传参。
IInstrumentationWatcher instrumentationWatcher = null;
IUiAutomationConnection instrumentationUiConnection = null;
if (instr2 != null) {
isSdkInSandbox = instr2.mIsSdkInSandbox;
instrumentationName = instr2.mClass;
instrumentationArgs = instr2.mArguments;
instrumentationWatcher = instr2.mWatcher;
instrumentationUiConnection = instr2.mUiAutomationConnection;
}
thread.bindApplication(
processName,
appInfo,//、应用信息
app.sdkSandboxClientAppVolumeUuid,
app.sdkSandboxClientAppPackage,
isSdkInSandbox,
providerList,
instrumentationName,
profilerInfo,
instrumentationArgs,
instrumentationWatcher,
instrumentationUiConnection,
testMode,
mBinderTransactionTrackingEnabled,
enableTrackAllocation,
isRestrictedBackupMode || !normalMode,
app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(),
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial,
autofillOptions,
contentCaptureOptions,
app.getDisabledCompatChanges(),
app.getLoggableCompatChanges(),
serializedSystemFontMap,
app.getStartElapsedTime(),
app.getStartUptime());
}
...
}
}

ActivityThread.bindApplication()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//frameworks/base/core/java/android/app/ActivityThread.java
@Override
public final void bindApplication(
String processName,
ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid,
String sdkSandboxClientAppPackage,
boolean isSdkInSandbox,
ProviderInfoList providerList,
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,
AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions,
long[] disabledCompatChanges,
long[] loggableCompatChanges,
SharedMemory serializedSystemFontMap,
long startRequestedElapsedTime,
long startRequestedUptime) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
for (Object oname : services.keySet()) {
if (services.get(oname) == null) {
continue; // AM just passed in a null service.
}
String name = (String) oname;

// See b/79378449 about the following exemption.
switch (name) {
case "package":
case Context.WINDOW_SERVICE:
continue;
}

if (ServiceManager.getService(name) == null) {
Log.wtf(TAG, "Service " + name + " should be accessible by this app");
}
}
}

// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}

setCoreSettings(coreSettings);

AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;
data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
data.isSdkInSandbox = isSdkInSandbox;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
data.mLoggableCompatChanges = loggableCompatChanges;
data.mSerializedSystemFontMap = serializedSystemFontMap;
data.startRequestedElapsedTime = startRequestedElapsedTime;
data.startRequestedUptime = startRequestedUptime;
updateCompatOverrideScale(compatInfo);
CompatibilityInfo.applyOverrideScaleIfNeeded(config);
sendMessage(H.BIND_APPLICATION, data);//将BIND_APPLICATION消息添加到消息队列中
}

这里的 class H extends Handler,是ActivityThread的一个内置类,H类中有处理消息的逻辑handleMessage()

handleMessage()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
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;
...
}
...
}

handleBindApplication(data)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//frameworks/base/core/java/android/app/ActivityThread.java
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
...
mBoundApplication = data;//将应用的绑定信息(AppBindData 对象)赋值给 mBoundApplication
mConfigurationController.setConfiguration(data.config);
mConfigurationController.setCompatConfiguration(data.config);
mConfiguration = mConfigurationController.getConfiguration();
mCompatibilityInfo = data.compatInfo;
...
final boolean isSdkSandbox = data.sdkSandboxClientAppPackage != null;
//获取LoadedApk对象
data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,
false /* securityViolation */, true /* includeCode */,
false /* registerPackage */, isSdkSandbox);//重点
...
//创建appContext
final IActivityManager mgr = ActivityManager.getService();
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
mConfigurationController.updateLocaleListFromAppContext(appContext);
...
long timestampApplicationOnCreateNs = 0;
try {
//此处data.info指LoadedApk, 通过反射创建目标应用Application对象
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//重点
app.setAutofillOptions(data.autofillOptions);
app.setContentCaptureOptions(data.contentCaptureOptions);
sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);
mInitialApplication = app;
final boolean updateHttpProxy;
...
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
timestampApplicationOnCreateNs = SystemClock.uptimeNanos();
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
} finally {
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}
// Preload fonts resources...
}

getPackageInfo

创建LoadedApk对象,并将将新创建的LoadedApk加入到mPackages。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage, boolean isSdkSandbox) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
// 根据不同的情况获取缓存的LoadedApk对象
if (differentUser || isSdkSandbox) {
// Caching not supported across users and for sdk sandboxes
ref = null;
} else if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}

LoadedApk packageInfo = ref != null ? ref.get() : null;

if (packageInfo != null) {
...
}

if (localLOGV) {
...
}

packageInfo =new LoadedApk(this, aInfo, compatInfo, baseLoader,securityViolation, includeCode&& (aInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}

if (differentUser || isSdkSandbox) {
// Caching not supported across users and for sdk sandboxes
} else if (includeCode) {
mPackages.put(aInfo.packageName,//更新mPackages,即将刚创建的packageInfo加入
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}

return packageInfo;
}
}

LoadedApk与Application一一对应,Application借助LoadedApk创建的,并存放在LoadedApk的mApplication字段,而在创建Application的过程中,也将LoadedApk存放在Application的mLoadedApk字段。最后返回Application的时候,也将Application存放在ActivityThread中的mInitialApplication字段。

makeApplicationInner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//frameworks/base/core/java/android/app/LoadedApk.java
private Application makeApplicationInner(boolean forceDefaultAppClass,
Instrumentation instrumentation, boolean allowDuplicateInstances) {
...
Application app = null; //新的application类

final String myProcessName = Process.myProcessName();
String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
myProcessName);
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}

try {
//获取当前应用进程的类加载器 (ClassLoader),用于加载应用程序和库的类。
final java.lang.ClassLoader cl = getClassLoader();
...
}

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// The network security config needs to be aware of multiple
// applications in the same process to handle discrepancies
NetworkSecurityConfigProvider.handleNewApplication(appContext);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);// 调用Instrumentation.java的newApplication
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
...
return app;
} ...
}

newApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//frameworks/base/core/java/android/app/Instrumentation.java
//通过工厂模式动态加载并初始化一个 Application 类
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//根据 context.getPackageName() 获取工厂实例,使用该工厂来实例化指定名称的 Application 类。
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
//通过反射机制动态创建 Application 类的实例
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}

attach

最后调用了attachBaseContext

1
2
3
4
5
6
//frameworks/base/core/java/android/app/Application.java
@UnsupportedAppUsage
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

attachBaseContext

1
2
3
4
5
6
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}

评论