文件最后提交记录最后更新时间
加锁防止ipc接口并发调用导致crash Signed-off-by: 张有康 <zhangyoukang2@h-partners.com> 4 个月前
enforce check at enty Signed-off-by: 张有康 <zhangyoukang2@h-partners.com> 2 个月前
Description:声明sa依赖的最低hdi版本 IssueNo:https://gitcode.com/openharmony/web_webview/issues/5730 Feature or Bugfix:Bugfix Binary Source:No Signed-off-by: wyk99 <wangyuekai1@huawei.com> 7 个月前
feat: 添加编译选项控制 app_fwk_update_service 组件编译 添加 webview_app_fwk_update_enable 编译开关,允许在编译时选择是否包含 app_fwk_update_service 组件及其相关测试。 修改内容: - config.gni: 添加 webview_app_fwk_update_enable 编译开关 - sa/app_fwk_update/BUILD.gn: 添加条件编译控制组件编译 - ohos_nweb/BUILD.gn: 添加条件编译控制核心库依赖 - test/unittest/app_fwk_update_client_test/BUILD.gn: 添加条件编译控制单元测试 - test/fuzztest/verifypackageinstall_fuzzer/BUILD.gn: 添加条件编译控制模糊测试 使用方法: - 启用(默认): ./build.sh --product-name rk3568 --build-target webview - 禁用: ./build.sh --product-name rk3568 --build-target webview --gn-args="webview_app_fwk_update_enable=false" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: LGH W <wulonghui2@huawei.com> 2 个月前
添加WebNativeMessage Signed-off-by: libing23232323 <libing23@huawei.com> 8 个月前
https://gitcode.com/openharmony/web_webview/issues/5979 docs: 添加 ArkWeb 项目完整文档体系 本次提交为 ArkWeb 项目添加了完整的文档体系,涵盖架构设计、开发工作流、API 接口、配置管理、测试等方面。 ## 新增文档 ### 项目主文档 - AGENT.md (英文版) - 项目主指南,便于 AI 工具理解 - AGENT_ZH.md (中文版) - 完整的中文项目指南 - CLAUDE.md - AI 辅助开发指南 - HOW_TO_ADD_BUILD_FEATURE.md - 编译特性开关添加指南 ### 核心模块文档 - ohos_nweb/README.md - 核心引擎层详细文档 - ohos_adapter/README.md - 系统适配层文档 (40+ 适配器) - ohos_interface/include/README.md - 胶水层接口文档 (双向解耦设计) - ohos_wrapper/README.md - 封装层文档 - arkweb_utils/README.md - 工具库文档 - ohos_nweb/README.md - 核心引擎层详细文档 - ohos_adapter/README.md - 系统适配层文档 (40+ 适配器) - ohos_interface/include/README.md - 胶水层接口文档 (双向解耦设计) - ohos_wrapper/README.md - 封装层文档 - arkweb_utils/README.md - 工具库文档 ### 配置管理文档 - ohos_nweb/HOW_TO_ADD_PARAM_CONFIG.md - PARAM 参数配置指南 (推荐方式) - ohos_nweb/HOW_TO_ADD_XML_CONFIG.md - XML 配置指南 ### 接口层文档 - interfaces/kits/napi/README.md - NAPI (ArkTS/JavaScript) 接口文档 - interfaces/kits/nativecommon/README.md - nativecommon 通用组件文档 - interfaces/kits/ani/README.md - ANI (高性能 ArkTS) 接口文档 - interfaces/kits/cj/README.md - CJ FFI (Rust/Python) 接口文档 - interfaces/native/README.md - Native (C++ NDK) 接口文档 ### 系统服务文档 - sa/app_fwk_update/README.md - 应用框架更新服务文档 - sa/web_native_messaging/README.md - Web 消息服务文档 ### 测试文档 - test/README.md - 测试代码文档 (单元测试 + 模糊测试) ## 文档特点 1. **全面性** - 覆盖所有核心模块、接口层、配置管理 2. **实用性** - 包含大量代码示例和实际使用场景 3. **结构清晰** - 分层架构说明,6 个常见开发场景 4. **双语支持** - 提供中英文版本,便于不同开发者使用 5. **AI 友好** - 英文版本便于 AI 工具理解和处理 ## 核心内容 ### 架构设计 - 8 层分层架构 (应用层 → 接口层 → 核心引擎 → 胶水层 → ArkWebCore → 胶水层 → 适配层 → 系统服务) - 胶水层双向解耦创新设计 (ohos_nweb: 53+ 接口, ohos_adapter: 66+ 接口) - 适配器模式 (40+ 适配器) ### 开发工作流 (6 大场景) 1. 添加新的 Public API (应用层接口) 2. 添加胶水层 API (ohos_adapter 方向) 3. 添加配置项 (PARAM 参数 + XML 配置) 4. 添加 nativecommon 通用组件 5. 添加测试用例 (单元测试 + 模糊测试) ### 配置管理 - PARAM 参数 (运行时配置,推荐) - XML 配置 (编译时配置) - 条件编译开关 (16 个功能开关) Signed-off-by: handyohos <zhangxiaotian@huawei.com> 3 个月前
添加WebNativeMessage Signed-off-by: libing23232323 <libing23@huawei.com> 8 个月前
添加WebNativeMessage Signed-off-by: libing23232323 <libing23@huawei.com> 8 个月前
README.md

