【小年答谢,新春送礼】免费抽取1000元京东卡+更多新春好礼~查看详情>>>

目录:
前言
背景知识
编译用户程序框架子系统
基于AbilityKit开发的Ability
总结

前言
上一篇,我们体验了一下鸿蒙上的界面的开发流程,这一篇我们继续深入一点点,尝试打通从用户态UI到内核态HDF之间的联系。其中涉及到的调用关系比较复杂,建议在“用鸿蒙开发AI应用(五)HDF 驱动补光灯”的基础上阅读本文,HDF的相关细节这里就不在赘述了。

背景知识
用户程序框架子系统包含两个大的模块:Ability子系统和包管理子系统。

1. Ability子系统

1.1 Ability
Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability

Page类型的Ability:带有界面,为用户提供人机交互的能力。
Service类型的Ability:不带界面,为用户提供后台任务机制。
1.2 AbilitySlice
AbilitySlice是单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。

1.3 生命周期
生命周期是Ability被调度到启动、激活、隐藏和退出等各个状态的的统称。

Ability生命周期各状态解析:

UNINITIALIZED:未初始状态,为临时状态,Ability被创建后会由UNINITIALIZED状态进入INITIAL状态;
INITIAL:初始化状态,也表示停止状态,表示当前Ability未运行,调用Start后进入INACTIVE,同时回调开发者的OnStart生命周期回调;
INACTIVE:未激活状态,表示当前窗口已显示但是无焦点状态,由于Window暂未支持焦点的概念,当前状态与ACTIVE一致。
ACTIVE:前台激活状态,表示当前窗口已显示,并获取焦点,Ability在退到后台之前先由ACTIVE状态进入INACTIVE状态;
BACKGROUND: 后台状态,表示当前Ability退到后台,Ability在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。
1.4 AbilityLoader
AbilityLoader负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。

1.5 AbilityManager
AbilityManager负责AbilityKit和Ability管理服务进行IPC的通信。

1.6 EventHandler
EventHandler是AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。

1.7 Ability运行管理服务
Ability运行管理服务是用于协调各Ability运行关系、及生命周期进行调度的系统服务。

其中,服务启动模块负责Ability管理服务的启动、注册等。

服务接口管理模块负责Ability管理服务对外能力的管理。

进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。

生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。

连接管理模块是Ability管理服务对Service类型Ability连接管理的模块。

1.8 AppSpawn
AppSpawn是负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。

2. 包管理子系统
包管理子系统,是OpenHarmony为开发者提供的安装包管理框架。

BundleKit:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化监听接口。
包扫描器:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。
包安装子模块:安装,卸载,升级一个包;包安装服务一个单独进程的用于创建删除安装目录,具有较高的权限。
包管理子模块:管理安装包相关的信息,存储持久化包信息。
包安全管理子模块:签名检查、权限授予、权限管理。

HDF驱动LED(可选)
之前在内核中已经注册过一个led_driver驱动,并以led_service服务发布,这一节稍微重构一下代码,功能上没有变化,我们快速过一遍,熟悉HDF的可以自行跳过。

1. 业务代码
先新建头文件vendor\huawei\hdf\led\include\led_ctrl.h。

#ifndef _LED_CTRL_H
#define _LED_CTRL_H #include "hdf_device_desc.h"
#include "hdf_log.h"
#include "device_resource_if.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "gpio_if.h"
#include "osal_irq.h"
#include "osal_time.h" #ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */ extern int32_t CtlLED(int mode); #ifdef __cplusplus
}
#endif /* __cplusplus */ #endif /* _LED_CTRL_H */

再新建源文件 vendor\huawei\hdf\led\led_ctrl.c

#include "led_ctrl.h"

#define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签

