消息通知之系统层事件发布相关流程
前言
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中存在消息通知的处理,消息通知包括系统层事件发布、消息订阅、消息投递与处理,为了开发者能够熟悉消息的处理流程,本篇文章主要介绍系统层事件发布的相关流程。 整体流程 代码流程 发布消息 { 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的土地利用景观格局分析
土地利用以及景观格局是当前全球环境变化研究的重要组成部分及核心内容,其对区域的可持续发展以及区域土地管理有非常重要的意义。通过对土地利用时空变化规律进行分析可以更好的了解土地利用变化的过程和机制,并且通过调整人类社会经济活动,…...
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的优化和持久化
持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下…...
David Silver Lecture 7: Policy Gradient
1 Introduction 1.1 Policy-Based Reinforcement Learning 1.2 Value-based and policy based RL 基于值的强化学习 在基于值的 RL 中,目标是找到一个最优的值函数,通常是 Q 函数或 V 函数。这些函数为给定的状态或状态-动作对分配一个值,表…...
知识图谱学习笔记——(五)知识图谱推理
一、知识学习 声明:知识学习中本文主体按照浙江大学陈华钧教授的《知识图谱》公开课讲义进行介绍,并个别地方加入了自己的注释和思考,希望大家尊重陈华钧教授的知识产权,在使用时加上出处。感谢陈华钧教授。 (一&…...
用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: …...
最新入河排污口设置论证、水质影响预测与模拟、污水处理工艺分析及典型建设项目入河排污口方案报告书
随着水资源开发利用量不断增大,全国废污水排放量与日俱增,部分河段已远远超出水域纳污能力。近年来,部分沿岸入河排污口设置不合理,超标排污、未经同意私设排污口等问题逐步显现,已威胁到供水安全、水环境安全和水生态安全&#x…...
2023年认证杯二阶段C题数据合并python以及matlab多途径实现代码
对于每种心率下给出的数据,我们需要进行合并才能方便后续处理,这里为大家展示利用python以及matlab分别实现合并的代码 import pandas as pd import os# 创建一个空的DataFrame对象 merged_data pd.DataFrame()# 设置数据文件所在的文件夹路径 folder_…...
Win11校园网不弹出登录页面怎么回事?
Win11校园网不弹出登录页面怎么回事?最近有用户在使用校园网的时候遇到了一些问题,访问登录网站的时候,一直无法显示登录的界面。那么遇到这个情况如何去进行解决呢?一起来看看以下的解决方法分享吧。 解决方法如下: 方…...
S32K144低功耗休眠与唤醒实践总结
在做车载项目时,模块在常供电时需要维系随时可以被唤醒工作的状态,并且静态电流需要在3mA以内,当然在JTT1163标准中要求的是5mA以内。 目标明确了,在模块休眠时需要关闭一切不必要的资源消耗,只保留模块被唤醒的部分功…...
一文吃透 Vue 框架教程(上)
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
堆排序与取topK java实现
1.堆排序思路 最近趁着有点时间,稍微复习了一下数据结构相关内容,温习了一下堆排序,做一下记录。 首先我们复习一下什么是堆: 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,…...
https通信流程通俗理解
场景,假设A和B进行通信 CA: ( Certificate Authority )就是颁发 HTTPS 证书的组织。 通信流程步骤: 1、A告诉B使用 RSA算法进行加密,B说好的。 2、A和B同时用 RSA算法各自生成一对公钥密钥,各自的公钥密钥都不同。 3…...
银行零售业务转型方法论:打造数字化的“有机体”
传统的业务增长进度叫做连续性创新,它是在一条曲线上渐进性的改良和发展,但这种发展终有极限,如果不能及时开辟第二增长曲线,就很容易被时代所抛弃。过去十年,以互联网为代表的数字化转型的先行者,不断冲击…...
【STM32】STM32使用RFID读卡器
STM32使用RFID读卡器 RFID卡片 ID卡(身份标识):作用就是比如你要输入学号,你刷卡直接就相当于输入学号,省去了输入的过程 IC卡:集成电路卡,是将一种微电子芯片嵌入卡片之中 RFID的操作 1、…...
spring集成mybatis的原理
spring是怎样和mybatis继承的? 在idea里点mapper.queryOne()直接跳到了接口或xml,它究竟是怎样利用jdbc执行的? 我直接调用mapper.queryOne是怎么使用的sqlsession?怎么去connect的? mybatis是怎样根据mapper找到对应的…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
