鸿蒙Harmony南向开发子系统适配

654 篇文章 4 订阅
648 篇文章 6 订阅

  OpenHarmony子系统适配一般包含两部分:

  • config.json中增加对应子系统和部件,这样编译系统会将该部件纳入编译目标中。
  • 针对该部件的HAL层接口进行硬件适配,或者可选的软件功能适配。
分布式软总线子系统适配
wifi_lite部件适配

首先,在config.json文件中,增加communication子系统的wifi_lite部件,如下:

  {
      "subsystem": "communication",
      "components": [
        {
          "component": "wifi_lite",
          "optional": "true"
        }
      ]
    },

wifi_lite部件在//build/lite/components/communication.json文件中,描述如下:

    {
      "component": "wifi_lite",
……
      "targets": [
        "//foundation/communication/wifi_lite:wifi"		 --- wifi_lite的编译目标
      ],
……
    },

//foundation/communication/wifi_lite/BUILD.gn文件中,描述需要适配的接口头文件路径,如下:

config("include") {
  include_dirs = [ "interfaces/wifiservice" ]	 --- 因为wifi_lite只提供头文件,不提供wifi的具体实现,所以wifi模块暴露出适配的目录路径提供给硬件厂商来适配,厂商提供wifi协议栈源码实现。
}

group("wifi") {
  public_configs = [ ":include" ]
}

因为在本案例中,wifi属于SoC提供的功能,所以适配源码放在SoC//device/soc/bestechnic/hals/communication/wifi_lite/wifiservice目录下,包含wifi_device.cwifi_hotspot.c分别适配wifi_device.hwifi_hotspot.h。如下:

……
WifiErrorCode Scan(void)	 --- wifi_device.c中扫描wifi热点的函数,对wifi_device.h中Scan函数的适配实现
{
    WifiErrorCode ret = ERROR_WIFI_BUSY;


    if (IsWifiActive() != WIFI_STA_ACTIVE)
        return ERROR_WIFI_IFACE_INVALID;

    if (g_HalHmosWifiInfo.scan_state == SCAN_REQUEST ||
        g_HalHmosWifiInfo.scan_state == SCAN_TRIGGER)
        return ERROR_WIFI_BUSY;

    HalHmosWifiLock();
    ret = ((HalHmosSendEvent(HMOS_ON_WIFI_SCAN_STATE_CHANGED, NULL) == 0) ? WIFI_SUCCESS : ERROR_WIFI_BUSY);
    HalHmosWifiUnLock();

    return ret;
}
……
int GetSignalLevel(int rssi, int band)	 --- wifi_hotspot.c中获取wifi信号热点函数,对wifi_hotspot.h中GetSignalLevel函数的适配实现。
{
    if (band == HOTSPOT_BAND_TYPE_2G) {
        if (rssi >= RSSI_LEVEL_4_2_G)
            return RSSI_LEVEL_4;
        if (rssi >= RSSI_LEVEL_3_2_G)
            return RSSI_LEVEL_3;
        if (rssi >= RSSI_LEVEL_2_2_G)
            return RSSI_LEVEL_2;
        if (rssi >= RSSI_LEVEL_1_2_G)
            return RSSI_LEVEL_1;
    }

    if (band == HOTSPOT_BAND_TYPE_5G) {
        if (rssi >= RSSI_LEVEL_4_5_G)
            return RSSI_LEVEL_4;
        if (rssi >= RSSI_LEVEL_3_5_G)
            return RSSI_LEVEL_3;
        if (rssi >= RSSI_LEVEL_2_5_G)
            return RSSI_LEVEL_2;
        if (rssi >= RSSI_LEVEL_1_5_G)
            return RSSI_LEVEL_1;
    }
    return ERROR_WIFI_INVALID_ARGS;
}
LWIP部件适配