int32_t CtlLED(int mode)
{
int32_t ret;
uint16_t valRead;
/* LED的GPIO管脚号 */
// uint16_t gpio = 5 * 8 + 1; // 红外补光灯
uint16_t gpio = 2 * 8 + 3; // 绿色指示灯
// uint16_t gpio = 3 * 8 + 4; // 红色指示灯 /* 将GPIO管脚配置为输出 */
ret = GpioSetDir(gpio, GPIO_DIR_OUT);
if (ret != 0)
{
HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
return ret;
} if (mode == -1)
{
// 翻转输出口
(void)GpioRead(gpio, &valRead);
ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
}
else
{
ret = GpioWrite(gpio, mode);
} if (ret != 0)
{
HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
return ret;
}
return ret;
}

先完成对绿色指示灯的控制逻辑。

2. 驱动实现
在 huawei/hdf 目录下新建一个文件夹 led, 然后在其中新建一个源文件 led.c。

#include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件
#include "hdf_log.h" // HDF 框架提供的日志接口头文件
#include "led_ctrl.h" // #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
#define LED_WRITE_READ 1 // 读写操作码1 // Dispatch是用来处理用户态发下来的消息
int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t result = HDF_FAILURE;
HDF_LOGE("Led driver dispatch");
if (client == NULL || client->device == NULL)
{
HDF_LOGE("Led driver device is NULL");
return HDF_ERR_INVALID_OBJECT;
} switch (cmdCode)
{
case LED_WRITE_READ:
const char *recv = HdfSbufReadString(data);
if (recv != NULL)
{
HDF_LOGI("recv: %s", recv);
result = CtlLED(-1);
// result = CtlLED(GPIO_VAL_HIGH);
if (!HdfSbufWriteInt32(reply, result))
{
HDF_LOGE("replay is fail");
}
return HdfDeviceSendEvent(client->device, cmdCode, data);
}
break; default:
break;
}
return result;
} //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver bind failed!");
return HDF_ERR_INVALID_OBJECT;
}
static struct IDeviceIoService ledDriver = {
.Dispatch = LedDriverDispatch,
}; deviceObject->service = (struct IDeviceIoService *)(&ledDriver);
HDF_LOGD("Led driver bind success");
return HDF_SUCCESS;
} // 驱动自身业务初始的接口
int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver Init failed!");
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGD("Led driver Init success");
return HDF_SUCCESS;
} // 驱动资源释放的接口
void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver release failed!");
return;
} HDF_LOGD("Led driver release success");
return;
} // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
struct HdfDriverEntry g_ledDriverEntry = {
.moduleVersion = 1,
.moduleName = "led_driver",
.Bind = HdfLedDriverBind,
.Init = HdfLedDriverInit,
.Release = HdfLedDriverRelease,
}; // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_ledDriverEntry);

3. 驱动编译
在 huawei/hdf/led 目录下新建编译文件 Makefile。

include $(LITEOSTOPDIR)/../../drivers/hdf/lite/lite.mk

MODULE_NAME := hdf_led_driver
LOCAL_SRCS += led_ctrl.c \
led.c \ LOCAL_INCLUDE := ./include
LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror
include $(HDF_DRIVER)

4. 编译结果链接到内核镜像
修改 huawei/hdf/hdf_vendor.mk 文件,添加以下代码

LITEOS_BASELIB += -lhdf_led_driver  #链接生成的静态库
LIB_SUBDIRS += $(VENDOR_HDF_DRIVERS_ROOT)/led #驱动代码Makefile的目录

5. 驱动配置
修改 vendor/hisi/hi35xx/hi3516dv300/config/device_info/device_info.hcs配置文件,添加驱动的设备描述。

