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

news2024/11/20 19:42:53

前言

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);
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/542495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自定义颜色编辑选取对话框

一、简介 Qt中已经有一些封装好的对话框&#xff0c;比如QMessageBox、QColorDialog等&#xff0c;使用起来快捷方便&#xff0c;但缺点是我们无法为它们自定义样式&#xff0c;所以可能难以“融入”我们的项目。既然如此&#xff0c;那就自己做一个把。抱着这样的想法&#x…

Android SELinux安全机制与权限管理那些事

文章目录 前言权限管理系统应用特权应用历史漏洞广播的保护机制CVE-2020-0391 SELinux 前言 在 Android 漏洞挖掘和安全研究过程中&#xff0c;不可避免地会涉及到跟 Android SELinux 安全机制打交道&#xff0c;比如当你手握一个 System 应用的路径穿越的漏洞的时候想去覆写其…

DS:基于鸢尾花数据集利用多种数据降维技术(PCA、SVD、MDS、LDA、T-SNE)实现三维可视化

DS&#xff1a;基于鸢尾花数据集利用多种数据降维技术(PCA、SVD、MDS、LDA、T-SNE)实现三维可视化 目录 基于鸢尾花数据集利用多种数据降维技术(PCA、SVD、MDS、LDA、T-SNE)实现三维可视化 # 1、加载示例数据集&#xff08;鸢尾花数据集&#xff09; # 2、数据预处理 # T1、…

媒体专访是品牌初创阶段宣传的重要手段

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 很早以前&#xff0c;有位前辈跟我讲&#xff0c;人的成功分两种&#xff0c;一种是借助平台成功&#xff0c;一种是自己创业成功&#xff0c; 前者成功的概率很大&#xff0c;只需要选好…

【5.18】二、黑盒测试方法—因果图与决策表法

目录 2.3 因果图与决策表法 2.3.1 因果图设计法 2.3.2 决策表 2.3.3 实例&#xff1a;三角形决策表 2.3.4 实例&#xff1a;工资发放决策表 2.3 因果图与决策表法 等价类划分法与边界值分析法主要侧重于输入条件&#xff0c;却没有考虑这些输入之间的关系&#xff0c;如…

单链表和双向链表如何执行删除操作

在实际的软件开发中&#xff0c;从链表中删除一个数据无外乎这两种情况&#xff1a; 删除结点中“值等于某个给定值”的结点&#xff1b;删除给定指针指向的结点。 1.从头结点开始一个一个依次遍历对比&#xff0c;直到找到值等于给定值的结点&#xff0c;然后再通过我前面讲…

LeetCode高频算法刷题记录4

文章目录 1. 二叉树的最近公共祖先【中等】1.1 题目描述1.2 解题思路1.3 代码实现 2. 全排列【中等】2.1 题目描述2.2 解题思路2.3 代码实现 3. 相交链表【简单】3.1 题目描述3.2 解题思路3.3 代码实现 4. 合并 K 个升序链表【困难】4.1 题目描述4.2 解题思路4.3 代码实现 5. 环…

chatgpt赋能Python-python3_4怎么下载

Python3.4的下载和安装 Python是一种流行的编程语言&#xff0c;它被广泛用于算法学习、数据分析和网站开发等领域。Python3.4是Python编程语言的一个版本&#xff0c;它在性能和功能方面都得到了改进。如果你希望学习Python3.4或者使用它开发项目&#xff0c;那么你需要下载并…

Jetpack Compose中的附带效应简介及使用

前言 附带效应是指LaunchedEffect、DisposableEffect、rememberCoroutineScope、rememberUpdatedState、produceState 、derivedStateOf的使用。附带效应这4个字在google官方文档上的表达与解释挺让人难以理解的。其实个人认为准确的描述应该是外部产生的数据向Compose状态作用…

chatgpt赋能Python-python3_8_1怎么用