LiteOS-M kernel目录下默认配置了lwip,因而具有编译功能,可以在kernel组件中指定lwip编译的目录。如下:

   {
      "subsystem": "kernel",
      "components": [
        {
          "component": "liteos_m",
          "features": [
            "ohos_kernel_liteos_m_lwip_path = \"//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1\""		 --- 指定在芯片厂商目录中进行适配
          ]
        }
      ]
    },

//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/BUILD.gn文件中,描述了lwip的编译,如下:

import("//kernel/liteos_m/liteos.gni")
import("$LITEOSTHIRDPARTY/lwip/lwip.gni")
import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni")

module_switch = defined(LOSCFG_NET_LWIP_SACK)
module_name = "lwip"
kernel_module(module_name) {
  sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES -
            [ "$LWIPDIR/api/sockets.c" ] + [ "porting/src/ethernetif.c" ]		 --- 增加ethernetif.c文件,用以适配ethernet网卡的初始化适配
  defines = [ "LITEOS_LWIP=1" ]
  defines += [ "CHECKSUM_BY_HARDWARE=1" ]
}

config("public") {
  defines = [ "_BSD_SOURCE=1" ]
  include_dirs =
      [ "porting/include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS
}

//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/include/lwip/lwipopts.h文件中,说明原有lwip配置选项保持不变,软总线会依赖这些配置选项,并且新增硬件适配的配置项,如下:

#ifndef _PORTING_LWIPOPTS_H_
#define _PORTING_LWIPOPTS_H_

#include_next "lwip/lwipopts.h"				 --- 保持原来的配置项不变

#define LWIP_NETIF_STATUS_CALLBACK      1
#define LWIP_CHECKSUM_ON_COPY           0
#define CHECKSUM_GEN_UDP                0	 --- 新增硬件适配选项

#endif /* _PORTING_LWIPOPTS_H_ */

//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/src/ethernetif.c文件中,说明对ethernet网卡初始化的适配,如下:

err_t
ethernetif_init(struct netif *netif)
{
……
#ifdef CHECKSUM_BY_HARDWARE
    eth_hw_checksum_init();
#endif
……
    netif->linkoutput = low_level_output;

    netif->drv_send = liteos_low_level_output;
    netif->hwaddr_len = NETIF_MAX_HWADDR_LEN;
    low_level_init(netif);
    driverif_init(netif);
    return ERR_OK;
……
}
dsoftbus部件适配

config.json中增加dsoftbus部件配置如下:

{
  "component": "dsoftbus",
  "features": [
    "softbus_adapter_config = \"//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config\""
  ]
},

dsoftbus部件在//foundation/communication/dsoftbus/dsoftbus.gni文件中提供了softbus_adapter_config配置选项可供移植过程进行配置,该配置设定了软总线移植适配的路径。

在本案例中,softbus_adapter_config配置为//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config路径,该路径下的内容为:

.
├── feature_config					--- 软总线功能特性配置,例如是否开启自发现功能等
│   └── mini
│       └── config.gni
└── spec_config						--- 软总线规格特性配置,例如设置软总线日志级别设置
    ├── softbus_config_adapter.c
    ├── softbus_config_adapter.h
    └── softbus_config_type.h

config.gni文件中规定了以下配置项:

配置项描述
dsoftbus_feature_disc_ble是否开启BLE发现功能
dsoftbus_feature_disc_coap是否开启COAP发现功能
dsoftbus_feature_conn_tcp是否开启TCP连接功能
dsoftbus_feature_conn_br是否开启BR连接功能
dsoftbus_feature_conn_ble是否开启BLE连接功能
dsoftbus_feature_conn_p2p是否开启P2P连接功能
dsoftbus_feature_trans_udp是否开启UDP传输功能
dsoftbus_feature_trans_udp_stream是否开启UDP传输流功能
dsoftbus_feature_trans_udp_file是否开启UDP传输文件功能
dsoftbus_feature_ip_auth是否开启认证传输通道功能
dsoftbus_feature_auth_account是否开启基于账号认证功能
dsoftbus_feature_qos是否开启QoS功能

softbus_config_adapter.c文件中规定了以下配置项:

配置项描述
SOFTBUS_INT_MAX_BYTES_LENGTHSendBytes发送最大Bytes长度
SOFTBUS_INT_MAX_MESSAGE_LENGTHSendMessage发送最大消息的长度
SOFTBUS_INT_CONN_BR_MAX_DATA_LENGTH蓝牙最大接收数据量
SOFTBUS_INT_CONN_RFCOM_SEND_MAX_LEN蓝牙最大接收数据量
SOFTBUS_INT_ADAPTER_LOG_LEVEL日志级别设置
SOFTBUS_STR_STORAGE_DIRECTORY存储目录设置

因为软总线配置了后,不会默认启动,所以需要在通过启动框架调用InitSoftBusServer函数,如下:

static void DSoftBus(void)
{
    osThreadAttr_t attr;
    attr.name = "dsoftbus task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 65536;
    attr.priority = 24;

    extern void InitSoftBusServer(void);
    if (osThreadNew((osThreadFunc_t) InitSoftBusServer, NULL, &attr) == NULL) {
        printf("Failed to create WifiSTATask!\n");
    }
}

APP_FEATURE_INIT(DSoftBus);
RPC部件适配

config.json中增加rpc部件配置如下:

{
  "component": "rpc"
},

同样地,rpc部件需要通过启动框架调用StartDBinderService函数,由于该函数正常运行依赖主机已经获取IP地址,因此在LWIP协议栈注册IP地址变化事件的回调函数中调用该函数,如下:

static void RpcServerWifiDHCPSucCB(struct netif *netif, netif_nsc_reason_t reason,
                                   const netif_ext_callback_args_t *args)
{
    (void) args;
    if (netif == NULL) {
        printf("%s %d, error: input netif is NULL!\n", __FUNCTION__, __LINE__);
        return;
    }
    if (reason == LWIP_NSC_IPSTATUS_CHANGE) {
        if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr)) {
            printf("%s %d, start rpc server!\n", __FUNCTION__, __LINE__);
            StartDBinderService();
        }
    }
}