platform :: host {
hostName = "platform_host"; // host名称,host节点是用来存放某一类驱动的容器
priority = 50; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 device_led :: device { // led设备节点
device0 :: deviceNode { // led驱动的DeviceNode节点
policy = 2; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍
priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序
preload = 0; // 驱动按需加载字段
permission = 0666; // 驱动创建设备节点权限
moduleName = "led_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
serviceName = "led_service"; // 驱动对外发布服务的名称,必须唯一
deviceMatchAttr = "led_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
}
}

编译用户程序框架子系统
1. 添加配置文件
在 build/lite/platform/hi3516dv300_liteos_a/platform.json中的subsystems字段下面添加appexecfwk和aafwk。

{
"subsystem": "aafwk",
"components": [
{
"component": "ability",
"optional": "true",
"dirs": [
"foundation/aafwk"
],
"targets": [
"//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
"//foundation/aafwk/frameworks/ability_lite:aafwk_abilityMain_lite",
"//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
"//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite"
],
"features": [
{"enable_ohos_appexecfwk_feature_ability": "true"}
],
"deps": {
"components": [
"hilog_a",
"bundle_mgr",
"system_ability_manager",
"distributed_schedule",
"graphic",
"utils",
"ipc"
],
"third_party": [
"cjson",
"bounds_checking_function"
]
}
}
]
}, {
"subsystem": "appexecfwk",
"components": [
{
"component": "bundle_mgr",
"optional": "true",
"dirs": [
"foundation/appexecfwk"
],
"targets": [
"//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
"//foundation/appexecfwk/frameworks/bundle_lite:appexecfwk_kits_lite"
],
"features": [],
"deps": {
"components": [
"iam",
"app_verify",
"hilog_a",
"system_ability_manager",
"global_resource_manager",
"graphic",
"utils"
],
"third_party": [
"cjson",
"zlib"
]
}
}
]
},

2. 添加编译文件
新建build\lite\config\subsystem\aafwk\BUILD.gn文件,

import("//build/lite/config/subsystem/lite_subsystem.gni")

lite_subsystem("aafwk") {
subsystem_components = [
"//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
"//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
"//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite",
]
}

新建/build/lite/config/subsystem/appexecfwk/BUILD.gn文件,

import("//build/lite/config/subsystem/lite_subsystem.gni")

lite_subsystem("appexecfwk") {
subsystem_components = [
"//foundation/appexecfwk/kits/appkit_lite:appexecfwk_kit_lite",
"//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
]
}

3. 运行管理服务
用户程序框架有两个系统服务ability管理服务(abilityms)和(bundlems),两系统服务运行于foundation进程中。

abilityms和bundlems注册到sa_manager中,sa_manager运行于foundation进程中,sa_manager为abilityms和bundlems创建线程运行环境。

在foundation/distributedschedule/services/safwk_lite/BUILD.gn中添加对abilityms和bundlems

deps = [
"...",
]
if (ohos_kernel_type == "liteos_a") {
deps += [
"...",
"//foundation/aafwk/services/abilitymgr_lite:abilityms",
"//foundation/appexecfwk/services/bundlemgr_lite:bundlems",
"...",
]
}

基于AbilityKit开发的Ability
1. 主页面实现
新建源文件applications\sample\camera\myLedApp\src\main_ability.cpp

#include "main_ability.h"

namespace OHOS {
REGISTER_AA(MainAbility) void MainAbility::OnStart(const Want &want)
{
printf("MainAbility::OnStart\n");
SetMainRoute("MainAbilitySlice"); Ability::OnStart(want);
}

查看更多章节>>>

作者:bluishfish

想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com

【小年答谢,新春送礼】免费抽取1000元京东卡+更多新春好礼~查看详情>>>

用鸿蒙开发AI应用(七)触摸屏控制LED的更多相关文章

  1. 用鸿蒙开发AI应用(八)JS框架访问内核层

    目录:前言JS应用开发框架原理内置模块实现ace模块开发界面程序 前言上回说到,用C++来写UI界面的开发效率不如JS+HTML来的高,但设备开发又免不了要通过内核态来操作硬件,这里我们就要先打通从J ...

  2. #2020征文-开发板# 用鸿蒙开发AI应用(一)硬件篇

    目录: 前言 开发板简介 产品特色及功能 产品参数 各个主板功能简介 Hi3516DV300 芯片手册 前言鸿蒙2.0的系统刚开源出来,华为志在打造1+8+N万物互联的全场景智慧生活,不仅是国产操作系 ...

  3. #2020征文-开发板# 用鸿蒙开发AI应用(二)系统篇

    目录: 前言 安装虚拟机 安装 Ubuntu 设置共享文件夹 前言上回说到,我们在一块 HarmonyOS HiSpark AI Camera 开发板,并将其硬件做了一下解读和组装.要在其上编译鸿蒙系 ...

  4. #2020征文-开发板# 用鸿蒙开发AI应用(五)HDF 驱动补光灯

    目录: 前言 硬件准备 HDF 驱动开发 总结 前言上一篇,我们在鸿蒙上运行了第一个程序,这一篇我们来编写一个驱动开启摄像头的红外补光灯,顺便熟悉一下鸿蒙上的 HDF 驱动开发. 硬件准备先查一下原理 ...

  5. #2020征文-开发板# 用鸿蒙开发AI应用(三)软件篇

    目录: 前言 HarmonyOS 简介 DevEco Device Tool(windows下) 获取源码(切换到ubuntu) 烧录程序(切换回windows) 前言上一篇,我们在 Win10 上用 ...

  6. 鸿蒙开发板外设控制 之 实现按键“按下事件”和“释放事件”的通用框架(V0.0.1)

    在帖子 <鸿蒙开发板外设控制>直播图文版(2020.10.28) 中我们提到过:"开发板上的按键也可以看作一种 GPIO 外设." 因此,要捕捉按键的状态(按下或释放) ...

  7. [ZigBee] 13、ZigBee基础阶段性回顾与加深理解——用定时器1产生PWM来控制LED亮度(七色灯)

    引言:PWM对于很多软件工程师可能又熟悉又陌生,以PWM调节LED亮度为例,其本质是在每个周期都偷工减料一些,整体表现出LED欠压亮度不同的效果.像大家看到的七色彩灯其原理也类似,只是用3路PWM分别 ...

  8. 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...

  9. Knockout应用开发指南 第七章:Mapping插件

    原文:Knockout应用开发指南 第七章:Mapping插件 Mapping插件 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些 ...

随机推荐

  1. Sublime Text 3 习惯插件 转

    原帖:https://www.cnblogs.com/hykun/p/sublimeText3.html Emmet插件 Emmet插件可以说是使用Sublime Text进行前端开发必不可少的插件 ...

  2. Mysql中的语句优化

    1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...

  3. Python实验6--网络编程

    题目1 1.编写程序实现基于多线程的TCP客户机/服务器程序. (1)创建服务器端套接字Socket,监听客户端的连接请求: (2)创建客户端套接字Socket,向服务器端发起连接: 服务器端套接字 ...

  4. spring cloud gateway 日志打印

    从api请求中获取访问的具体信息,是一个很常见的功能,这几天在研究springcloud,使用到了其中的gateway,刚好将研究的过程结果都记录下来 0. Version <parent> ...

  5. Java并发/多线程-CAS原理分析

    目录 什么是CAS 并发安全问题 举一个典型的例子i++ 如何解决? 底层原理 CAS需要注意的问题 使用限制 ABA 问题 概念 解决方案 高竞争下的开销问题 什么是CAS CAS 即 compar ...

  6. (四)React Ant Design Pro + .Net5 WebApi:PostgreSQL数据库环境搭建

    一.简介 PostgreSQL,开源数据库(没听过小伙伴自己反思一下自行百度) PgAdmin,官方提供的数据库管理工具. 二.环境 1. 官网下载包,安装数据库 tar xjvf /app/pack ...

  7. eCATT使用前的配置

    如果想在SAP中使用eCATT,必须做一下相关的配置才行,下面简单介绍这几步:1.SM30,输入表T000,然后点击维护,或者是进入事物SCC4,进入对应的clint属性编辑视图下,将CATT and ...

  8. new String("ab")到底创建了几个对象说明

    new String("ab")到底创建了几个对象? 之前一直被这个问题困扰,网上一些描述的都不是很清楚,自己看了一些资料可算搞清楚了,那就在博客上记录一下吧! String st ...

  9. CentOS对接GlusterFS

    存储节点部署示例环境,仅供参考 主机名 IP 系统 gfs01 10.10.10.13 CentOS 7.4.1708 gfs02 10.10.10.14 CentOS 7.4.1708 一.Glus ...

  10. owners

    community/owners.md at master · kubernetes/community https://github.com/kubernetes/community/blob/ma ...