Application 初始化流程

文章详细解析了AndroidApplication的onCreate和attachBaseContext的调用顺序,以及整个应用初始化过程,包括创建ContentImpl、Instrumentation、Application对象,启动ContentProvider和调用onCreate方法。在attachBaseContext时,Application尚未完全创建,调用getApplicationContext会返回空。文章讨论了在同步初始化和多ContentProvider场景下,AppStartup的适用性和性能优化问题,并推荐使用同步+异步初始化结合拓扑排序的方法。

Application 的 onCreate 和 attachBaseContext

Application 的 onCreate 和 attachBaseContext 是 Application 的两个回调方法,通常我们会在其中做一些初始化操作。

onCreate 和 attachBaseContext 顺序: Application 的 attachBaseContext 在 onCreate 之前执行。

handleBindApplication

App 的 application 创建是在 ActivityThread 的 handleBindApplication 方法完成的。

  private void handleBindApplication(AppBindData data) {
     ....
     final InstrumentationInfo ii;
     ....
     if (ii != null) {
       //1.创建ContentImpl
       final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                    "Unable to instantiate instrumentation "
                    + data.instrumentationName + ": " + e.toString(), e);
            }
        //2.创建Instrumentation
      final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
        ....
        //3.创建Application对象
         Application app;
         app = data.info.makeApplication(data.restrictedBackupMode, null);
         // Propagate autofill compat state
            app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
            mInitialApplication = app;
        ...
        //4.启动当前进程中的ContentProvider和调用其onCreate方法
        if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }
        //5.调用Application的onCreate方法
        try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                }
            }
    }
 }

可以看到初始化顺序: 1.创建ContentImpl -> 2.创建Instrumentation -> 3.创建Application对象 并调用 attachBaseContext方法 -> 4.启动当前进程中的ContentProvider和调用其onCreate方法 -> 5.调用Application的onCreate方法

总结

Application 的 attachBaseContext 在 onCreate 之前执行。attachBaseContext 中拿到了创建的 ContextImpl,但是此时 Application 没有创建完成,比如 mLoadedApk 的赋值还没有执行。此时如果在 attachBaseContext 中调用 this.getApplicationContext,也会返回空,因为 application 还没有创建完成。等到回调了 onCreate 时,Application 才算真正构造完毕。

如果项目中的初始化都是同步初始化的话,并且使用到了多个ContentProvider,App Startup 还是不错的,毕竟统一到了一个ContentProvider中,同时支持了简单的顺序依赖。

但是如果在追求App性能与启动速度的场景中,多个SDK同时利用各自定义的ContentProvider实现“自启动”, 在各种有先后顺序与依赖的SDK初始化下做优化,那么 App Startup 就不是很好用了。也正式这个原因,目前不建议将 App Startup 用于生产环境中。

目前的推荐方案还是之前我们都使用过的:同步+异步初始化,并通过有向无环图拓扑排序的方式; Anchors

