OH 标准系统启动结构梳理(三):samgr / safwk 启动接入链路
文档概述
说明:
1.文章由移远通信技术股份有限公司提供
2.以下内容包含了个人理解,仅供参考,如有不合理处,请联系笔者修改
1. 说明与范围
本文承接前两篇启动梳理,主题收敛到 foundation/systemabilitymgr。
这篇只关注标准系统下下面这条链:
init如何把samgr和具体 SA 进程拉起来;samgr如何建立系统能力注册中心;safwk如何解析 profile、装载 SA so、向samgr注册;- 按需拉起场景里,
LoadSystemAbility是如何把一个 SA 进程真正启动起来的。
如果只保留一句话,可以这样理解:
samgr 负责维护全局 SA 目录和进程目录,safwk 负责承载单个 SA 进程内部的 profile 解析、so 装载和 Publish(),二者通过 binder 和 profile 元数据把“进程启动”和“能力注册”衔接成一条完整链路。
2. 角色划分
先把几个角色分清楚,否则很容易把启动链看混。
2.1 samgr
samgr 是系统能力管理器,职责是全局的:
- 维护 SA 注册表;
- 维护系统进程与 SA 的映射关系;
- 提供
GetSystemAbility/LoadSystemAbility等能力访问入口; - 负责按需启动的状态编排、回调通知和超时控制;
- 在系统早期建立 IPC context object。
它不是某一个 SA 的宿主进程,而是全局注册中心和调度器。
2.2 safwk
safwk 是单个 SA 进程的承载框架,职责是进程内的:
- 解析该进程对应的 profile;
- 解析 trust profile;
dlopen目标 SA so;- 执行 SA 启动、停止、活跃和空闲流程;
- 调用
Publish()把 SA 报到samgr。它不是全局调度器,而是“一个 SA 进程内部的装载器和运行时容器”。
2.3 SA 实现体
真正的 SA 业务代码一般继承 SystemAbility 基类,通过:
MakeAndRegisterAbility()Publish()
把自己注册进 samgr。
因此,整条链不是 samgr 直接 dlopen 所有 SA,而是 safwk 在对应进程内完成 so 装载,再由 SA 自己 Publish()。
下面是三个核心角色的架构关系图,展示它们之间的协作边界:
flowchart LR
subgraph 系统层["系统层"]
init["init 进程管理器"]
end
subgraph 全局层["全局注册与调度"]
samgr["samgr\n系统能力管理器"]
end
subgraph 进程层["SA 进程内部"]
safwk["safwk\n进程内装载框架"]
SA1["SA 实现体 A"]
SA2["SA 实现体 B"]
end
init -- "start samgr" --> samgr
init -- "start sa_main + profile" --> safwk
safwk -- "dlopen + Publish()" --> SA1
safwk -- "dlopen + Publish()" --> SA2
SA1 -- "Publish() → AddSystemAbility()" --> samgr
SA2 -- "Publish() → AddSystemAbility()" --> samgr
samgr -- "GetSystemAbility / LoadSystemAbility" --> 客户端["客户端调用方"]
style init fill:#1565C0,color:#ffffff,stroke:#0D47A1,stroke-width:2px
style samgr fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style safwk fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style SA1 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style SA2 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style 客户端 fill:#6A1B9A,color:#ffffff,stroke:#4A148C,stroke-width:2px
3. 启动入口
3.1 samgr 入口
标准系统的 samgr 入口在 samgr/services/samgr/native/source/main.cpp。
主流程很短,但顺序非常关键:
- 创建
SystemAbilityManager单例; - 调
Init()建立内部状态; - 调
IPCSkeleton::SetContextObject()把自己设为 binder context object; - 调
AddSamgrToAbilityMap()把自身加入能力表; - 写系统参数
bootevent.samgr.ready=true; - 进入
IPCSkeleton::JoinWorkThread()。
也就是说,samgr 的启动不是“先把所有 SA 都拉起来”,而是先把自己变成一个可被其他进程访问的中心节点。
3.2 init 如何拉起 samgr
samgr 不是被某个上层服务再次启动的,它由 init 直接拉起。
当前仓里的接入点有两层:
samgr_standard.rc在on init中显式start samgr;samgr_standard.cfg定义 service 路径、uid/gid、socket 语义和bootevent.samgr.ready。
因此,从系统启动结构看,samgr 属于核心 boot service,而不是后续应用或框架层动态创建的进程。
3.3 safwk 入口
标准系统 safwk 主入口在 safwk/services/safwk/src/main.cpp。
它的启动方式和 samgr 不同,不是固定只跑一个名字,而是把 profile 路径作为参数带进来。
主流程可以概括成:
- 解析命令行;
- 读取 profile 路径;
- 如果是按需拉起,再额外解析
saId#eventId#name#value#extraDataId#启动原因串; - 调
LocalAbilityManager::DoStartSAProcess(profilePath, saId)。
这意味着 safwk 自身更像一个通用进程入口,真正决定它承载哪些 SA 的,是传入的 profile。
3.4 init 如何拉起具体 SA 进程
典型例子是 foundation.cfg:
- service
foundation执行/system/bin/sa_main /system/profile/foundation.json
这说明标准系统里很多 SA 进程并不是通过独立的 main 入口分别维护,而是统一走 sa_main + profile.json 这种装载模型。
从工程角度看,这样做有两个直接好处:
- 启动骨架统一;
- 进程内承载哪些 SA,尽量收敛到 profile,而不是写死在 C++ 主程序里。
4. samgr 启动主链
从系统启动角度看,samgr 的主链可以写成:
init拉起samgrsamgr mainSystemAbilityManager::Init()IPCSkeleton::SetContextObject()AddSamgrToAbilityMap()SetParameter("bootevent.samgr.ready", "true")JoinWorkThread()
这条链的核心不是代码量,而是时序位置:
- 必须先有
samgr; - 其他 SA 进程才有可能向它注册;
safwk才能把自己进程内的LocalAbilityManager报到全局。
换句话说,samgr 是整个 SA 世界的“根上下文”。
下面是 samgr 启动过程的时序图,突出关键步骤的先后依赖关系:
sequenceDiagram
participant init as init
participant samgr_main as samgr main
participant SAMgr as SystemAbilityManager
participant IPC as IPCSkeleton
participant param as 系统参数
init->>samgr_main: start samgr
samgr_main->>SAMgr: 创建单例
SAMgr->>SAMgr: Init() 建立内部状态
SAMgr->>IPC: SetContextObject()
IPC->>IPC: 设为 binder context object
SAMgr->>SAMgr: AddSamgrToAbilityMap()
SAMgr->>param: SetParameter("bootevent.samgr.ready", "true")
SAMgr->>IPC: JoinWorkThread()
Note over SAMgr,IPC: samgr 进入工作线程,开始接收 IPC 请求
rect rgb(232, 245, 233)
Note over SAMgr,param: ★ 关键节点:写 bootevent 参数,\n通知其他进程 samgr 已就绪
end
5. samgr 的全局 profile 建模
5.1 profile 扫描入口
samgr 自身不会只依赖运行时注册,它启动后还会先做一次全局 profile 建模。
入口在 SystemAbilityManager::InitSaProfile(),主要工作包括:
- 扫描
profile目录; - 过滤
.json; - 排除
_trust.json; - 对每个 profile 执行
ParseSaProfiles(file); - 初始化
abilityStateScheduler_; - 初始化
collectManager_; - 构建
saProfileMap_和onDemandSaIdsSet_。
因此,samgr 在运行初期就已经掌握了系统里“理论上存在哪些 SA、属于哪个进程、是否 run-on-create、是否支持按需启动”等全局元数据。
5.2 profile 字段模型
公共字段解析定义集中在 sa_profiles.h 和 parse_util.cpp。
一个 SaProfile 至少包含下面这些关键信息:
processsaIdlibPathdependSadependTimeoutrunOnCreatedistributedbootPhasestartOnDemandstopOnDemandrecycleStrategyextension
这些字段决定的不是单纯“怎么解析 JSON”,而是后续三类运行时行为:
- 这个 SA 是否在进程启动时直接启动;
- 这个 SA 是否由状态机按需拉起;
- 这个 SA 是否存在依赖和回收策略。
5.3 ondemand 事件
parse_util.cpp 对按需场景还做了更细的事件解析,支持:
deviceonlinesettingswitchcommoneventparamtimedevent
每类事件还能携带:
conditionsenable-onceload-priorityextra-messagespersistence
因此,samgr 的按需加载不是纯粹的“有人调一次就拉起来”,而是已经具备带条件和带事件的调度语义。
6. safwk 的进程内装载主链
6.1 DoStartSAProcess()
safwk 最重要的入口不是 main(),而是 LocalAbilityManager::DoStartSAProcess()。
这一步的主逻辑可以概括成:
InitSystemAbilityProfiles(profilePath, saId)CheckSystemAbilityManagerReady()Run()
如果翻译成职责语言,就是:
- 先知道“我要承载谁”;
- 再确认
samgr已经可用; - 最后把当前进程真正加入系统能力运行体系。
6.2 等待 samgr 就绪
这里有个容易写浅的点:safwk 并不是简单读取 bootevent.samgr.ready 参数来判断是否可注册。
它的真正判断逻辑是循环调用:
SystemAbilityManagerClient::GetSystemAbilityManager()
实现上最多重试 50 次,每次 200 ms,总计约 10 秒。
这说明 safwk 关心的不是“参数有没有被写”,而是 binder 上的 samgr 代理是否已经真的可用。
6.3 进程内 profile 解析
InitSystemAbilityProfiles(profilePath, saId) 做的事情和 samgr 那边不完全一样。
这里的目标不是全局建模,而是构建“当前进程的能力清单”,主要包括:
- 解析当前 profile;
- 解析 process 名;
- 建立当前进程内 SA 列表;
- 如果存在
<process>_trust.json,再额外读取 trust profile; - 把不在信任白名单里的 SA 从本进程 profile 中剔除。
因此,samgr 侧的 profile 解析解决“系统知道有什么”,而 safwk 侧的 profile 解析解决“当前进程最终允许装什么”。
6.4 Run()
LocalAbilityManager::Run() 是进程真正进入稳定态的入口。
核心顺序是:
AddLocalAbilityManager()- 向
samgr注册当前 system process RegisterOnDemandSystemAbility()FindAndStartPhaseTasks()
这里的 AddLocalAbilityManager() 很关键,它相当于告诉 samgr:
- 当前这个进程已经起来了;
- 它的名字是什么;
- 后续它内部的 SA 可以通过该进程来管理。
7. run-on-create SA 启动链
标准系统里最常见的一类 SA 是 run-on-create。
这条链路可以按下面顺序理解:
init启动sa_main /system/profile/<proc>.jsonsafwk main解析参数DoStartSAProcess(profilePath, saId)InitSystemAbilityProfiles()CheckSystemAbilityManagerReady()Run()InitializeRunOnCreateSaProfiles()dlopen对应 soStartSystemAbilityTask()SystemAbility::Start()- SA 内部
Publish() samgr->AddSystemAbility()
这条链路里最重要的不是 Start(),而是 Publish()。
因为只有 Publish() 之后,samgr 才真正把这个 SA 视为全局可见能力。
也就是说:
- 进程启动不等于 SA 已注册;
- so 已装载不等于 SA 已可用;
Publish()之后,能力才真正接入全局目录。
下面是 run-on-create SA 启动链的完整流程图,突出从 init 到 SA 全局可见的每一步:
flowchart TD
A["init 启动 sa_main + profile"] --> B["safwk main 解析参数"]
B --> C["DoStartSAProcess()"]
C --> D["InitSystemAbilityProfiles()"]
D --> E{"CheckSystemAbilityManagerReady()\n等待 samgr 代理可用"}
E -- 重试最多 50 次×200ms --> E
E -- 成功 --> F["Run()"]
F --> G["AddLocalAbilityManager()\n向 samgr 注册 system process"]
G --> H["InitializeRunOnCreateSaProfiles()"]
H --> I["dlopen 对应 SA so"]
I --> J["StartSystemAbilityTask()"]
J --> K["SystemAbility::Start()"]
K --> L["SA 内部 Publish()"]
L --> M["samgr->AddSystemAbility()"]
M --> N["SA 进入全局可见状态"]
style A fill:#1565C0,color:#ffffff,stroke:#0D47A1,stroke-width:2px
style B fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style C fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style D fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style E fill:#F57C00,color:#ffffff,stroke:#E65100,stroke-width:2px
style F fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style G fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style H fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style I fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style J fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style K fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style L fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style M fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style N fill:#388E3C,color:#ffffff,stroke:#1B5E20,stroke-width:2px
L ==> M
linkStyle 11 stroke:#F57F17,stroke-width:3px
8. Publish() 与注册完成
SystemAbility 基类把 SA 生命周期和注册动作封装起来了。
典型流程是:
- SA 对象被构造出来;
Start()被执行;- SA 内部调用
Publish() Publish()最终走到samgrProxy->AddSystemAbility(...)
而在 samgr 侧,AddSystemAbility() 会做几件事:
- 把 SA 写入
abilityMap_; - 更新状态机;
- 触发已登记的 load callback;
- 通知监听者该能力已经 ready。
这一步才是“启动接入链路”的真正闭环。
9. 按需拉起链路
run-on-create 只是静态启动的一半,另一半是按需启动。
9.1 入口
按需场景的用户态入口一般是:
ISystemAbilityManager::LoadSystemAbility(saId, callback)
在 samgr 侧,会进入 SystemAbilityManager::LoadSystemAbility(),再交给 SystemAbilityStateScheduler。
9.2 状态机编排
状态机的主职责不是直接启动进程,而是:
- 判断当前 SA 状态;
- 保存 load request;
- 决定是否应该触发进程拉起;
- 等待 SA
Publish(); - 在成功或超时时通知回调。
这层抽象非常重要,因为它把“调用方等待结果”和“底层进程装载能力”解耦了。
9.3 启动目标进程
真正需要拉起目标进程时,samgr 会调用 StartingSystemProcess(),必要时进一步走:
ServiceControlWithExtra(... START ...)
也就是说,按需拉起最终还是回到 init 提供的服务控制机制。
这里附带的参数格式比较特别:
saId#eventId#name#value#extraDataId#
这串参数会跟着进程启动一起传入目标 safwk 进程。
9.4 目标 safwk 进程处理
目标进程启动后,safwk main 会解析这串 ondemand 参数,并通过:
SetStartReason(saId, eventMap)
把这次启动原因写入本地上下文。
随后,LocalAbilityManager::StartAbility() 执行:
LoadSaLibOnStartAbility()
当目标 SA Publish() 完成后,samgr 才会通过:
NotifySystemAbilityLoaded()
把加载成功结果回给原始调用者。
9.5 超时处理
按需链路不是无界等待。
如果目标 SA 在规定时间内没有完成 Publish(),samgr 会通过:
SendCheckLoadedMsg()
触发加载失败路径并回调失败结果。
这说明按需加载的成功判据同样不是“进程起来了”,而是“SA 注册完成了”。
下面是按需拉起链路的状态机流程图,展示从客户端调用到回调返回的完整编排过程:
stateDiagram-v2
[*] --> 空闲: 初始状态
空闲 --> 等待加载: 客户端调用 LoadSystemAbility()
等待加载 --> 启动进程: samgr 判断 SA 未加载
启动进程 --> 等待注册: samgr 通过 init 启动目标 safwk 进程
等待注册 --> 已注册: SA Publish() 完成\nsamgr AddSystemAbility()
已注册 --> 通知回调: samgr NotifySystemAbilityLoaded()
通知回调 --> [*]: 回调返回成功
等待注册 --> 超时: 超过等待时间
超时 --> [*]: 回调返回失败
等待加载 --> 直接返回: 目标 SA 已加载
直接返回 --> [*]: 回调返回已有 SA
note right of 等待加载: 状态机保存 load request\n解耦调用方与底层装载
note right of 等待注册: 成功判据:Publish() 完成\n不是进程启动
10. trust profile 的作用
_trust.json 这条线通常容易被忽略,但它对 safwk 的装载边界很关键。
当前实现里:
samgr全局扫描阶段会主动跳过_trust.json;safwk在本进程 profile 解析阶段会额外读取<process>_trust.json;- 如果某个 SA 不在 trust 白名单中,会被从
profileParser_里移除。
因此,trust profile 不是额外描述文件,而是 safwk 进程内能力装载的最后一道约束。
它解决的是:
- 当前进程即使 profile 里写了某个 SA;
- 如果不在 trust 白名单里;
- 也不允许真正装载。
11.1 常驻 SA
init启动samgrsamgr建立 context object 并写bootevent.samgr.readyinit启动sa_main /system/profile/<proc>.jsonsafwk解析 profilesafwk等待samgr代理可用safwk向samgr注册当前 system processsafwk装载 run-on-create SA 对应 so- SA
Start() - SA
Publish() samgrAddSystemAbility()- SA 进入全局可见状态
11.2 按需 SA
- 客户端调用
LoadSystemAbility(saId, callback) samgr进入状态机samgr判断目标 SA 未加载samgr通过init启动目标safwk进程safwk解析 ondemand 参数与 profilesafwk装载目标 SA so- SA
Publish() samgrAddSystemAbility()samgr触发NotifySystemAbilityLoaded()- 回调返回成功
下面是两条核心链路的 Mermaid 流程图,便于直观对比常驻 SA 与按需 SA 的完整流程和关键节点差异:
flowchart TD
subgraph 常驻SA["常驻 SA 启动链路"]
A1["init 启动 samgr"] --> A2["samgr 建立 context object"]
A2 --> A3["写 bootevent.samgr.ready"]
A3 --> A4["init 启动 sa_main + profile"]
A4 --> A5["safwk 解析 profile"]
A5 --> A6["safwk 等待 samgr 代理可用"]
A6 --> A7["safwk 向 samgr 注册 system process"]
A7 --> A8["safwk 装载 run-on-create SA so"]
A8 --> A9["SA Start()"]
A9 --> A10["SA Publish()"]
A10 --> A11["samgr AddSystemAbility()"]
A11 --> A12["SA 进入全局可见状态"]
end
subgraph 按需SA["按需 SA 启动链路"]
B1["客户端调用 LoadSystemAbility()"] --> B2["samgr 进入状态机"]
B2 --> B3{"目标 SA 已加载?"}
B3 -- 否 --> B4["samgr 通过 init 启动目标 safwk 进程"]
B4 --> B5["safwk 解析 ondemand 参数与 profile"]
B5 --> B6["safwk 装载目标 SA so"]
B6 --> B7["SA Publish()"]
B7 --> B8["samgr AddSystemAbility()"]
B8 --> B9["samgr NotifySystemAbilityLoaded()"]
B9 --> B10["回调返回成功"]
B3 -- 是 --> B11["直接返回已有 SA"]
end
常驻SA --> 关键对比["关键对比"]
按需SA --> 关键对比
关键对比 --> C1["启动触发:init 静态启动 vs 客户端动态调用"]
关键对比 --> C2["进程创建:init 直接拉起 vs samgr 按需触发 init"]
关键对比 --> C3["成功判据:Publish() 完成,samgr 登记 SA"]
style A1 fill:#1565C0,color:#ffffff,stroke:#0D47A1,stroke-width:2px
style A2 fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style A3 fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style A4 fill:#1976D2,color:#ffffff,stroke:#1565C0,stroke-width:2px
style A5 fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style A6 fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style A7 fill:#00838F,color:#ffffff,stroke:#006064,stroke-width:2px
style A8 fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style A9 fill:#2E7D32,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style A10 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style A11 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style A12 fill:#388E3C,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style B1 fill:#6A1B9A,color:#ffffff,stroke:#4A148C,stroke-width:2px
style B2 fill:#7B1FA2,color:#ffffff,stroke:#6A1B9A,stroke-width:2px
style B3 fill:#F57C00,color:#ffffff,stroke:#E65100,stroke-width:2px
style B4 fill:#7B1FA2,color:#ffffff,stroke:#6A1B9A,stroke-width:2px
style B5 fill:#7B1FA2,color:#ffffff,stroke:#6A1B9A,stroke-width:2px
style B6 fill:#7B1FA2,color:#ffffff,stroke:#6A1B9A,stroke-width:2px
style B7 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style B8 fill:#F57F17,color:#ffffff,stroke:#E65100,stroke-width:2px
style B9 fill:#7B1FA2,color:#ffffff,stroke:#6A1B9A,stroke-width:2px
style B10 fill:#388E3C,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style B11 fill:#388E3C,color:#ffffff,stroke:#1B5E20,stroke-width:2px
style 关键对比 fill:#37474F,color:#ffffff,stroke:#263238,stroke-width:2px
style C1 fill:#455A64,color:#ffffff,stroke:#37474F,stroke-width:2px
style C2 fill:#455A64,color:#ffffff,stroke:#37474F,stroke-width:2px
style C3 fill:#455A64,color:#ffffff,stroke:#37474F,stroke-width:2px
A10 ==> A11
B7 ==> B8
linkStyle 9 stroke:#F57F17,stroke-width:3px
linkStyle 20 stroke:#F57F17,stroke-width:3px
12. 工程化理解
把实现细节抽掉后,这套链路体现了四个稳定设计点。
12.1 全局目录与进程内装载分离
samgr 只做全局目录和调度,不直接承载所有 SA;safwk 只做本进程内装载,不做全局注册中心。这种拆分让职责边界非常清晰。
12.2 profile 是装载边界,不只是配置文件
无论是 samgr 的全局 profile 解析,还是 safwk 的本地 profile 解析,profile 都不仅仅是“描述信息”,而是后续启动和注册行为的直接输入。
12.3 进程 ready 不等于 SA ready
无论是常驻还是按需场景,真正的成功判据都是 Publish() 完成,samgr 已登记该 SA,而不是某个可执行文件已经启动。
12.4 按需启动最终仍回到 init 服务控制
samgr 虽然负责状态机和调度,但真正的进程拉起仍然回到 init 的 service control。也就是说,系统级启动控制面还是收敛在 init。
13. 建议的阅读顺序
如果后续要继续下钻,建议按下面顺序看:
foundation/systemabilitymgr/samgr/services/samgr/native/source/main.cppfoundation/systemabilitymgr/samgr/etc/samgr_standard.cfgfoundation/systemabilitymgr/samgr/services/samgr/native/samgr_standard.rcfoundation/systemabilitymgr/safwk/services/safwk/src/main.cppfoundation/systemabilitymgr/safwk/services/safwk/src/local_ability_manager.cppfoundation/systemabilitymgr/safwk/services/safwk/src/system_ability.cppfoundation/systemabilitymgr/samgr/services/common/src/parse_util.cppfoundation/systemabilitymgr/samgr/interfaces/innerkits/common/include/sa_profiles.hfoundation/systemabilitymgr/samgr/services/samgr/native/source/system_ability_manager.cppfoundation/systemabilitymgr/samgr/services/samgr/native/source/schedule/system_ability_state_scheduler.cppfoundation/systemabilitymgr/safwk/etc/profile/foundation.cfg
按这个顺序看,先抓住“谁启动谁”,再看“怎么解析 profile”,最后看“怎么按需拉起”,会比较容易建立整体脑图。
更多推荐


所有评论(0)