static void WifiDHCPRpcServerCB(void)
{
    NETIF_DECLARE_EXT_CALLBACK(WifiReadyRpcServerCallback);
    netif_add_ext_callback(&WifiReadyRpcServerCallback, RpcServerWifiDHCPSucCB);
}

APP_FEATURE_INIT(WifiDHCPRpcServerCB);
启动恢复子系统适配

启动恢复子系统适配bootstrap_lite/syspara_lite两个部件。请在vendor/bestechnic_bak/display_demo/config.json中新增对应的配置选项。

{
  "subsystem": "startup",
  "components": [
	{
	  "component": "bootstrap_lite"		 --- bootstrap_lite 部件
	},
	{
	  "component": "syspara_lite",		 --- syspara_lite 部件
	  "features": [
		"enable_ohos_startup_syspara_lite_use_posix_file_api = true"
	  ]
	}
  ]
},

适配bootstrap_lite部件时,需要在连接脚本文件//device/soc/bestechnic/bes2600/liteos_m/sdk/bsp/out/best2600w_liteos/_best2001.lds中手动新增如下段:

       __zinitcall_bsp_start = .;
      KEEP (*(.zinitcall.bsp0.init))
      KEEP (*(.zinitcall.bsp1.init))
      KEEP (*(.zinitcall.bsp2.init))
      KEEP (*(.zinitcall.bsp3.init))
      KEEP (*(.zinitcall.bsp4.init))
      __zinitcall_bsp_end = .;
      __zinitcall_device_start = .;
      KEEP (*(.zinitcall.device0.init))
      KEEP (*(.zinitcall.device1.init))
      KEEP (*(.zinitcall.device2.init))
      KEEP (*(.zinitcall.device3.init))
      KEEP (*(.zinitcall.device4.init))
      __zinitcall_device_end = .;
      __zinitcall_core_start = .;
      KEEP (*(.zinitcall.core0.init))
      KEEP (*(.zinitcall.core1.init))
      KEEP (*(.zinitcall.core2.init))
      KEEP (*(.zinitcall.core3.init))
      KEEP (*(.zinitcall.core4.init))
      __zinitcall_core_end = .;
      __zinitcall_sys_service_start = .;
      KEEP (*(.zinitcall.sys.service0.init))
      KEEP (*(.zinitcall.sys.service1.init))
      KEEP (*(.zinitcall.sys.service2.init))
      KEEP (*(.zinitcall.sys.service3.init))
      KEEP (*(.zinitcall.sys.service4.init))
      __zinitcall_sys_service_end = .;
      __zinitcall_sys_feature_start = .;
      KEEP (*(.zinitcall.sys.feature0.init))
      KEEP (*(.zinitcall.sys.feature1.init))
      KEEP (*(.zinitcall.sys.feature2.init))
      KEEP (*(.zinitcall.sys.feature3.init))
      KEEP (*(.zinitcall.sys.feature4.init))
      __zinitcall_sys_feature_end = .;
      __zinitcall_run_start = .;
      KEEP (*(.zinitcall.run0.init))
      KEEP (*(.zinitcall.run1.init))
      KEEP (*(.zinitcall.run2.init))
      KEEP (*(.zinitcall.run3.init))
      KEEP (*(.zinitcall.run4.init))
      __zinitcall_run_end = .;
      __zinitcall_app_service_start = .;
      KEEP (*(.zinitcall.app.service0.init))
      KEEP (*(.zinitcall.app.service1.init))
      KEEP (*(.zinitcall.app.service2.init))
      KEEP (*(.zinitcall.app.service3.init))
      KEEP (*(.zinitcall.app.service4.init))
      __zinitcall_app_service_end = .;
      __zinitcall_app_feature_start = .;
      KEEP (*(.zinitcall.app.feature0.init))
      KEEP (*(.zinitcall.app.feature1.init))
      KEEP (*(.zinitcall.app.feature2.init))
      KEEP (*(.zinitcall.app.feature3.init))
      KEEP (*(.zinitcall.app.feature4.init))
      __zinitcall_app_feature_end = .;
      __zinitcall_test_start = .;
      KEEP (*(.zinitcall.test0.init))
      KEEP (*(.zinitcall.test1.init))
      KEEP (*(.zinitcall.test2.init))
      KEEP (*(.zinitcall.test3.init))
      KEEP (*(.zinitcall.test4.init))
      __zinitcall_test_end = .;
      __zinitcall_exit_start = .;
      KEEP (*(.zinitcall.exit0.init))
      KEEP (*(.zinitcall.exit1.init))
      KEEP (*(.zinitcall.exit2.init))
      KEEP (*(.zinitcall.exit3.init))
      KEEP (*(.zinitcall.exit4.init))
      __zinitcall_exit_end = .;

