目录

运行数据应用处理数据

概述

本节介绍如何在机密空间内运行数据应用,并完成相应的数据处理任务。

机密空间是一个对外隔离的计算环境,专注于用户隐私数据的计算,仅支持通过机密空间接口加载、运行数据应用。

数据应用(Data application,简称DA)是运行于机密空间内部的独立程序,可使用外部应用提供的数据、机密空间内数据管理服务提供的用户数据,完成特定计算任务,再将最终计算结果发送回外部应用。数据应用以动态库(.so文件)形式通过机密空间API加载到空间中运行。

约束与限制

  1. 同一应用一天内最多调用20次runApp接口。

  2. 数据应用在单次运行期间最多发送总计4比特的数据,即长度为1的数组,并且此元素范围为[0, 15]。

  3. 数据应用单次运行时长不得超过5秒,超时的实例将被强制结束。

业务流程

为了方便开发者理解机密空间的运行完整流程,本节描述机密空间内部运行原理。

机密空间相关的系统服务进程有:机密空间管理服务、数据管理服务。

应用在机密空间中运行数据应用(以下简称DA)的业务流程如下:

  1. 应用调用runApp,异步发起运行DA请求:

    1. 应用连接系统中的机密空间管理服务,后者按需启动机密空间。
    2. 通过空间内服务拉起空间内部新进程,加载待启动的DA动态库文件。
    3. 调用DA的初始化函数。
    4. 完成DA启动后,应用与数据管理服务间建立socket,数据管理服务与DA间建立socket;应用与数据管理服务间的socket被包装成DataAppHandle对象。
  2. 应用调用onReceiveData,注册消息接收回调。

  3. 应用调用sendData,异步发送数据:

    1. 应用向数据管理服务发送报文,传递要发送的数据,数据管理服务读取报文,将要发送的数据转发给DA。
    2. DA接收到消息,进入消息处理逻辑。
    3. DA完成消息处理后,向应用发送数据。
    4. 数据管理服务对DA发送的数据进行校验,校验成功时,生成数据签名,发送回调用方应用。
    5. 调用方应用接收到数据,触发消息接收回调。
  4. 应用调用stop停止DA,由机密空间服务结束DA进程。

接口说明

接口及使用方法请参见API参考。

接口名 描述
runApp(appPath: string, argv: string[]): Promise<DataAppHandle> 以给定路径启动数据应用。
sendData(data: Uint8Array): Promise<void> 向数据应用发送数据。
onReceiveData(callback: Callback<Uint8Array>): void 注册从数据应用接收数据的回调函数。
offReceiveData(callback?: Callback<Uint8Array>): void 取消注册从数据应用接收数据的回调函数。
onReceiveDataError(callback: ErrorCallback<BusinessError<DataAppErrorInfo>>): void 注册处理接收数据时发生错误的回调函数。
offReceiveDataError(callback?: ErrorCallback<BusinessError<DataAppErrorInfo>>): void 取消注册处理接收数据时发生错误的回调函数。
stop(): void 结束数据应用。

开发步骤

  1. 导入机密空间模块。

    import { confidentialSpace } from '@kit.ConfidentialSpaceKit';
    // 导入示例代码所需的日志模块和文本转二进制能力
    import { buffer } from '@kit.ArkTS';
    import { hilog } from '@kit.PerformanceAnalysisKit';
  2. 调用runApp方法在机密空间中启动数据应用。

    const TAG = 'ConfidentialSpace';
    
    let handle: confidentialSpace.DataAppHandle;
    try {
      // 在机密空间中运行数据应用
      handle = await confidentialSpace.runApp(`/data/storage/el1/bundle/libs/arm64/libdemo_da.so`, []);
    } catch (e) {
      hilog.error(0x0000, TAG, `Failed to run app. code=${e.code} message=${e.message}`);
      // ...
    }
  3. 调用onReceiveData和onReceiveDataError方法注册接收到数据(或接收出错)时的回调。

    // 注册消息接收回调和错误回调
    handle.onReceiveData((data: Uint8Array) => {
      hilog.info(0x0000, TAG, `Received data, length=${data.length}`);
      handle.stop();
      handle.offReceiveData();
      handle.offReceiveDataError();
      // ...
    });
    handle.onReceiveDataError((e: BusinessError<confidentialSpace.DataAppErrorInfo>) => {
      hilog.error(0x0000, TAG, `Failed to receive data. code=${e.code} message=${e.message}`);
      if (e.code === 1028700014) { // 数据应用产生的错误
        hilog.error(0x0000, TAG, `Error is from DA; raw code=${e.data?.dataAppErrorCode}`);
      }
      handle.stop();
      handle.offReceiveData();
      handle.offReceiveDataError();
      // ...
    });
  4. 调用sendData发送数据到数据应用中。

    // 定义消息格式为 "ECHO:${msg}",并将其转换为字符数组
    let payload = new Uint8Array(buffer.from(`ECHO:${msg}`, 'utf-8').buffer);
    // 发送数据
    try {
      await handle.sendData(payload);
    } catch (e) {
      hilog.error(0x0000, TAG, `Failed to send data. code=${e.code} message=${e.message}`);
      handle.stop();
      // ...
    }