当前位置: 首页 > news >正文

消息通知之系统层事件发布相关流程

前言

Openharmony 3.1Release中存在消息通知的处理,消息通知包括系统层事件发布、消息订阅、消息投递与处理,为了开发者能够熟悉消息的处理流程,本篇文章主要介绍系统层事件发布的相关流程。

整体流程

代码流程

发布消息

{
eventAction)want.SetAction("usual.event.license.LIC_EXPIRED");
EventFwk::CommonEventPublishInfo publishInfo;CommonEventData commonData;commonData.SetWant(want);if (!CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {LICENSE_LOGI("failed to publish event[%{public}d]", eventAction);return false;}return true;}

 

CommonEventManager函数处理,调用PublishCommonEvent

{CommonEventPublishInfo publishInfo;return PublishCommonEventAsUser(data, publishInfo, nullptr, UNDEFINED_USER);
}

调用PublishCommonEventAsUser

    const CommonEventPublishInfo &publishInfo, const std::shared_ptr<CommonEventSubscriber> &subscriber,const int32_t &userId)
{EVENT_LOGI("enter");return DelayedSingleton<CommonEvent>::GetInstance()->PublishCommonEventAsUser(data, publishInfo, subscriber,userId);
}

调用CommonEvent的PublishCommonEventAsUser

    const std::shared_ptr<CommonEventSubscriber> &subscriber, const int32_t &userId)
{EVENT_LOGI("enter");sptr<IRemoteObject> commonEventListener = nullptr;if (!PublishParameterCheck(data, publishInfo, subscriber, commonEventListener)) {return false;}EVENT_LOGD("before PublishCommonEvent proxy valid state is %{public}d", isProxyValid_);return commonEventProxy_->PublishCommonEvent(data, publishInfo, commonEventListener, userId);
}

CommonEventProxy调用PublishCommonEvent向服务端发送CES_PUBLISH_COMMON_EVENT消息

    const sptr<IRemoteObject> &commonEventListener, const int32_t &userId)
{EVENT_LOGD("start");MessageParcel data;MessageParcel reply;…….bool ret = SendRequest(ICommonEvent::Message::CES_PUBLISH_COMMON_EVENT, data, reply);if (ret) {ret = reply.ReadBool();}EVENT_LOGD("end");return ret;
}

服务端接收CES_PUBLISH_COMMON_EVENT消息

{if (data.ReadInterfaceToken() != GetDescriptor()) {EVENT_LOGE("local descriptor is not equal to remote");return ERR_TRANSACTION_FAILED;}switch (code) {case static_cast<uint32_t>(ICommonEvent::Message::CES_PUBLISH_COMMON_EVENT): {std::unique_ptr<CommonEventData> event(data.ReadParcelable<CommonEventData>());std::unique_ptr<CommonEventPublishInfo> publishinfo(data.ReadParcelable<CommonEventPublishInfo>());sptr<IRemoteObject> commonEventListener = nullptr;bool hasLastSubscriber = data.ReadBool();if (hasLastSubscriber) {sptr<IRemoteObject> commonEventListener = data.ReadRemoteObject();}int32_t userId = data.ReadInt32();if (!event) {EVENT_LOGE("Failed to ReadParcelable<CommonEventData>");return ERR_INVALID_VALUE;}if (!publishinfo) {EVENT_LOGE("Failed to ReadParcelable<CommonEventPublishInfo>");return ERR_INVALID_VALUE;}bool ret = PublishCommonEvent(*event, *publishinfo, commonEventListener, userId);if (!reply.WriteBool(ret)) {EVENT_LOGE("Failed to write reply ");return ERR_INVALID_VALUE;}break;}……..default:EVENT_LOGW("unknown, code = %{public}u, flags= %{public}u", code, option.GetFlags());return IPCObjectStub::OnRemoteRequest(code, data, reply, option);}return NO_ERROR;
}

调用服务端PublishCommonEvent函数

    const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const int32_t &userId)
{EVENT_LOGI("enter");if (!IsReady()) {return false;}return PublishCommonEventDetailed(event, publishinfo, commonEventListener, IPCSkeleton::GetCallingPid(),IPCSkeleton::GetCallingUid(),userId);
}