需要新增上述段是因为bootstrap_init提供的对外接口,见//utils/native/lite/include/ohos_init.h文件,采用的是灌段的形式,最终会保存到上述链接段中。主要的服务自动初始化宏如下表格所示:

接口名描述
SYS_SERVICE_INIT(func)标识核心系统服务的初始化启动入口
SYS_FEATURE_INIT(func)标识核心系统功能的初始化启动入口
APP_SERVICE_INIT(func)标识应用层服务的初始化启动入口
APP_FEATURE_INIT(func)标识应用层功能的初始化启动入口

 说明: 通过上面加载的组件编译出来的lib文件需要手动加入强制链接。

​ 如在 vendor/bestechnic/display_demo/config.json 中配置了bootstrap_lite 部件

    {
      "subsystem": "startup",
      "components": [
        {
          "component": "bootstrap_lite"
        },
        ...
      ]
    },

​ bootstrap_lite部件会编译//base/startup/bootstrap_lite/services/source/bootstrap_service.c,该文件中,通过SYS_SERVICE_INITInit函数符号灌段到__zinitcall_sys_service_start__zinitcall_sys_service_end中,由于Init函数是没有显式调用它,所以需要将它强制链接到最终的镜像。如下:

static void Init(void)
{
    static Bootstrap bootstrap;
    bootstrap.GetName = GetName;
    bootstrap.Initialize = Initialize;
    bootstrap.MessageHandle = MessageHandle;
    bootstrap.GetTaskConfig = GetTaskConfig;
    bootstrap.flag = FALSE;
    SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
}
SYS_SERVICE_INIT(Init);   --- 通过SYS启动即SYS_INIT启动就需要强制链接生成的lib

