# huaweicloud-cloudPhoneAccess-engine **Repository Path**: HuaweiCloudDeveloper/huaweicloud-cloud-phone-access-engine ## Basic Information - **Project Name**: huaweicloud-cloudPhoneAccess-engine - **Description**: 作为端云协同的云侧接入引擎,用于在云手机内处理端侧的接入、触控指令等各类事件,并通过云手机内置的媒体引擎采集云手机画面和声音然后传输给端侧。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 4 - **Created**: 2024-12-24 - **Last Updated**: 2025-07-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### [华为云手机开源项目仓主入口](https://gitee.com/HuaweiCloudDeveloper/huaweicloud-cloud-phone) ## CloudAppEngine ### 1. 方案简介 CloudAppEngine(CAE)为华为云手机端云协同方案云侧组件,致力于高效、便捷的接入并使用华为云手机,涵盖信令交互、接入鉴权、音视频流传输、解码渲染、触控采集等模块,使得客户构建云游戏、个人云手机等业务场景变的简单。客户在云手机内部署 CloudAppEngine,真机侧集成安卓或 H5 的 SDK,RemoteServer 实现相关 RestApi 接口,进一步结合业务场景丰富相关模块,实现完整接入方案。 ### 2. 组件交互架构图 #### 2.1 直连版 ![](res/直连版架构图.png) 该方案适用于客户无自己的后台管理系统,客户端直接与华为云OpenAPI和云侧CAE交互的场景。 1. SDK调CPH[查询云手机列表](https://support.huaweicloud.com/api-cph/cph_api_0503.html)接口获取云手机信息,再请求[获取连接信息](https://support.huaweicloud.com/api-cph/cph_api_0564.html)接口获取云手机的连接信息。 2. SDK向CAE发起连接请求,CAE使用证书进行验签,验签通过开始出流。 **注1:** 在此场景下,鉴权认证服务默认使用华为云提供的非对称秘钥对进行签名、验签。客户端在调用[获取连接信息](https://support.huaweicloud.com/api-cph/cph_api_0564.html)接口时,拿到的信息包含使用私钥签名后的签名信息。向CAE发起连接请求后,CAE会使用下载到本地的证书进行验签。如果是首次接入,CAE会先访问 https\://cph-common-{region_id}.obs.{region_id}.myhuaweicloud.com/open-source/cae/server.crt 地址下载证书,其中{region_id}为当前云手机所在region,如“cn-southwest-2”。 **注2:** 客户可以使用自己的非对称秘钥对进行签名验签。需要在云侧配置 **obtain_verification_public_key_url** 字段,值为证书地址(详见5.1),并在客户端侧使用私钥进行签名替换从接口拿到的签名信息。 #### 2.2 管理版 ![](res/管理版架构图.png) 该方案适用于客户有自己的后台server,客户端与客户的后台和云侧CAE交互的场景。 1. 后台server调华为云OpenAPI,同步云手机列表、状态等信息,执行重启、重置等操作。 2. 客户端调后台server接口,获取云手机实例信息及连接信息。 3. 客户端向CAE发起连接请求以及发送控制信令、触控指令等。 4. CAE使用证书进行验签,验签通过后向端侧发送音视频流。 5. CAE上报心跳、接入事件等。 ### 3. 工程构建 #### 3.1 目录介绍 ``` ├── app │   └── src │   └── main │   └── cpp │      ├── cae_3rd <依赖三方类代码> │      ├── cae_agent <主控逻辑> │      ├── cae_common <通用辅助> │      ├── cae_CPHMediaEngine <华为云手机音视频 SDK Mock 文件> │      ├── cae_CPHMediaEngineDemo <华为云手机音视频 SDK Demo> │      ├── cae_dataHandler <音视频数据发送、客户端信令数据处理> │      ├── cae_dataPipe <音视频等数据管道队列> │      ├── cae_service │      ├── cae_socket | ├── hwsecure <华为安全函数库> │      └── libs <依赖的三方 lib 库和对应头文件,需自行下载编译> │      ├── cJSON <用于 http 请求体构造、响应解析> │      │   ├── include │      │   └── lib │      ├── curl <用于 http/https 请求> │      │   ├── include │      │   └── lib │      ├── ffmpeg <用于读取本地文件作为虚拟摄像头输入数据> │      │   ├── include │      │   └── lib │      ├── mtrans <用于 UDP 传输> │      │   ├── include │      │   └── lib │      └── openssl <用于加解密、https、tls 安全通信> │      | ├── include │      | │   └── openssl │      | └── lib └── gradle ``` #### 3.2 编译构建 1. build -> Refresh Linked C++ Projects 2. build -> Rebuild Project ```shell ## 项目构建产物路径 app/.cxx/cmake/release/arm64-v8a/CloudAppEngine ``` #### 3.3 使用发行版 ```shell ## 可以直接下载本项目构建好的产物,下载后解压 https://gitee.com/HuaweiCloudDeveloper/huaweicloud-cloudPhoneAccess-engine/releases ``` ### 4. 部署流程 #### 4.1 证书说明 客户端与CAE通信使用TLS协议,运行时需要加载证书,测试环境采用 CAE 临时生成的证书。生产环境需购买权威证书,替换 /data/cloudAppEngine 目录下的 CAE_server.key和CAE_server.crt文件,也可以在代码中自定义证书存放路径,重新编译 CloudAppEngine。 #### 4.2 打包 CAE ```shell ## 创建目录,将编译好的 CloudAppEngine 文件,拷贝到如下目录 mkdir -p /data/cloudAppEngine/ ## 打包文件,不要压缩 tar -cvf CAE.tar data/* ``` #### 4.3 部署启动 ```shell ## 调用如下接口将 CAE.tar 推送到云手机 https://support.huaweicloud.com/api-cph/cph_api_0529.html ## 打开端云引擎开关(默认打开) 将云手机属性 ro.com.cph.cloud_app_engine 设置为"是",并点击确定(立即生效) ``` ### 5. 开发指导 #### 5.1 配置组件交互图中 RemoteServer (鉴权认证服务、调度服务) 对应的 url 地址 CloudAppEngine 可以读取 /data/cloudAppEngine 目录下的 **可选** 配置文件 CaeConfig.ini,如果配置了程序启动时会读取配置文件的配置项。 支持的配置项如下: ```shell #obtain_verification_public_key_url=https://xx.xx.com #sign_check_url=https://xx.xx.com #event_notify_url=https://xx.xx.com #heartbeat_url=https://xx.xx.com #pool_scheduling_elb_ip=xx.xx.xx.xx #pool_scheduling_elb_port=123 #mtrans_enable=0 #exclusive_mode=0 #ticket_expiration_time=1800000 #enable_ws=0 ``` - obtain_verification_public_key_url 客户使用自己的秘钥对验签时需要配置的证书地址 (直连版鉴权认证服务) - sign_check_url 字段配置的是鉴权认证接口的 url 地址 (管理版鉴权认证服务) - event_notify_url 字段配置的是接入和退出上报接口的 url 地址 - heartbeat_url 字段配置的是心跳上报接口的 url 地址 - pool_scheduling_elb_ip 字段配置的是编码池 elb 对应的 ip - pool_scheduling_elb_port 字段配置的是编码池 elb 对应的 port - mtrans_enable 是否启用UDP传输,0为不启用,1为启用。默认为1。 - exclusive_mode 是否开启独占模式,0为不开启,即为抢占模式(其他用户可以抢占使用同一台云手机),1为开启独占模式(一名用户在使用云手机时其他用户无法接入)。默认为0. - ticket_expiration_time 连接信息的签名过期时间,单位为毫秒。默认为60000。 - enable_ws 是否启用http,0为不启用,1为启用。默认为0。 #### 5.2 接口描述 CloudAppEngine在用户接入和退出时会上报事件,运行时会上报心跳。RemoteServer实现事件和心跳上报接口,用于实现相关调度逻辑。 ##### 5.2.1 事件上报 ###### 请求参数 | 参数 | 是否必选 | 参数类型 | 描述 | | ---------- | -------- | -------- | --------------------- | | event_type | 是 | String | 事件类型,枚举值:app | | event | 是 | Object | 事件信息 | | 参数 | 是否必选 | 参数类型 | 描述 | | ---------- | -------- | -------- | -------------------- | | phone_id | 是 | String | 手机标识ID,32位 | | status | 是 | Integer | 0:进入 1:退出 | | session_id | 是 | String | 会话ID | | time | 是 | String | 时间,格式为UTC 时间 | ###### 请求样例 ```json { "event_type": "app", "event": { "phone_id": "12345678901234567890123456789012", "status": 0, "session_id": "aa5b1cbafcc64c9f8063fb807fb8214b", "time": "2019-11-14T19:38:49z" } } ``` ###### 响应参数 | 参数 | 参数类型 | 描述 | | ---------- | -------- | ----------------- | | request_id | String | 请求的唯一标识 ID | ###### 响应样例 状态码:200 ```json { "request_id": "6837531fd3f54550927b930180a706bf" } ``` 状态码:非200 ``` 上报事件为进入,响应状态码非200,后端RemoteServer认为连接非法,CloudAppEngine主动断开 ``` ##### 5.2.2 心跳上报 ###### 请求参数 | 参数 | 是否必选 | 参数类型 | 描述 | | ---------- | -------- | -------- | --------------------------- | | event_type | 是 | String | 事件类型,枚举值:heartbeat | | event | 是 | Object | 事件信息 | | 参数 | 是否必选 | 参数类型 | 描述 | | ---------- | -------- | -------- | -------------------- | | phone_id | 是 | String | 手机标识ID,32位 | | session_id | 是 | String | 会话ID | | time | 是 | String | 时间,格式为UTC 时间 | ###### 请求样例 ```json { "event_type": "heartbeat", "event": { "phone_id": "12345678901234567890123456789012", "session_id": "aa5b1cbafcc64c9f8063fb807fb8214b", "time": "2019-11-14T19:38:49z" } } ``` ###### 响应参数 | 参数 | 参数类型 | 描述 | | ---------- | -------- | ----------------- | | request_id | String | 请求的唯一标识 ID | ###### 响应样例 状态码:200 ```json { "request_id": "6837531fd3f54550927b930180a706bf" } ``` 状态码:非200 ``` 心跳正常上报,响应状态码非200,后端RemoteServer认为连接非法,CloudAppEngine主动断开 ``` #### 5.3 模拟虚拟设备数据注入 CAE 支持注入模拟的摄像头和麦克风数据,摄像头支持 H264/YUV/Jpeg 格式文件注入,麦克风支持PCM格式文件注入。 ```shell ## CaeDefine.h 文件中的如下配置字段为是否打开模拟数据注入的开关,1代表打开,0代表关闭。 ENABLE_INJECT_LOCAL_CAMERA_STREAM (1) ENABLE_INJECT_LOCAL_MICROPHONE_STREAM (1) ## 虚拟设备的模拟数据文件在手机的存储路径如下,具体路径可在 CaeVirtualDeviceConfig.cpp 中修改。 ## 按照需要注入的设备及格式推送对应文件到相应目录即可,不需推送所有格式文件。 CAMERA_STREAM_H264_FILE_PATH = "/data/cloudAppEngine/camera.h264"; CAMERA_STREAM_YUV_FILE_PATH = "/data/cloudAppEngine/camera.yuv"; CAMERA_STREAM_JPEG_FILE_PATH = "/data/cloudAppEngine/camera.jpg"; MICROPHONE_STREAM_PCM_FILE_PATH = "/data/cloudAppEngine/microphone.pcm"; ## 同时需要在 CaeVirtualDeviceConfig.cpp 中指定注入文件的格式,如下所示 LOCAL_CAMERA_STREAM_INJECT_FILE_TYPE = VMI_H264; LOCAL_MICROPHONE_STREAM_INJECT_FILE_TYPE = VMI_PCM; ``` ### 6. license Apache License 2.0。