PublishCommonEventDetailed绑定PublishCommonEvent,然后进行事件投递

    const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const pid_t &pid,const uid_t &uid, const int32_t &userId)
{EVENT_LOGI("enter");struct tm recordTime = {0};if (!GetSystemCurrentTime(&recordTime)) {EVENT_LOGE("Failed to GetSystemCurrentTime");return false;}std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(uid);if (DelayedSingleton<PublishManager>::GetInstance()->CheckIsFloodAttack(uid)) {EVENT_LOGE("Too many common events have been sent in a short period from %{public}s (pid = %{public}d, uid = ""%{public}d, userId = %{public}d)", bundleName.c_str(), pid, uid, userId);return false;}Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();std::function<void()> PublishCommonEventFunc = std::bind(&InnerCommonEventManager::PublishCommonEvent,innerCommonEventManager_, event, publishinfo, commonEventListener, recordTime, pid,uid, callerToken, userId, bundleName, this);return handler_->PostTask(PublishCommonEventFunc);
}

在事件投递中调用处理InnerCommonEventManager::PublishCommonEvent

    const sptr<IRemoteObject> &commonEventListener, const struct tm &recordTime, const pid_t &pid, const uid_t &uid,const Security::AccessToken::AccessTokenID &callerToken, const int32_t &userId, const std::string &bundleName,const sptr<IRemoteObject> &service)
{EVENT_LOGI("enter %{public}s(pid = %{public}d, uid = %{public}d), event = %{public}s to userId = %{public}d",bundleName.c_str(), pid, uid, data.GetWant().GetAction().c_str(), userId);if (data.GetWant().GetAction().empty()) {EVENT_LOGE("the commonEventdata action is null");return false;}if ((!publishInfo.IsOrdered()) && (commonEventListener != nullptr)) {EVENT_LOGE("When publishing unordered events, the subscriber object is not required.");return false;}std::string action = data.GetWant().GetAction();bool isSystemEvent = DelayedSingleton<CommonEventSupport>::GetInstance()->IsSystemEvent(action);…….if (!controlPtr_) {EVENT_LOGE("CommonEventControlManager ptr is nullptr");return false;}controlPtr_->PublishCommonEvent(eventRecord, commonEventListener);…….return true;
}

默认IsOrdered是false,参数不配置调用ProcessUnorderedEvent

    const CommonEventRecord &eventRecord, const sptr<IRemoteObject> &commonEventListener)
{EVENT_LOGI("enter");bool ret = false;if (!eventRecord.publishInfo->IsOrdered()) {ret = ProcessUnorderedEvent(eventRecord);} else {ret = ProcessOrderedEvent(eventRecord, commonEventListener);}return ret;
}

无序事件处理,投递事件在hander中调用NotifyUnorderedEvent

    const CommonEventRecord &eventRecord, const std::shared_ptr<EventSubscriberRecord> &subscriberRecord)
{…….std::function<void()> innerCallback =std::bind(&CommonEventControlManager::NotifyUnorderedEvent, this, eventRecordPtr);if (eventRecord.isSystemEvent) {ret = handler_->PostImmediateTask(innerCallback);} else {ret = handler_->PostTask(innerCallback);}return ret;
}

NotifyUnorderedEvent调用NotifyEvent

{……for (auto vec : eventRecord->receivers) {size_t index = eventRecord->nextReceiver++;eventRecord->curReceiver = vec->commonEventListener;if (vec->isFreeze) {eventRecord->deliveryState[index] = OrderedEventRecord::SKIPPED;DelayedSingleton<CommonEventSubscriberManager>::GetInstance()->InsertFrozenEvents(vec, *eventRecord);} else {……if (ret == OrderedEventRecord::DELIVERED) {eventRecord->state = OrderedEventRecord::RECEIVEING;commonEventListenerProxy->NotifyEvent(*(eventRecord->commonEventData), false, eventRecord->publishInfo->IsSticky());eventRecord->state = OrderedEventRecord::RECEIVED;}}}……
}

在EventReceiveProxy::NotifyEvent函数中发送消息CES_NOTIFY_COMMON_EVENT

{……int32_t result = remote->SendRequest(static_cast<uint32_t>(IEventReceive::Message::CES_NOTIFY_COMMON_EVENT), data, reply, option);if (result != OHOS::NO_ERROR) {EVENT_LOGE("Failed to SendRequest, error code: %{public}d", result);return;}EVENT_LOGD("end");
}

服务端接收消息调用服务端NotifyEvent函数