​ 在//base/startup/bootstrap_lite/services/source/BUILD.gn文件中,描述了在out/v200zr/display_demo/libs 生成 libbootstrap.a,如下:

static_library("bootstrap") {
  sources = [
    "bootstrap_service.c",
    "system_init.c",
  ]
  ....

​ 那么需要在 vendor/bestechnic/display_demo/config.json 配置强制链接库bootstrap,如下:

 "bin_list": [
    {
      "elf_name": "wifiiot",
      "bsp_target_name": "best2600w_liteos",
      "signature": "false",
      "burn_name": "rtos_main",
      "enable": "true",
      "force_link_libs": [
        "bootstrap",	 --- 强制链接libbootstrap.a
        ...
      ]
    },

适配syspara_lite部件时,系统参数会最终写到文件中进行持久化保存。在轻量系统中,文件操作相关接口有POSIX接口与HalFiles接口这两套实现。

因为对接内核的文件系统,采用POSIX相关的接口,所以features字段中需要增加enable_ohos_startup_syspara_lite_use_posix_file_api = true

如果对接HalFiles相关的接口实现的,则无须修改。

在适配GetSerial接口时,开发板不像产线生产过程那样,会写入一个具体的Serial Number,因而需要确定一个数据对开发板进行唯一标识。本案例采用WiFi Mac地址进行适配。

#define ETH_ALEN 6
#define MAC_BITS 4
#define MAC_HIGH_MASK 0xf0
#define MAC_LOW_MASK 0x0f
#define HEX_A 0xa
#define CHAR_NUM_OFFSET 0x30
#define CHAR_CAPITAL_OFFSET 0x37
#define STR_END_FLAG '\0'

typedef unsigned char               u8;

static char serialNumber[2*ETH_ALEN + 1];		 --- 最后一位留作'\0'结束符标识


static char Hex2Char(u8 hex)
{
    if (hex < HEX_A) {
        return hex + CHAR_NUM_OFFSET;			 --- 将数值0转为char的'0'
    } else {
        return hex + CHAR_CAPITAL_OFFSET;		 --- 将数值0xa转为char的'A'
    }
}

const char* HalGetSerial(void)
{
    char macAddr[ETH_ALEN];
    // as devboard has no production serial number, we just
    // use wifi mac address as device serial number.
    if (serialNumber[0] == STR_END_FLAG) {		 --- 只有第一次调用时,才去获取mac地址
        extern int bwifi_get_own_mac(u8 *addr);
        bwifi_get_own_mac(macAddr);				 --- 获取mac地址
        int j = 0;
        for (int i = 0; i < ETH_ALEN; i++) {
            u8 lowFour, highFour;
            highFour = (macAddr[i] & MAC_HIGH_MASK) >> MAC_BITS;
            serialNumber[j] = Hex2Char(highFour);
            j++;
            lowFour = macAddr[i] & MAC_LOW_MASK;
            serialNumber[j] = Hex2Char(lowFour);
            j++;
        }		 --- 将mac地址值转化为serial number
    }
    return serialNumber;
}
DFX子系统适配

进行DFX子系统适配需要添加hilog_lite部件,直接在config.json文件配置即可。

{
  "subsystem": "hiviewdfx",
  "components": [
	{
	  "component": "hilog_lite",
	  "optional": "true"
	}
  ]
},

配置完成之后,在//device/soc/bestechnic/bes2600/liteos_m/components/utils/src/hm_sys.c中注册日志输出实现函数。

boolean HilogProc_Impl(const HiLogContent *hilogContent, uint32 len)
{
    char tempOutStr[LOG_FMT_MAX_LEN] = {0};
    if (LogContentFmt(tempOutStr, sizeof(tempOutStr), hilogContent) > 0) {
        printf(tempOutStr);
    }
	return TRUE;   
}

HiviewRegisterHilogProc(HilogProc_Impl);
系统服务管理子系统适配

进行系统服务管理子系统适配需要添加samgr_lite部件,直接在config.json配置即可。

{
  "subsystem": "systemabilitymgr",
  "components": [
	{
	  "component": "samgr_lite",
	  "features": [
		"config_ohos_systemabilitymgr_samgr_lite_shared_task_size = 4096"
	  ]
	}
  ]
},

在轻量系统中,samgr_lite配置的共享任务栈大小默认为0x800。当函数调用栈较大时,会出现栈溢出的问题。在本次适配过程中,将其调整为0x1000

安全子系统适配

进行安全子系统适配需要添加huks/deviceauth_lite部件,直接在config.json配置即可。

  {
      "subsystem": "security",
      "components": [
        {
          "component": "huks",
          "features": [
            "huks_use_lite_storage = true",
            "huks_use_hardware_root_key = true",
            "huks_config_file = \"hks_config_lite.h\"",
            "huks_key_store_path = \"/data/\"",
            "ohos_security_huks_mbedtls_porting_path = \"//device/soc/bestechnic/hals/mbedtls\""
          ]
        },
        {
          "component": "deviceauth_lite",
          "features": [
            "deviceauth_storage_path = \"/data/\"",
            "deviceauth_hichain_thread_stack_size = 9472"
          ]
        }
      ]
    }

huks部件适配时,huks_key_store_path配置选项用于指定存放秘钥路径,ohos_security_huks_mbedtls_porting_path配置选项用于指定进行mbedtls适配的目录,用于芯片对mbedtls进行硬件随机数等适配。

deviceauth_lite部件适配时,deviceauth_storage_path配置选项用于指定存放设备认证信息的路径,deviceauth_hichain_thread_stack_size用于指定线程栈大小。

媒体子系统适配

进行媒体子系统适配需要添加histreamer部件,直接在config.json配置即可。

{
  "subsystem": "multimedia",
  "components": [
    {
      "component": "histreamer",
      "features": [
        "histreamer_enable_plugin_hdi_adapter = true",
        "histreamer_enable_plugin_minimp3_adapter = true",
        "histreamer_enable_plugin_ffmpeg_adapter = false",
        "config_ohos_histreamer_stack_size = 65536"
      ]
    }
  ]
},

histreamer部件配置项说明如下:

配置项说明
histreamer_enable_plugin_hdi_adapter是否使能histreamer对接到hdi接口
histreamer_enable_plugin_minimp3_adapter是否使能插件适配minimp3
histreamer_enable_plugin_ffmpeg_adapter是否使能插件适配FFmpeg
config_ohos_histreamer_stack_sizehistreamer栈大小设置
公共基础库子系统适配

进行公共基础库子系统适配需要添加kv_store/js_builtin/timer_task/kal_timer部件,直接在config.json配置即可。

{
  "subsystem": "utils",
  "components": [
	{
	  "component": "kv_store",
	  "features": [
		"enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true"
	  ]
	},
	{
	  "component": "js_builtin"
	},
	{
	  "component": "timer_task"
	},
	{
	  "component": "kal_timer",
	}
  ]
},

与适配syspara_lite部件类似,适配kv_store部件时,键值对会写到文件中。在轻量系统中,文件操作相关接口有POSIX接口与HalFiles接口这两套实现。因为对接内核的文件系统,采用POSIX相关的接口,所以features需要增加enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true。如果对接HalFiles相关的接口实现的,则无须修改。

图形子系统适配

进行图形子系统适配需要添加graphic_utils部件,直接在config.json配置即可。

  {
      "components": [
        {
          "component": "graphic_utils",
          "features": [
            "enable_ohos_graphic_utils_product_config = true"
          ]
        },
        {
          "component": "ui"
        }
      ]
    },

graphic配置文件见 //vendor/bestechnic/display_demo/graphic_config/product_graphic_lite_config.h

graphic适配见//device/soc/bestechnic/bes2600/liteos_m/components/ui, 主要功能如下:

  • display_device:实例化BaseGfxEngine
  • touch_input:实例化PointerInputDevice
  • UiMainTask:初始化字体引擎,执行渲染任务等。

图形子系统层次:

aafwk_lite + appexecfwk_lite    (AAFWK + APPEXECFWK)
      |
ace_engine_lite + jerryscript + i18n_lite + resmgr_lite + utils/native/lite/... (ACE,JS引擎及其依赖)
      |
arkui_ui_lite + graphic_utils      (图形框架)
      |
giflib + libjpeg + libpng + qrcodegen + freetype... (图形第三方库)

图形应用示例见文件//vendor/bestechnic/display_demo/tests/app.cpp,如下:

/* ui app entry */
void RunApp()
{
#ifdef UI_TEST
    AnimatorDemoStart(); 	 --- native ui demo
#elif defined(ABILITY_TEST)
    StartJSApp(); 			 --- js demo
#endif
}

void AppEntry(void)
{
    UiMain();
}

APP_FEATURE_INIT(AppEntry);
ACE开发框架子系统适配

进行ACE开发框架子系统适配需要添加ace_engine_lite部件,直接在config.json配置即可。

{
  "subsystem": "ace",
  "components": [
    {
      "component": "ace_engine_lite",
      "features": [
        "enable_ohos_ace_engine_lite_product_config = true"
      ]
    }
  ]
},

ace_engine_lite部件配置文件见 //vendor/bestechnic/display_demo/ace_lite_config/product_acelite_config.h

ace_lite的应用采用js语言进行开发,详细步骤如下:

  1. DevEco Studio编写js应用,参考轻量级智能穿戴开发
  2. 使用预览功能进行预览,并且得到js包:entry\.preview\intermediates\res\debug\lite\assets\js\default
  3. 将js包放到对应的文件系统目录下,文件系统路径为vendor/bestechnic/display_demo/fs/data/data/js,如下:
├── app.js
├── common
├── i18n
├── manifest.json
└── pages
  1. 最终编译生成系统镜像,烧录到单板后,系统会从app.js加载启动ace的应用。
元能力子系统适配

进行元能力子系统适配需要添加aafwk_lite部件,直接在config.json配置即可。

  {
      "subsystem": "aafwk",
      "components": [
        {
          "component": "aafwk_lite",
          "features": [
            "enable_ohos_appexecfwk_feature_ability = true",	 --- 支持FA特性,即包含图形能力
            "config_ohos_aafwk_ams_task_size = 4096"			 --- 配置aafwk栈的大小
          ]
        }
      ]
    },

aafwk_lite相关的应用样例见vendor/bestechnic/display_demo/tests/ability目录,包含launcherjs app这两类应用,应用的函数调用流程描述如下:

  1. launcher应用,通过InstallLauncher安装BundleName为 "com.example.launcher"native ui应用,在AbilityMgrSliteFeature启动后会调用AbilityMgrHandler::StartLauncher()启动launcher应用。

  2. StartJSApp应用,通过StartAbility启动任意Want,通过将want data传递JS_APP_PATHSetWantData(&want, JS_APP_PATH, strlen(JS_APP_PATH) + 1)

包管理子系统适配

进行包管理子系统适配需要添加appexecfwk_lite部件,直接在config.json配置即可。

  {
      "subsystem": "appexecfwk",
      "components": [
        {
          "component": "appexecfwk_lite"
        }
      ]
    },


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

鸿蒙HarmonyOS Next全套学习资料←点击领取!(安全链接,放心点击

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值