Skip to content

handleBindApplication

追踪 handleBindApplication 的 compat、LoadedApk、Instrumentation、Provider、Application.onCreate 和 finishAttachApplication。

基于android-17.0.0_r1
AndroidActivityThreadApplicationContentProvider源码阅读

handleBindApplication ​

handleBindApplication() 是应用进程从“已向 AMS attach 的空壳”进入“包代码可以运行”的核心入口。AMS 通过 ApplicationThread Binder 传入 AppBindData,ActivityThread 主线程依次安装 compat、进程身份、资源配置、LoadedApk、网络安全、Instrumentation,创建 Application,先安装 ContentProvider,再调用 Application.onCreate(),最后 finishAttachApplication() 通知 AMS 应用绑定完成。

1. Bind消息入口 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
private void handleBindApplication(AppBindData data) {
    mDdmSyncStageUpdater.next(Stage.Bind);
    VMRuntime.registerSensitiveThread();

    Process.setStartTimes(
            SystemClock.elapsedRealtime(),
            SystemClock.uptimeMillis(),
            data.startRequestedElapsedTime,
            data.startRequestedUptime);

    AppCompatCallbacks.install(
            data.disabledCompatChanges,
            data.enabledCompatChanges,
            data.mLoggableCompatChanges,
            data.mLogChangeChecksToStatsD,
            data.appInfo.targetSdkVersion);

bind 在 ActivityThread 主 Handler 消费,先记录 DDM stage、注册敏感线程、保存 AMS 请求时间并安装完整 compat 数据。这里覆盖 RuntimeInit 的早期 compat 基线,因为 AMS 已提供包和进程级完整配置。

2. 进程身份与运行时 ​

java
mBoundApplication = data;
mConfigurationController.setConfiguration(data.config);
mCompatibilityInfo = data.compatInfo;

Process.setArgV0(data.processName);
DdmHandleAppName.setAppName(
        data.processName,
        data.appInfo.packageName,
        UserHandle.myUserId());
VMRuntime.setProcessPackageName(
        data.appInfo.packageName);
VMRuntime.setProcessDataDirectory(
        data.appInfo.dataDir);

进程名从 <pre-initialized> 切到真实 processName;VMRuntime 获得 package 和 data directory,用于 profile/cache。该顺序必须在加载应用代码前完成,否则静态初始化生成的缓存和诊断信息会归属错误进程。

3. 资源与LoadedApk ​

java
synchronized (mResourcesManager) {
    mResourcesManager.applyConfigurationToResources(
            data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    mConfigurationController.applyCompatConfiguration();
}

data.info = getPackageInfo(
        data.appInfo, mCompatibilityInfo,
        null, false,
        true /*includeCode*/,
        false /*registerPackage*/,
        isSdkSandbox);

先把 AMS 提供的最新 Configuration 应用到 ResourcesManager,再创建 LoadedApk。includeCode=true 允许加载 APK 代码和 classloader;SDK sandbox 还会设置独立 storage。LoadedApk 是 Application、组件和资源的包级 owner。

4. 网络与安全前置 ​

java
ContextImpl appContext = ContextImpl.createAppContext(
        this, data.info);

NetworkSecurityConfigProvider.install(appContext);
if (!Process.isIsolated()) {
    TrafficStats.init(appContext);
}

if (!Process.isIsolated()) {
    setupGraphicsSupport(appContext);
} else {
    HardwareRenderer.setIsolatedProcess(true);
}

Network Security Config 必须在应用代码创建 TLS 对象前安装;isolated process 不访问相关网络服务。graphics support 同样按 isolated 状态分流。appContext 已存在,但 Application 尚未创建。

5. Instrumentation ​

java
InstrumentationInfo ii;
if (data.instrumentationName != null) {
    ii = prepareInstrumentation(data);
} else {
    ii = null;
}

if (ii != null) {
    initInstrumentation(ii, data, appContext);
} else {
    mInstrumentation = new Instrumentation();
    mInstrumentation.basicInit(this);
}

Instrumentation 会影响 classloader 和 Application 创建,所以必须先准备。默认路径创建基础 Instrumentation;测试路径加载 instrumentation APK、runner 和参数。失败时 Application 未创建,后续 Provider/onCreate 不执行。

6. Application顺序 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
Application app = data.info.makeApplicationInner(
        data.restrictedBackupMode, null);
mInitialApplication = app;

if (!data.restrictedBackupMode
        && !ArrayUtils.isEmpty(data.providers)) {
    installContentProviders(app, data.providers);
}

mInstrumentation.onCreate(
        data.instrumentationArgs);

long timestampApplicationOnCreateNs =
        SystemClock.uptimeNanos();
mInstrumentation.callApplicationOnCreate(app);

Application 先构造并保存为 initial application;普通模式随后安装 ContentProvider,之后才执行 Instrumentation.onCreate 和 Application.onCreate。Provider 提前是 Android 启动语义的重要边界:Provider 的 onCreate() 可以早于 Application.onCreate 被外部/框架使用。restricted backup mode 使用基础 Application 并跳过 Provider,避免加载自定义应用逻辑。

7. StrictMode与异常 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
StrictMode.ThreadPolicy savedPolicy =
        StrictMode.allowThreadDiskWrites();
try {
    app = data.info.makeApplicationInner(...);
    ...
    mInstrumentation.callApplicationOnCreate(app);
} finally {
    if (data.appInfo.targetSdkVersion
            < Build.VERSION_CODES.O_MR1
            || StrictMode.getThreadPolicy()
                    .equals(writesAllowedPolicy)) {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

应用/Provider 初始化允许主线程磁盘写入,因为加载 APK、资源和 provider 通常需要 I/O;finally 按 target SDK/应用是否自行修改 policy 决定恢复。Application.onCreate 异常先交给 Instrumentation.onException;未处理时包装为“Unable to create application”并终止绑定。

8. 完成通知 ​

java
mgr.finishAttachApplication(
        mStartSeq,
        timestampApplicationOnCreateNs);

Binder.setTransactionCallback(
        (pid, code, flags, err) ->
            mgr.frozenBinderTransactionDetected(
                    pid, code, flags, err));

只有 Application.onCreate 成功后才调用 finishAttachApplication(),AMS 据此完成 startSeq 对应的进程绑定状态。随后安装 Binder transaction error callback。进程已经 attach AMS 不代表 bind 完成,finishAttach 才是应用初始化成功的重要服务端信号。

9. 失败与状态边界 ​

  • AppBindData 已收到:不代表 LoadedApk/Application 已创建;
  • LoadedApk 已创建:不代表 Provider/Application.onCreate 成功;
  • Provider 已安装:Application.onCreate 可能随后失败;
  • Application.onCreate 成功:仍需 finishAttachApplication 通知 AMS;
  • instrumentation 异常:可在 Application 之前终止;
  • ConnectivityService 为空:记录 WTF 并使用空 proxy 配置;
  • isolated process:跳过 TrafficStats/普通 graphics 网络路径。

10. 导航与后续 ​

bash
# bind 主线、compat、进程名、资源、LoadedApk 和 Application。
rg -n "handleBindApplication|AppCompatCallbacks|setArgV0|getPackageInfo|createAppContext|prepareInstrumentation|makeApplicationInner|installContentProviders|callApplicationOnCreate|finishAttachApplication" \
  frameworks/base/core/java/android/app/ActivityThread.java

# AMS 发出 bindApplication 和 finishAttach 的服务端消费。
rg -n "bindApplication\(|finishAttachApplication|AppBindData|startSeq" \
  frameworks/base/services/core/java/com/android/server/am \
  frameworks/base/core/java/android/app/ActivityThread.java

下一篇将专门分析 Application.onCreate() 前后的 Provider、Instrumentation 和进程 ready 语义;不会重复整个 bind 主线。