AppFwkUpdateService

概述

AppFwkUpdateService 是 OpenHarmony 系统中 ArkWeb WebView 组件的应用框架更新系统服务(System Ability)。该服务负责监听和管理 ArkWebCore HAP 包的安装、更新和卸载事件,并在检测到变化时通知相关组件(如 AppSpawn 进程)进行相应的处理。

SA ID: 8350 (SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID) 进程名: app_fwk_update_service 库文件: libapp_fwk_update_service.z.so

核心职责

  1. 监听 ArkWebCore 包变化 - 通过公共事件监听 HAP 包的安装、更新、卸载
  2. 验证包安装 - 验证新的 ArkWebCore 包是否正确安装
  3. 通知框架更新 - 在 BMS (Bundle Manager Service) 启动后通知框架
  4. 与 AppSpawn 通信 - 通过 AppSpawn 客户端发送消息,触发 Web 库的加载/卸载
  5. 按需启动 - 支持按需启动(On-Demand),节省系统资源

目录结构

sa/app_fwk_update/
├── include/
│   ├── app_fwk_update_service.h           # 服务主类头文件
│   ├── app_fwk_update_client.h            # 客户端接口头文件
│   └── app_fwk_update_load_callback.h     # SA 加载回调头文件
├── src/
│   ├── app_fwk_update_service.cpp         # 服务实现
│   ├── app_fwk_update_client.cpp          # 客户端实现
│   └── app_fwk_update_load_callback.cpp   # SA 加载回调实现
├── IAppFwkUpdateService.idl               # IDL 接口定义
├── BUILD.gn                               # 构建配置
├── 8350.json                              # SA 配置文件(SA Profile)
├── app_fwk_update_service.cfg             # 服务启动配置
├── libapp_fwk_update_service.map          # 符号可见性配置
└── README.md                              # 本文档

工作原理

系统架构

┌─────────────────────────────────────────────────────────────┐
│                    Common Event Service                     │
│               (usual.event.PACKAGE_CHANGED)                  │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│              AppFwkUpdateService (SA 8350)                   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  PackageChangedReceiver (订阅公共事件)                 │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  VerifyPackageInstall() (验证包安装)                   │   │
│  │  NotifyFWKAfterBmsStart() (通知框架)                  │   │
│  │  NotifyArkWebInstallSuccess() (通知安装成功)          │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────┬───────────────────────────────────────┘
                      │ AppSpawn Client
                      ▼
┌─────────────────────────────────────────────────────────────┐
│                   AppSpawn Service                          │
│  - MSG_LOAD_WEBLIB_IN_APPSPAWN    (加载 Web 库)             │
│  - MSG_UNLOAD_WEBLIB_IN_APPSPAWN  (卸载 Web 库)            │
│  - MSG_UPDATE_MOUNT_POINTS        (更新挂载点)              │
└─────────────────────────────────────────────────────────────┘