Python3.8.1使用指南&#xff1a;让您的编程更加高效 Python是一种流行的高级编程语言&#xff0c;它以简洁明了的语法和丰富的库而著称。如果您是一名新手或有经验的程序员&#xff0c;Python都是一个很好的选择。在Python3.8.1中&#xff0c;新的功能和改进将进一步提高Pyth…

chatgpt赋能Python-python2的n次方程序

Python2的N次方程序&#xff1a;一个实用的编程工具 Python2是广泛使用的编程语言之一&#xff0c;它是一种强大且灵活的开源语言&#xff0c;被广泛应用于科学计算、数据分析、Web开发等领域。在Python2中&#xff0c;N次方程序是一种非常基础的程序&#xff0c;但是它在实际…

二叉树的基本认识(一)

要了解二叉树&#xff0c;就必然要知道什么是树&#xff0c;树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的…

C++类模板的具体化

目录 分类 代码 分析 一、类模板 一&#xff09;代码 二&#xff09;注意事项 三&#xff09;运行结果 二、完全具体化的模板类 一&#xff09;代码 二&#xff09;注意事项 三&#xff09;执行结果 三、部分具体化的模板类 一&#xff09;代码 二&#xff09;注…

【研发工具】Yapi接口管理平台内网Centos8下搭建

1 环境依赖安装 环境要求 nodejs&#xff08;7.6) &#xff08;本文安装12.18.3&#xff09; mongodb&#xff08;2.6&#xff09;&#xff08;本文安装5.0.17&#xff09; 1.1 安装Nodejs 1.1.1 下载安装包 下载地址&#xff1a;https://nodejs.org/zh-cn/download/这里下载…

代码随想录训练营Day42|背包问题

目录 学习目标 学习内容 416. 分割等和子集 学习目标 01背包问题&#xff0c;你该了解这些&#xff01; 01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组 416. 分割等和子集 学习内容 problems/背包理论基础01背包-1.md programmercarl/leetcode-master&#…

Java【网络编程2】详解ServerSocket和Socket类, 逐行代码解析如何服务器客户端通信(附代码)

文章目录 前言一、认识 Socket(套接字), TCP 协议和 UDP 协议1, 什么是 Socket(套接字)2, 浅谈 TCP 协议和 UDP 协议的区别和特点 二、基于 TCP 协议的 Socket API1, ServerSocket 类2, Socket 类 三、逐行代码解析网络编程1, 逐行解析客户端1.1, 核心成员方法 start() 2, 逐行…

【黑马笔记】Servlet简易教程

1. Servlet demo 0. 新建web app项目 记得去 web.xml 中删除多余的配置&#xff0c;以及新建对应的文件夹 1. 导入 Servlet依赖坐标 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version&…

四块ACM区域赛金牌,我队友

是的&#xff0c;毕业12年以后&#xff0c;他来找我。     痛失网名了属于是&#xff0c;但是这不重要&#xff0c;​怎么说呢&#xff1f;有点激动&#xff0c;我得把这件事情记录下来&#xff0c;这是一位重量级的人物&#xff0c;也是大家眼中别人家的孩子。     他…

Python网络爬虫:Scrapy和Beautiful Soup的使用和数据处理技巧

章节一&#xff1a;引言 在当今互联网时代&#xff0c;数据的价值越来越被重视&#xff0c;而网络爬虫作为一种强大的工具&#xff0c;可以帮助我们从互联网中提取有用的数据。Python作为一门广泛应用于数据科学和网络开发的编程语言&#xff0c;有着丰富的库和框架来支持网络…

SD卡数据恢复软件哪个最好 SD卡数据恢复多少钱

SD卡是一种常见的数字存储卡&#xff0c;由于其体积小、存储能力强&#xff0c;至今仍然被应用在手机&#xff0c;行车记录仪&#xff0c;微型摄像机中。但SD卡在使用过程中可能会出现一些故障或者数据丢失的情况。那么今天小编就给大家介绍一下SD卡数据恢复软件哪个最好&#…