{if (data.ReadInterfaceToken() != GetDescriptor()) {EVENT_LOGE("local descriptor is not equal to remote");return ERR_TRANSACTION_FAILED;}switch (code) {case static_cast<uint32_t>(IEventReceive::Message::CES_NOTIFY_COMMON_EVENT): {std::unique_ptr<CommonEventData> eventData(data.ReadParcelable<CommonEventData>());bool ordered = data.ReadBool();bool sticky = data.ReadBool();if (eventData == nullptr) {EVENT_LOGE("callback stub receive common event data is nullptr");return ERR_INVALID_VALUE;}NotifyEvent(*eventData, ordered, sticky);break;}default:EVENT_LOGW("event receive stub receives unknown code, code = %{public}u", code);return IPCObjectStub::OnRemoteRequest(code, data, reply, option);}return NO_ERROR;
}

服务端NotifyEvent函数,调用OnReceiveEvent

{EVENT_LOGI("enter");std::lock_guard<std::mutex> lock(mutex_);if (!IsReady()) {EVENT_LOGE("not ready");return;}std::function<void()> onReceiveEventFunc =std::bind(&CommonEventListener::OnReceiveEvent, this, commonEventData, ordered, sticky);handler_->PostTask(onReceiveEventFunc);
}

从上面我们就梳理整个系统层事件发布流程,希望对大家有所帮助。

相关文章:

消息通知之系统层事件发布相关流程

前言 Openharmony 3.1Release中存在消息通知的处理&#xff0c;消息通知包括系统层事件发布、消息订阅、消息投递与处理&#xff0c;为了开发者能够熟悉消息的处理流程&#xff0c;本篇文章主要介绍系统层事件发布的相关流程。 整体流程 代码流程 发布消息 { eventAction)w…...

Elsevier Ocean Engineering Guide for Authors 解读

文章目录 ★Types of contributions★Submission checklistEthics in publishing★Declaration of competing interestDeclaration of generative AI in scientific writingSubmission declaration and verificationPreprint posting on SSRNUse of inclusive languageReportin…...

基于Fragstats的土地利用景观格局分析

土地利用以及景观格局是当前全球环境变化研究的重要组成部分及核心内容&#xff0c;其对区域的可持续发展以及区域土地管理有非常重要的意义。通过对土地利用时空变化规律进行分析可以更好的了解土地利用变化的过程和机制&#xff0c;并且通过调整人类社会经济活动&#xff0c;…...

ffmpeg-转码脚本02

ffmpeg-转码脚本详解 高级脚本 以下为主要部分 更高级优化要见git上 mkv转码电影脚本 ECHO OFF REM 以下参数不可乱填 SET FFMPEG%~DP0\ffmpeg.exe ::------------------------------------------------------------------------------ CALL:PRO_LOOPDIR ::CALL:PRO_LOOPDIR_SU…...

SharedPreferences