核心工作流程

1. 服务启动(按需启动)

服务采用按需启动模式,只有在接收到相关公共事件时才会启动:

触发事件(定义在 8350.json):

  • usual.event.PACKAGE_CHANGED - 包变化事件
  • usual.event.PACKAGE_ADDED - 包添加事件

启动流程

1. Common Event Service 接收到 PACKAGE_CHANGED/ADDED 事件
2. SAMGR (System Ability Manager) 检查事件中的 bundleName
3. 如果 bundleName 为 "com.ohos.nweb" 或 "com.ohos.arkwebcore"
4. 启动 app_fwk_update_service 进程
5. 调用 AppFwkUpdateService::OnStart() -> Init()
6. 服务发布到 SAMGR
7. 订阅 COMMON_EVENT_SERVICE
8. 延迟 60 秒后卸载任务(如果空闲)

2. 包变化监听

PackageChangedReceiver 订阅并处理包变化事件:

void PackageChangedReceiver::OnReceiveEvent(const CommonEventData& data) {
    std::string action = data.GetWant().GetAction();
    std::string bundleName = data.GetWant().GetBundle();

    // 只处理 ArkWeb 相关的包
    if (action == COMMON_EVENT_PACKAGE_CHANGED &&
        (bundleName == "com.ohros.nweb" || bundleName == "com.ohos.arkwebcore")) {
        // 从 BundleManager 获取 HAP 路径
        // 触发 OnPackageChangedEvent(bundleName, hapPath)
    }
}

3. 验证包安装流程

当检测到 ArkWebCore 包变化时,执行 VerifyPackageInstall()

VerifyPackageInstall(bundleName, hapPath, success)
    │
    ├─ 1. 检查调用者 UID(必须为 FOUNDATION_UID: 5523)
    │
    ├─ 2. 发送 MSG_UNLOAD_WEBLIB_IN_APPSPAWN 到 AppSpawn
    │      └─ 通知 AppSpawn 卸载旧的 Web 库
    │
    ├─ 3. 检查 HAP 路径是否变化
    │      └─ 如果路径未变,直接返回成功
    │
    ├─ 4. 设置新的安装路径
    │      └─ SetParameter("persist.arkwebcore.install_path", hapPath)
    │
    ├─ 5. 设置包名
    │      └─ SetParameter("persist.arkwebcore.package_name", bundleName)
    │
    └─ 6. 发送 MSG_UPDATE_MOUNT_POINTS 到 AppSpawn
           └─ 通知 AppSpawn 更新挂载点

关键系统参数

  • persist.arkwebcore.install_path - ArkWebCore 安装路径
  • persist.arkwebcore.package_name - ArkWebCore 包名
  • web.engine.install.completed - Web 引擎安装完成标志

4. 通知框架更新

NotifyFWKAfterBmsStart() 在 BMS 启动后被调用:

NotifyFWKAfterBmsStart()
    │
    ├─ 1. 读取 persist.arkwebcore.package_name
    │
    ├─ 2. 发送 MSG_LOAD_WEBLIB_IN_APPSPAWN 到 AppSpawn
    │      └─ 通知 AppSpawn 加载 Web 库
    │
    └─ 3. 设置 web.engine.install.completed = "true"
           └─ 通知其他组件 Web 引擎已就绪

5. AppSpawn 消息类型

通过 SendAppSpawnMessage() 发送三种消息:

消息类型 说明
MSG_LOAD_WEBLIB_IN_APPSPAWN 20 加载 Web 库到 AppSpawn
MSG_UNLOAD_WEBLIB_IN_APPSPAWN 21 从 AppSpawn 卸载 Web 库
MSG_UPDATE_MOUNT_POINTS 22 更新挂载点

IDL 接口定义

IAppFwkUpdateService.idl

interface OHOS.NWeb.IAppFwkUpdateService {
    // 验证包安装(同步调用)
    void VerifyPackageInstall(
        [in] String bundleName,   // 包名
        [in] String hapPath,      // HAP 文件路径
        [out] int success         // 0=成功, -1=失败
    );