<think>我们正在讨论指纹TA(Trusted Application)的初始化流程。根据之前的对话,指纹TA的加载流程已经概述过,现在用户要求更详细的初始化流程。结合用户提供的引用[1],我们知道指纹TA的初始化是在指纹服务调用链的最后一步,由指纹CA(Client Application)通过TEE驱动触发。 指纹TA初始化的具体步骤(基于ARM TrustZone架构)如下: 1. **CA发起会话请求**:普通世界的指纹CA(如fingerprint.default.so中的Fingerprint.cpp)通过ioctl系统调用向TEE驱动发送打开会话的指令(对应命令`TA_OPEN_SESSION`)[^1]。 2. **世界切换**:TEE驱动接收到指令后,通过SMC(Secure Monitor Call)指令触发安全监控模式(EL3),将CPU从普通世界(Non-Secure World, NS)切换到安全世界(Secure World, S)。 3. **TEE内核处理请求**:在安全世界,TEE内核(例如OP-TEE的core)接收到打开会话的请求,解析出需要加载的TA UUID(指纹TA的唯一标识符)。 4. **TA加载与验证**:如果该TA尚未加载,TEE内核会从安全存储分区读取TA的加密镜像(如`fpchips.mdt`和多个`.bXX`分段文件),并进行以下操作: - **验证签名**:使用TEE供应商的公钥验证TA的签名,确保其完整性和来源可信。 - **解密分段**:使用硬件加密引擎(如TrustZone CryptoCell)动态解密每个分段。 - **内存映射**:将解密后的代码和数据映射到安全内存区域(TEE的内存空间)。 5. **创建TA实例**: - **分配上下文**:TEE内核为TA分配一个安全上下文(包括私有堆栈、寄存器状态、堆内存等)。 - **初始化全局变量**:将TA的.data段(已初始化的全局变量)和.bss段(未初始化的全局变量)置零或赋予初始值。 - **设置入口点**:准备执行TA的初始化函数。 6. **执行TA初始化函数**: - 跳转到TA的入口函数`TA_OpenSessionEntryPoint`(由TA开发者实现)。该函数通常完成以下任务: - 初始化内部状态(如算法模块、硬件资源)。 - 打开与指纹传感器SPI的通信通道(需声明访问安全外设的权限)。 - 申请安全内存用于存储临时数据(如指纹图像)。 - 返回状态码(如`TA_SUCCESS`表示初始化成功)。 7. **建立CA-TA通信通道**: - TEE内核为此次会话创建一个唯一的会话ID(Session ID)。 - 在共享内存区域(安全世界与普通世界之间的通信缓冲区)建立加密通道(如使用AES-GCM保护通信数据)。 8. **返回结果**:TEE内核将初始化结果(会话ID或错误码)通过SMC返回给普通世界的TEE驱动,最终传递给指纹CA。 9. **错误处理**:若初始化失败(如签名验证错误、资源不足),TEE内核会销毁已分配的资源,并向CA返回错误码。 ```mermaid sequenceDiagram participant CA as 指纹CA (普通世界) participant Driver as TEE驱动 participant SMC as 安全监控模式(EL3) participant TEE_Kernel as TEE内核 participant TA as 指纹TA CA->>Driver: 发送TA_OPEN_SESSION命令 Driver->>SMC: 触发SMC指令 SMC->>TEE_Kernel: 切换至安全世界 TEE_Kernel->>TEE_Kernel: 解析TA UUID,加载TA镜像 TEE_Kernel->>TEE_Kernel: 验证签名并解密 TEE_Kernel->>TA: 分配安全上下文 TEE_Kernel->>TA: 调用TA_OpenSessionEntryPoint TA->>TA: 初始化算法/硬件 TA->>TEE_Kernel: 返回初始化结果 TEE_Kernel->>SMC: 返回会话ID/错误 SMC->>Driver: 切换回普通世界 Driver->>CA: 传递结果 ``` ### 关键安全机制 - **内存加密**:TA的代码和数据在安全内存中以明文形式存在,但普通世界无法访问。 - **权限控制**:TA在初始化时需声明其访问的资源(如指纹传感器),TEE内核会检查其权限。 - **隔离性**:每个TA运行在独立的安全上下文中,互不影响。 §§相关问题§§ 1. `TA_OpenSessionEntryPoint` 函数中通常包含哪些具体初始化操作? 2. 如果指纹传感器初始化失败,TA 如何处理? 3. TEE 内核如何管理多个 TA 的并发初始化请求? 4. 指纹 TA 的初始化时间对用户体验有何影响?</think>### 指纹 TA 初始化流程详解 指纹 TA(Trusted Application)的初始化是安全执行环境中的关键环节,其核心流程如下(基于 ARM TrustZone 架构): --- #### **1. 初始化触发** - **CA 调用**:普通世界的指纹客户端(如 `Fingerprint.cpp`)通过 **TEE 驱动** 发送 `TA_OpenSession` 命令[^1]。 - **世界切换**:触发 **SMC 指令**,CPU 从普通世界(Non-Secure)切换到安全世界(Secure),进入 **TEE 内核**(如 QSEE/OP-TEE)。 --- #### **2. TA 上下文创建** - **资源分配**: - TEE 内核为 TA 分配 **私有安全内存**(包括代码区、堆栈、数据段)。 - 初始化 **安全寄存器状态**,隔离其他 TA 的访问。 - **权限检查**: - 验证 TA 声明的权限(如访问 SPI 传感器或密钥库)是否匹配其数字证书[^3]。 --- #### **3. 入口函数执行** TEE 内核跳转到 TA 的 **入口函数** `TA_OpenSessionEntryPoint`,该函数由开发者实现,执行以下操作: 1. **硬件初始化**: - 配置指纹传感器 SPI 接口(如设置采样率、电压)。 - 复位传感器并检查就绪状态(超时或错误则返回 `TA_ERROR_HW_COMMUNICATION`)[^1]。 2. **算法模块加载**: - 解密预置的指纹模板(如 AES-256 解密)。 - 初始化特征提取和比对算法(如初始化神经网络模型权重)。 3. **安全资源申请**: - 分配 **加密内存缓冲区** 用于临时存储原始指纹图像。 - 生成 **会话密钥**(用于 CA-TA 通信加密)。 --- #### **4. IPC 通道建立** - **共享内存映射**: - TEE 内核创建 **安全世界与普通世界的共享内存区**(如 `dma_buf`)。 - 启用 **内存加密引擎**(如 TrustZone CryptoCell)保护数据传输[^3]。 - **中断注册**: - 在 EL3 层注册指纹传感器中断(参考引用[2]的 `ehf_el3_interrupt_handler`): ```c // 示例:中断优先级注册(类似 ARM BL31 流程) ehf_pri_desc_t plat_exceptions[] = { EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_FP_SENSOR_PRI), // 指纹传感器中断优先级 }; EHF_REGISTER_PRIORITIES(plat_exceptions, ...); ``` - 绑定中断服务例程(ISR)到 TA,用于实时响应传感器数据。 --- #### **5. 状态返回** - 若初始化成功: - 返回 `TA_SUCCESS` 和会话句柄(Session Handle)给 CA。 - 若失败: - 释放所有资源,返回错误码(如 `TA_ERROR_STORAGE` 或 `TA_ERROR_OUT_OF_MEMORY`)。 --- ### 安全机制设计 1. **运行时隔离**: - TA 的代码和数据仅存在于安全内存,普通世界无法直接访问[^3]。 2. **防篡改通信**: - CA-TA 通信使用会话密钥加密(如 AES-GCM),并附加 MAC 校验。 3. **原子性操作**: - 初始化失败时,TEE 内核确保资源完全回滚(无残留数据)。 ```mermaid sequenceDiagram participant CA as 指纹CA (普通世界) participant TEE_Kernel as TEE内核 participant TA as 指纹TA CA->>TEE_Kernel: TA_OpenSession 请求 TEE_Kernel->>TA: 分配安全内存+寄存器 TEE_Kernel->>TA: 调用 TA_OpenSessionEntryPoint TA->>TA: 初始化传感器/算法 TA->>TA: 申请加密缓冲区 TA->>TEE_Kernel: 请求注册中断 TEE_Kernel-->>CA: 返回会话句柄/错误码 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值