Android轻量级数据存储 import android.content.Context; import android.content.SharedPreferences;public class SharedPreferencesUtil {private SharedPreferences sharedPreferences;private SharedPreferences.Editor editor;public SharedPreferencesUtil(Context con…...

服务(第二十五篇)redis的优化和持久化

持久化的功能&#xff1a;Redis是内存数据库&#xff0c;数据都是存储在内存中&#xff0c;为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失&#xff0c;需要定期将Redis中的数据以某种形式&#xff08;数据或命令&#xff09;从内存保存到硬盘&#xff1b;当下…...

David Silver Lecture 7: Policy Gradient

1 Introduction 1.1 Policy-Based Reinforcement Learning 1.2 Value-based and policy based RL 基于值的强化学习 在基于值的 RL 中&#xff0c;目标是找到一个最优的值函数&#xff0c;通常是 Q 函数或 V 函数。这些函数为给定的状态或状态-动作对分配一个值&#xff0c;表…...

知识图谱学习笔记——(五)知识图谱推理

一、知识学习 声明&#xff1a;知识学习中本文主体按照浙江大学陈华钧教授的《知识图谱》公开课讲义进行介绍&#xff0c;并个别地方加入了自己的注释和思考&#xff0c;希望大家尊重陈华钧教授的知识产权&#xff0c;在使用时加上出处。感谢陈华钧教授。 &#xff08;一&…...

用vs2010编译和调试多个arx版本的arx项目

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、一级标题二级标题三级标题四级标题五级标题六级标题升级原先vs2008版本的项目文件到2010,或直接用vs2010新建一个arx项目; vs中查看项目属性:Project menu -> Properties,项目名上右…...

安全相关词汇

• DEW: Data Encryption Workshop • HSM: Hardware Security Module • KMS: Key Management System • KAM: Key Account Management • DHSM: Dedicated Hardware Security Module • KPS: Key Pair Service • CSMS: Cloud Secret Management Service • PCI-DSS: …...

最新入河排污口设置论证、水质影响预测与模拟、污水处理工艺分析及典型建设项目入河排污口方案报告书

随着水资源开发利用量不断增大&#xff0c;全国废污水排放量与日俱增&#xff0c;部分河段已远远超出水域纳污能力。近年来,部分沿岸入河排污口设置不合理&#xff0c;超标排污、未经同意私设排污口等问题逐步显现&#xff0c;已威胁到供水安全、水环境安全和水生态安全&#x…...

2023年认证杯二阶段C题数据合并python以及matlab多途径实现代码

对于每种心率下给出的数据&#xff0c;我们需要进行合并才能方便后续处理&#xff0c;这里为大家展示利用python以及matlab分别实现合并的代码 import pandas as pd import os# 创建一个空的DataFrame对象 merged_data pd.DataFrame()# 设置数据文件所在的文件夹路径 folder_…...

Win11校园网不弹出登录页面怎么回事?

Win11校园网不弹出登录页面怎么回事&#xff1f;最近有用户在使用校园网的时候遇到了一些问题&#xff0c;访问登录网站的时候&#xff0c;一直无法显示登录的界面。那么遇到这个情况如何去进行解决呢&#xff1f;一起来看看以下的解决方法分享吧。 解决方法如下&#xff1a; 方…...

S32K144低功耗休眠与唤醒实践总结

在做车载项目时&#xff0c;模块在常供电时需要维系随时可以被唤醒工作的状态&#xff0c;并且静态电流需要在3mA以内&#xff0c;当然在JTT1163标准中要求的是5mA以内。 目标明确了&#xff0c;在模块休眠时需要关闭一切不必要的资源消耗&#xff0c;只保留模块被唤醒的部分功…...

一文吃透 Vue 框架教程(上)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

堆排序与取topK java实现

1.堆排序思路 最近趁着有点时间&#xff0c;稍微复习了一下数据结构相关内容&#xff0c;温习了一下堆排序&#xff0c;做一下记录。 首先我们复习一下什么是堆&#xff1a; 堆是具有以下性质的完全二叉树&#xff1a;每个结点的值都大于或等于其左右孩子结点的值&#xff0c…...

https通信流程通俗理解

场景&#xff0c;假设A和B进行通信 CA: ( Certificate Authority &#xff09;就是颁发 HTTPS 证书的组织。 通信流程步骤&#xff1a; 1、A告诉B使用 RSA算法进行加密&#xff0c;B说好的。 2、A和B同时用 RSA算法各自生成一对公钥密钥&#xff0c;各自的公钥密钥都不同。 3…...

银行零售业务转型方法论:打造数字化的“有机体”

传统的业务增长进度叫做连续性创新&#xff0c;它是在一条曲线上渐进性的改良和发展&#xff0c;但这种发展终有极限&#xff0c;如果不能及时开辟第二增长曲线&#xff0c;就很容易被时代所抛弃。过去十年&#xff0c;以互联网为代表的数字化转型的先行者&#xff0c;不断冲击…...

【STM32】STM32使用RFID读卡器

STM32使用RFID读卡器 RFID卡片 ID卡&#xff08;身份标识&#xff09;&#xff1a;作用就是比如你要输入学号&#xff0c;你刷卡直接就相当于输入学号&#xff0c;省去了输入的过程 IC卡&#xff1a;集成电路卡&#xff0c;是将一种微电子芯片嵌入卡片之中 RFID的操作 1、…...

spring集成mybatis的原理

spring是怎样和mybatis继承的&#xff1f; 在idea里点mapper.queryOne()直接跳到了接口或xml&#xff0c;它究竟是怎样利用jdbc执行的&#xff1f; 我直接调用mapper.queryOne是怎么使用的sqlsession&#xff1f;怎么去connect的&#xff1f; mybatis是怎样根据mapper找到对应的…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...