    // BMS 启动后通知框架(单向调用)
    [oneway] void NotifyFWKAfterBmsStart();

    // 通知 ArkWeb 安装成功
    void NotifyArkWebInstallSuccess();
}

接口实现

所有接口都在 AppFwkUpdateService 中实现:

class AppFwkUpdateService : public SystemAbility,
                            public AppFwkUpdateServiceStub {
public:
    ErrCode VerifyPackageInstall(
        const std::string& bundleName,
        const std::string& hapPath,
        int32_t& success) override;

    ErrCode NotifyFWKAfterBmsStart() override;

    ErrCode NotifyArkWebInstallSuccess() override;

    // ...
};

客户端使用

AppFwkUpdateClient

客户端通过单例模式访问服务:

#include "app_fwk_update_client.h"

using namespace OHOS::NWeb;

// 获取客户端实例
AppFwkUpdateClient& client = AppFwkUpdateClient::GetInstance();

// 验证包安装
int result = client.VerifyPackageInstall(
    "com.ohos.nweb",
    "/data/storage/el1/bundle/arkwebcore/entry.hap"
);

// 通知框架 BMS 已启动
int ret = client.NotifyFWKAfterBmsStart();

// 通知 ArkWeb 安装成功
client.NotifyArkWebInstallSuccess();

客户端工作原理

  1. SA 加载

    • 调用 LoadFwkService() 请求 SAMGR 加载 SA 8350
    • 超时时间:4 秒
    • 使用 AppFwkUpdateLoadCallback 处理加载结果
  2. Proxy 获取

    • 通过 iface_cast<IAppFwkUpdateService> 获取服务代理
    • 支持服务死亡监听(Death Recipient)
  3. 重试机制

    • 连接失败时自动重试
    • 加载超时后返回错误

服务配置

SA Profile (8350.json)

{
    "process": "app_fwk_update_service",
    "systemability": [{
        "name": 8350,                                    // SA ID
        "libpath": "libapp_fwk_update_service.z.so",
        "run-on-create": false,                         // 不在创建时运行
        "auto-restart": true,                           // 自动重启
        "distributed": false,                           // 非分布式
        "dump-level": 1,
        "start-on-demand": {                            // 按需启动配置
            "commonevent": [
                { "name": "usual.event.PACKAGE_CHANGED" },
                { "name": "usual.event.PACKAGE_ADDED" }
            ]
        }
    }]
}

服务启动配置 (app_fwk_update_service.cfg)

{
    "services": [{
        "name": "app_fwk_update_service",
        "path": ["/system/bin/sa_main",
                 "/system/profile/app_fwk_update_service.json"],
        "ondemand": true,                               // 按需启动
        "uid": "app_fwk_update",
        "gid": ["app_fwk_update"],
        "permission": [
            "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
            "ohos.permission.GET_BUNDLE_INFO"
        ],
        "start-mode": "condition",                      // 条件启动模式
        "secon": "u:r:app_fwk_update_service:s0"        // SELinux 上下文
    }]
}

关键常量

Bundle 名称集合

const std::set<std::string> ARK_WEB_DEFAULT_BUNDLE_NAME_SET = {
    "com.ohros.nweb",          // 旧包名
    "com.ohos.arkwebcore"      // 新包名
};

UID

const int FOUNDATION_UID = 5523;  // Foundation 进程的 UID

系统参数

const std::string PERSIST_ARKWEBCORE_PACKAGE_NAME = "persist.arkwebcore.package_name";
const std::string WEB_ENGINE_INSTALL_COMPLETED = "web.engine.install.completed";
const std::string PERSIST_ARKWEBCORE_INSTALL_PATH = "persist.arkwebcore.install_path";

重试和超时

const int RETRY_COUNT = 2;               // AppSpawn 消息重试次数
const int LOAD_SA_TIMEOUT_MS = 4000;     // SA 加载超时(4秒)
const int32_t TASK_DELAY_TIME = 60000;   // 延迟卸载任务时间(60秒)

依赖关系

外部依赖(BUILD.gn)

external_deps = [
    "ability_base:want",                    # Want 数据结构
    "ability_base:zuri",                    # URI 处理
    "ability_runtime:ability_manager",      # Ability 管理
    "ability_runtime:napi_common",          # NAPI 公共部分
    "appspawn:appspawn_client",             # AppSpawn 客户端
    "bundle_framework:appexecfwk_base",     # Bundle 框架基础
    "bundle_framework:appexecfwk_core",     # Bundle 框架核心
    "c_utils:utils",                        # 工具库
    "common_event_service:cesfwk_core",     # 公共事件服务核心
    "common_event_service:cesfwk_innerkits",# 公共事件内部 kit
    "eventhandler:libeventhandler",         # 事件处理器
    "hilog:libhilog",                       # 日志系统
    "hitrace:hitrace_meter",                # 链路追踪
    "init:libbeget_proxy",                  # Init 代理
    "init:libbegetutil",                    # Init 工具
    "ipc:ipc_core",                         # IPC 核心
    "safwk:system_ability_fwk",             # System Ability 框架
    "samgr:samgr_proxy",                    # SAMGR 代理
]

内部依赖

include_dirs = [
    "include",                               # 本服务头文件
    "${target_gen_dir}/../../ohos_nweb/include",
    "../../ohos_nweb/include",              # Nweb 头文件
    "${target_gen_dir}",                     # IDL 生成目录
]

权限要求

  • ohos.permission.GET_BUNDLE_INFO_PRIVILEGED - 获取 Bundle 信息特权
  • ohos.permission.GET_BUNDLE_INFO - 获取 Bundle 信息

使用场景

场景 1: ArkWebCore OTA 更新

1. 系统通过 OTA 更新新的 ArkWebCore.hap
2. BMS (Bundle Manager Service) 安装新的 HAP 包
3. Common Event Service 发送 PACKAGE_CHANGED 事件
4. AppFwkUpdateService 按需启动
5. PackageChangedReceiver 接收事件
6. 调用 VerifyPackageInstall()
7. 通知 AppSpawn 卸载旧的 Web 库
8. 设置新的安装路径和包名
9. 通知 AppSpawn 更新挂载点
10. 设置 web.engine.install.completed = true
11. 其他组件检测到参数变化,重新加载 Web 库

场景 2: 系统启动后 BMS 初始化完成

1. BMS 启动并完成初始化
2. 调用 NotifyFWKAfterBmsStart()
3. 读取 persist.arkwebcore.package_name
4. 通知 AppSpawn 加载 Web 库
5. 设置 web.engine.install.completed = true
6. WebView 组件可以正常使用

场景 3: ArkWebCore 安装成功通知

1. ArkWebCore 安装成功
2. 调用 NotifyArkWebInstallSuccess()
3. 检查预加载模式和启动完成状态
4. 如果需要预加载且启动已完成,设置安装完成标志
5. 触发后续的预加载流程

日志与调试

日志标签

HILOG_TAG="app_fwk_update_service"

关键日志点

  1. 服务启动

    AppFwkUpdateService reasonName: commonevent
    AppFwkUpdateService bundleName: com.ohros.nweb
    Service init success.
    
  2. 包变化事件

    packagechangeReceiver OnReceiveEvent, ret = PACKAGE_CHANGED.
    PackagechangeReceiver hapPath is /data/storage/.../entry.hap.
    
  3. AppSpawn 通信

    Send appspawn message start,uid = 1037.
    Send appspawn message success.
    
  4. 参数设置

    SetWebInstallPath res = 1.
    SetWebCorePackageName res = 1.
    

调试建议

  1. 查看服务状态

    # 检查服务是否运行
    ps -A | grep app_fwk_update_service
    
    # 查看 SA 状态
    hidumper -s 8350
    
  2. 查看系统参数

    # 查看包名
    param get persist.arkwebcore.package_name
    
    # 查看安装路径
    param get persist.arkwebcore.install_path
    
    # 查看安装完成标志
    param get web.engine.install.completed
    
  3. 手动触发服务

    # 发送公共事件(需要 root 权限)
    # 模拟包安装事件
    
  4. 查看日志

    hilog -T app_fwk_update_service
    

安全性

UID 校验

VerifyPackageInstall() 会检查调用者的 UID:

if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
    return ERR_INVALID_VALUE;
}

只有 Foundation 进程(UID 5523)才能调用此接口,防止恶意应用篡改 Web 引擎。

权限要求

服务需要以下权限才能正常工作:

  • GET_BUNDLE_INFO_PRIVILEGED - 获取包信息特权
  • GET_BUNDLE_INFO - 获取包信息

SELinux 策略

服务运行在专门的 SELinux 域:

secon: u:r:app_fwk_update_service:s0

性能优化

按需启动

服务采用按需启动模式,节省系统资源:

  • 不在系统启动时运行
  • 只在接收到相关公共事件时启动
  • 空闲 60 秒后自动卸载

延迟卸载

void PostDelayUnloadTask() {
    // 延迟 60 秒后卸载服务
    // 如果期间有新的请求,取消卸载任务
}

重试机制

AppSpawn 消息发送失败时自动重试(最多 2 次):

do {
    ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
} while (++retryCount < RETRY_COUNT && ret != 0);

故障处理

服务启动失败

症状:服务无法启动或注册失败

排查

  1. 检查 8350.json 配置是否正确
  2. 检查 app_fwk_update_service.cfg 配置
  3. 查看日志:hilog -T app_fwk_update_service
  4. 检查权限是否正确授予

AppSpawn 通信失败

症状SendAppSpawnMessage 返回错误

排查

  1. 检查 AppSpawn 服务是否运行:ps -A | grep appspawn
  2. 检查消息类型是否正确
  3. 查看系统日志确认错误码
  4. 检查包名是否为有效的 ArkWeb 包

包变化事件未触发

症状:更新 HAP 后服务无响应

排查

  1. 确认公共事件是否发送:使用 dump broadcaster
  2. 检查 bundleName 是否匹配:必须是 com.ohros.nwebcom.ohos.arkwebcore
  3. 查看服务是否按需启动失败
  4. 检查 Common Event Service 是否正常

参数未设置成功

症状SetParameter 返回错误

排查

  1. 检查参数名是否正确
  2. 检查是否有设置参数的权限
  3. 查看系统参数服务状态:param get
  4. 确认参数值是否合法

常见问题

Q1: 为什么要使用按需启动?

A: ArkWebCore 更新不频繁,按需启动可以:

  • 节省系统内存和 CPU 资源
  • 减少系统启动时间
  • 只在需要时才运行服务

Q2: 为什么需要与 AppSpawn 通信?

A: AppSpawn 负责应用进程的孵化,需要:

  • 在 AppSpawn 进程中预加载 Web 库
  • 更新 Web 库的挂载点
  • 确保新启动的应用使用最新的 Web 引擎

Q3: VerifyPackageInstall 为什么只允许 Foundation 调用?

A: 这是安全考虑,防止恶意应用:

  • 伪造包更新事件
  • 强制卸载 Web 库导致系统异常
  • 篡改 Web 引擎路径

Q4: 服务为什么会在 60 秒后卸载?

A: 这是资源优化策略:

  • 包更新事件是瞬时的
  • 更新完成后服务不再需要
  • 延迟卸载避免频繁启动/停止

Q5: 如何手动触发服务加载 Web 库?

A: 有两种方式:

  1. 通过客户端调用:AppFwkUpdateClient::GetInstance().NotifyFWKAfterBmsStart()
  2. 设置系统参数:param set web.engine.install.completed true

维护建议

代码规范

  1. 保持 IDL 接口稳定,避免频繁变更
  2. 新增接口需要向后兼容
  3. 使用 WVLOG_I/WVLOG_E 记录关键操作

测试要点

  1. 单元测试:test/unittest/app_fwk_update_client_test
  2. 服务启动/停止测试
  3. 包更新场景测试
  4. AppSpawn 通信测试
  5. 并发调用测试

版本演进

  1. 新增功能要考虑按需启动的影响
  2. 避免长时间阻塞操作
  3. 新增公共事件订阅需要更新 8350.json

相关文档

许可证

Apache License 2.0