首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

OpenHarmony的公共事件

  • 25-03-06 02:31
  • 4071
  • 7195
blog.csdn.net

OpenHarmony的公共事件

公共事件简介

CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。

公共事件分类

公共事件从系统角度可分为:系统公共事件和自定义公共事件。

  • 系统公共事件:CES内部定义的公共事件,当前仅支持系统应用和系统服务发布,例如HAP安装、更新、卸载等公共事件。目前支持的系统公共事件请参见系统公共事件列表。
  • 自定义公共事件:应用定义的公共事件,可用于实现跨进程的事件通信能力。
    公共事件按发送方式可分为:无序公共事件、有序公共事件和粘性公共事件。
  • 无序公共事件:CES在转发公共事件时,不考虑订阅者是否接收到该事件,也不保证订阅者接收到该事件的顺序与其订阅顺序一致。
  • 有序公共事件:CES在转发公共事件时,根据订阅者设置的优先级等级,优先将公共事件发送给优先级较高的订阅者,等待其成功接收该公共事件之后再将事件发送给优先级较低的订阅者。如果有多个订阅者具有相同的优先级,则他们将随机接收到公共事件。
  • 粘性公共事件:能够让订阅者收到在订阅前已经发送的公共事件就是粘性公共事件。普通的公共事件只能在订阅后发送才能收到,而粘性公共事件的特殊性就是可以先发送后订阅,同时也支持先订阅后发送。发送粘性事件必须是系统应用或系统服务,粘性事件发送后会一直存在系统中,且发送者需要申请ohos.permission.COMMONEVENT_STICKY权限,配置方式请参见声明权限。

运作机制

每个应用都可以按需订阅公共事件,订阅成功,当公共事件发布时,系统会将其发送给对应的应用。这些公共事件可能来自系统、其他应用和应用自身。
图1 公共事件示意图
图1 公共事件示意图

安全注意事项

  • 公共事件发布方:如果不加限制,任何应用都可以订阅公共事件并读取相关信息,应避免在公共事件中携带敏感信息。采用以下方式,可以限制公共事件接收方的范围。
    • 通过CommonEventPublishData中的subscriberPermissions参数指定订阅者所需权限。
    • 通过CommonEventPublishData中的bundleName参数指定订阅者的包名。
  • 公共事件订阅方:订阅自定义公共事件后,任意应用都可以向订阅者发送潜在的恶意公共事件。采用以下方式,可以限制公共事件发布方的范围。
    • 通过CommonEventSubscribeInfo中的publisherPermission参数指定发布者所需权限。
    • 通过CommonEventSubscribeInfo中的publisherBundleName参数参数指定发布者的包名。
  • 自定义公共事件名称应确保全局唯一,否则可能与其他公共事件冲突。

常用的公共事件

公共事件类型定义在ohos.commonEventManager模块的Support枚举中。

事件名称功能描述
COMMON_EVENT_POWER_CONNECTED设备连接到外部电源的公共事件的动作
COMMON_EVENT_POWER_DISCONNECTED设备与外部电源断开的公共事件的动作
COMMON_EVENT_CHARGING表示系统开始为电池充电的公共事件的动作
COMMON_EVENT_DISCHARGING表示系统停止为电池充电的公共事件的动作
COMMON_EVENT_SHUTDOWN表示设备正在关闭并将继续最终关闭的公共事件的操作
COMMON_EVENT_SCREEN_ON表示由电源服务发起的设备亮屏完成的普通事件的动作
COMMON_EVENT_SCREEN_OFF表示由电源服务发起的设备灭屏完成的普通事件的动作
COMMON_EVENT_WIFI_POWER_STATEWi-Fi开关状态变化
COMMON_EVENT_SCREEN_LOCKED表示屏幕锁定的公共事件
COMMON_EVENT_SCREEN_UNLOCKED表示屏幕解锁的公共事件
COMMON_EVENT_BATTERY_CHANGED表示电池充电状态、电平和其他信息发生变化的公共事件的动作
COMMON_EVENT_USB_DEVICE_ATTACHED当用户设备作为USB主机时,提示USB设备已挂载
COMMON_EVENT_USB_DEVICE_DETACHED当用户设备作为USB主机时,提示USB设备被卸载
其中上面的屏幕亮屏和灭屏,屏幕锁屏和解锁,接电源适配器和拔掉电源适配器、开启wifi和断开wifi、插入USB设备/拔掉USB设备等。其中对于手机、平板、PC来说,上面的几个事件都比较常用,尤其在设备后台灭屏降功耗的时候比较有用。COMMON_EVENT_POWER_CONNECTED/COMMON_EVENT_POWER_DISCONNECTED这两个事件对于手机和平板来说就是接电源和拔掉电源,在PC中就是AC和DC了。

资源调度服务中的事件转换

resource_schedule_service开源仓地址:https://gitee.com/openharmony/resourceschedule_resource_schedule_service
在资源调度子系统中,提供系统事件的感知以及分发,例如应用启动、退出、亮灭屏等。如果需要获取系统事件,并且进行相关资源调度,那么可以选择以插件形式加入资源调度服务中。

作为资源调度子系统的子模块,智能分组模块通过系统内应用前后台切换、用户焦点输入、后台任务的执行状态,决策进程的分组调度策略,并支持通过配置将调度策略映射到不同的CGROUP分组,为系统的性能、功耗均衡调度提供决策依据。同时该模块向资源调度框架转发应用状态、焦点状态、后台任务状态等系统事件,供插件订阅。

resource_schedule_service是接收事件,决策调度策略和执行调度机制的引擎,其架构图示如下:
资源调度服务架构图
其中包括以下几个重要组成部分: 1、事件管理器,包含了使用对外接口直接感知系统事件,以及使用监听形式感知系统事件功能。 2、应用智能分组,该组件接收应用生命周期变更的事件,决策应用的分组优先级,是全局资源调度的根本依据。 3、插件管理器,负责产品对应资源调度插件的加载,接收系统和应用的事件,并根据插件的订阅情况将事件分发给插件。 4、SOC统一调频服务,该服务主要是从SOC统一调频插件中接收调频事件,进行相关的调频仲裁,最终使用内核接口设置CPU频率策略。

resource_schedule_service主要通过插件的形式进行扩展和实现系统全局资源的调度功能,插件以动态链接的形式运行,不同产品可以选择不同的插件进行加载。目前已知的插件有智能感知调度插件、设备状态管理插件、SOC统一调频插件。其中SOC统一调频插件的服务包含在resource_schedule_service中,而另外两个插件的服务包含在其它仓内,最终都是根据系统事件设置调度策略到内核中进行实施。

1:插件Check_List

更新2022年2月18日14:35:24

插件名插件功能简介插件订阅事件进程基线内存(KB)插件内存基线(KB)插件的事件执行效率插件新增线程插件关联进程插件需要的权限插件负责人
soc_perfcpu提频RES_TYPE_APP_STATE_CHANGE; RES_TYPE_WINDOW_FOCUS; RES_TYPE_CLICK_RECOGNIZE;RES_TYPE_PUSH_PAGE; RES_TYPE_SLIDE_RECOGNIZE;常驻:5918 动态:5922常驻:88 动态:88无无socperf_service无HaoyangT
frame_aware_sched智能感知调度RES_TYPE_WINDOW_FOCUS; RES_TYPE_PROCESS_STATE_CHANGE; RES_TYPE_APP_STATE_CHANGE常驻:4537常驻:109暂无rongkunshi
component_sched外设调度RES_TYPE_SCREEN_STATUS;RES_TYPE_APP_STATE_CHANGE;RES_TYPE_ABILITY_STATE_CHANGE;RES_TYPE_EXTENSION_STATE_CHANGE;RES_TYPE_PROCESS_STATE_CHANGE;RES_TYPE_WINDOW_FOCUS; RES_TYPE_DEVICE_STILL_STATE_CHANGE;常驻:常驻: 动态:暂无linyunxuan
事件Check_List

更新2022年6月01日14:35:24

事件type事件用途事件value事件payload格式事件打点延时:订阅事件插件
RES_TYPE_SCREEN_STATUS屏幕状态0:屏幕暗 1:屏幕亮无需payload
RES_TYPE_APP_STATE_CHANGEAPP状态改变事件value : app state{“pid”=?,“uid”=?,“bundleName”=“?”}<10mssoc_perf; frame_aware
RES_TYPE_ABILITY_STATE_CHANGEABILITY状态改变事件value : ability state{“pid”=?,“uid”=?,“bundleName”=“?”}
RES_TYPE_EXTENSION_STATE_CHANGEEXTENSION状态改变事件value :extension state{“pid”=?,“uid”=?,“bundleName”=“?”}
RES_TYPE_PROCESS_STATE_CHANGE进程状态事件0:创建 1:销毁{“pid”=?,“uid”=?,“bundleName”=“?”}<10msframe_aware
RES_TYPE_WINDOW_FOCUS窗口聚焦事件0:聚焦1:不聚焦{“pid”=?,“uid”=?,“bundleName”=“?”, “windowId”=?,“windowType”=?,displayId=?}<10mssoc_perf ; frame_aware
RES_TYPE_TRANSIENT_TASK瞬态任务事件0:开始 1:结束{“pid”=?,“uid”=?,“bundleName”=“?”}
RES_TYPE_CONTINUOUS_TASK长时任务事件0:开始 1:结束{“pid”=?,“uid”=?,“abilityName”=“?”}
RES_TYPE_CGROUP_ADJUSTERcgroup改变事件0: 进程组分组变化 1: 线程分组变化{“pid”=?,“uid”=?,“name”=“?”,“oldGroup”=?, “newGroup”=?}
RES_TYPE_CLICK_RECOGNIZEace手势点击识别器无无<10mssoc_perf
RES_TYPE_PUSH_PAGEace pipeline_context.cpp::PushPage()无无<10mssoc_perf
RES_TYPE_SLIDE_RECOGNIZEace slide event recognize1: list fling on; 0: list fling off; 3: slide normal begin, 4: slide normal end无<10mssoc_perf
RES_TYPE_WINDOW_VISIBILITY_CHANGE窗口可见性状态变化事件1: 可见, 0: 不可见无--
RES_TYPE_REPORT_MMI_PROCESS上报mmi_service线程IDmmi_service线程号{“uid”=?, “pid”=?}--
RES_TYPE_REPORT_RENDER_THREAD上报应用的RSRender线程IDRSRenderThread线程号{“uid”=?, “pid”=?}--
RES_TYPE_APP_INSTALL_UNINSTALL应用安装和卸载事件value 0: 卸载, 1: 安装{“uid”=?,“bundleName”="?}--
RES_TYPE_WIFI_CONNECT_STATE_CHANGEwifi连接状态事件1:空闲, 2:连接中, 3:已连接, 4:断开中, 5:已断开无需payload--
RES_TYPE_USER_SWITCH用户切换事件value: 切换到的目标用户id无需payload--
RES_TYPE_USER_REMOVE用户删除事件value: 删除的用户id无需payload--
RES_TYPE_SCREEN_LOCK锁屏和解锁事件0:解锁 1:锁屏无需payload--
RES_TYPE_CALL_STATE_UPDATE电话状态改变事件value:电话状态无需payload--
RES_TYPE_AUDIO_RENDER_STATE_CHANGE音频流状态改变事件value:音频流状态{“uid”=?,“sessionId”=?}--
RES_TYPE_AUDIO_RING_MODE_CHANGE声音模式改变事件0:响铃模式 1:静音模式无需payload--
RES_TYPE_AUDIO_VOLUME_KEY_CHANGE音量改变事件value:音量大小{“volumeType”=?}--
RES_TYPE_POP_PAGEace pipeline_context.cpp::PopPage();无{“pid”=?,“uid”=?,“bundleName”=“?”,“abilityName”=“?”, “pageUrl”=“?”}--
RES_TYPE_WEB_GESTUREweb手势事件无无--
RES_TYPE_SHOW_REMOTE_ANIMATION动画开始事件0:动画开始 1:动画结束{“srcPid”=?}--
RES_TYPE_DEVICE_STILL_STATE_CHANGE当前设备运动状态和静止状态转变事件-1: 无效值,0: 转变为运动状态,1:转变为静止状态无--
RES_TYPE_RESIZE_WINDOW窗口缩放事件0: 窗口缩放开始,1:窗口缩放结束无--
RES_TYPE_MOVE_WINDOW窗口拖拽事件0: 窗口拖拽开始,1:窗口拖拽结束无--
RES_TYPE_LOAD_PAGE页面加载事件0: 页面加载开始,1:页面加载结束无--
RES_TYPE_DRAG_STATUS_BAR状态栏下拉事件0:状态栏下拉开始, 1:状态栏下拉结束无--
RES_TYPE_REPORT_SCENE_BOARD报告sceneBoard进程信息进程PID{“uid”=?, “mainTid”=?, “bundleName”=?}--
RES_TYPE_REPORT_KEY_THREAD报告关键线程0:新增,1:删除{“uid”=?, “pid”=?, “tid”=?, “role”=?}--
RES_TYPE_REPORT_WINDOW_STATE报告窗口状态0:新增,1:删除{“uid”=?, “pid”=?, “windowId”=?, “serialNum”=?, “state”=0 active 1 inactive}--
RES_TYPE_REPORT_SCENE_SCHED报告场景状态0:场景进入,1:场景退出{“uid”=?, “sceneId”=?,}--

通过查看https://gitee.com/openharmony/resourceschedule_resource_schedule_service中的源代码,我们可以看到event_controller.cpp中的void EventController::SystemAbilityStatusChangeListener::OnAddSystemAbility( int32_t systemAbilityId, const std::string& deviceId)接口中,添加了需要监听的公共事件,代码如下:

void EventController::SystemAbilityStatusChangeListener::OnAddSystemAbility(
    int32_t systemAbilityId, const std::string& deviceId)
{
    RESSCHED_LOGI("common event service is added");
    MatchingSkills matchingSkills;
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_CONNECTIVITY_CHANGE);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_INSTALLATION_STARTED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REPLACED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SCREEN_ON);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SCREEN_OFF);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_REMOVED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_BUNDLE_REMOVED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_FULLY_REMOVED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_NITZ_TIME_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_NITZ_TIMEZONE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_CHARGING);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_DISCHARGING);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_CALL_STATE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_WIFI_P2P_STATE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_POWER_SAVE_MODE_CHANGED);
    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED);
    matchingSkills.AddEvent(DATA_SHARE_READY);
    CommonEventSubscribeInfo subscriberInfo(matchingSkills);
    subscriber_ = std::make_shared<EventController>(subscriberInfo);
    SubscribeCommonEvent(subscriber_);
    SubscribeLockScreenCommonEvent();
}

void EventController::SystemAbilityStatusChangeListener::SubscribeLockScreenCommonEvent()
{
    MatchingSkills lockScreenSkills;
    lockScreenSkills.AddEvent("common.event.UNLOCK_SCREEN");
    lockScreenSkills.AddEvent("common.event.LOCK_SCREEN");
    CommonEventSubscribeInfo subscriberInfo(lockScreenSkills);
    subscriberInfo.SetPublisherBundleName(SCENE_BOARD_NAME);
    lockScreenSubscriber_ = std::make_shared<EventController>(subscriberInfo);
    SubscribeCommonEvent(lockScreenSubscriber_);
}

inline void SubscribeCommonEvent(std::shared_ptr<EventController> subscriber)
{
    if (CommonEventManager::SubscribeCommonEvent(subscriber)) {
        RESSCHED_LOGI("SubscribeCommonEvent ok");
    } else {
        RESSCHED_LOGW("SubscribeCommonEvent fail");
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
                        "COMPONENT_NAME", "MAIN",
                        "ERR_TYPE", "register failure",
                        "ERR_MSG", "EventController subscribe common events failed!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

另外,资源调度服务部件是通过`void EventController::OnReceiveEvent(const EventFwk::CommonEventData &data)'这个函数接口中转换公共事件到自定义枚举事件的,代码如下:

void EventController::OnReceiveEvent(const EventFwk::CommonEventData &data)
{
    Want want = data.GetWant();
    std::string action = want.GetAction();
    RESSCHED_LOGI("Recieved common event:%{public}s", action.c_str());

    nlohmann::json payload = nlohmann::json::object();
    if (HandlePkgCommonEvent(action, want, payload)) {
        return;
    }
    if (action == CommonEventSupport::COMMON_EVENT_SCREEN_ON) {
        ReportDataInProcess(ResType::RES_TYPE_SCREEN_STATUS, ResType::ScreenStatus::SCREEN_ON, payload);
        return;
    }
    if (action == CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
        ReportDataInProcess(ResType::RES_TYPE_SCREEN_STATUS, ResType::ScreenStatus::SCREEN_OFF, payload);
        return;
    }
    if (action == CommonEventSupport::COMMON_EVENT_CONNECTIVITY_CHANGE) {
        int32_t code = data.GetCode();
        HandleConnectivityChange(want, code, payload);
        return;
    }
    if (action == CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
        int32_t userId = data.GetCode();
        ReportDataInProcess(ResType::RES_TYPE_USER_SWITCH, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == CommonEventSupport::COMMON_EVENT_USER_REMOVED) {
        int32_t userId = data.GetCode();
        ReportDataInProcess(ResType::RES_TYPE_USER_REMOVE, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == "common.event.UNLOCK_SCREEN") {
        ReportDataInProcess(ResType::RES_TYPE_SCREEN_LOCK, ResType::ScreenLockStatus::SCREEN_UNLOCK, payload);
        return;
    }
    if (action == "common.event.LOCK_SCREEN") {
        ReportDataInProcess(ResType::RES_TYPE_SCREEN_LOCK, ResType::ScreenLockStatus::SCREEN_LOCK, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_CALL_STATE_CHANGED) {
        payload["state"] = want.GetIntParam("state", -1);
        ReportDataInProcess(ResType::RES_TYPE_CALL_STATE_CHANGED, static_cast<int64_t>(data.GetCode()), payload);
        return;
    }
    if (action == DATA_SHARE_READY) {
        DataShareIsReady();
        return;
    }
    
    handleEvent(data.GetCode(), action, payload);
}

void EventController::handleEvent(int32_t userId, const std::string &action, nlohmann::json &payload)
{
    if (action == CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_TIMEZONE_CHANGED, ResType::RES_TYPE_TIMEZONE_CHANGED, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_TIME_CHANGED, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIME_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_NITZ_TIME_CHANGED, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIMEZONE_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_NITZ_TIMEZONE_CHANGED, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_CHARGING) {
        ReportDataInProcess(ResType::RES_TYPE_CHARGING_DISCHARGING, ResType::ChargeStatus::EVENT_CHARGING, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_DISCHARGING) {
        ReportDataInProcess(ResType::RES_TYPE_CHARGING_DISCHARGING, ResType::ChargeStatus::EVENT_DISCHARGING, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED) {
        ReportDataInProcess(ResType::RES_TYPE_USB_DEVICE, ResType::UsbDeviceStatus::USB_DEVICE_ATTACHED, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED) {
        ReportDataInProcess(ResType::RES_TYPE_USB_DEVICE, ResType::UsbDeviceStatus::USB_DEVICE_DETACHED, payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_P2P_STATE_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_WIFI_P2P_STATE_CHANGED, static_cast<int64_t>(userId), payload);
        return;
    }
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_POWER_SAVE_MODE_CHANGED) {
        ReportDataInProcess(ResType::RES_TYPE_POWER_MODE_CHANGED, static_cast<int64_t>(userId), payload);
        return;
    }
    handleOtherEvent(userId, action, payload);
}

void EventController::handleOtherEvent(int32_t userId, const std::string &action, nlohmann::json &payload)
{
    if (action == EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED) {
        RESSCHED_LOGI("report boot completed");
        ReportDataInProcess(ResType::RES_TYPE_BOOT_COMPLETED,
            ResType::BootCompletedStatus::START_BOOT_COMPLETED, payload);
        return;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108

其中资源调度服务内部事件枚举定义如下:

namespace OHOS {
namespace ResourceSchedule {
namespace ResType {
enum : uint32_t {
    // first resType
    RES_TYPE_FIRST = 0,
    // screen status, value 0 means screen off, value 1 means screen on, else are invalid.
    RES_TYPE_SCREEN_STATUS = RES_TYPE_FIRST,
    // app state change event; value means app state; payload:pid,uid,bundleName
    RES_TYPE_APP_STATE_CHANGE = 1,
    // ability state change event; value means ability state; payload:pid,uid,bundleName
    RES_TYPE_ABILITY_STATE_CHANGE = 2,
    // extension state change event; value means extension state; payload:pid,uid,bundleName
    RES_TYPE_EXTENSION_STATE_CHANGE = 3,
    // process state event; value 0:created, 1:died; payload:pid,uid,bundleName
    RES_TYPE_PROCESS_STATE_CHANGE = 4,
    // window focused event; value 0:focused, 1:unfocused; payload:pid,uid,bundleName,windowId,windowType,displayId
    RES_TYPE_WINDOW_FOCUS = 5,
    // transient task event; value 0:start, 1:finish; payload:pid,uid,bundleName
    RES_TYPE_TRANSIENT_TASK = 6,
    // continuous task event; value 0:start, 1:finish; payload:pid,uid,abilityName
    RES_TYPE_CONTINUOUS_TASK = 7,
    /* cgroup change event;
     * value 0:set thread group sched; 1:set thread sched
     * payload: pid,uid,name,oldGroup,newGroup
     */
    RES_TYPE_CGROUP_ADJUSTER = 8,
    // ace gestures click_recognizer; value 1 touch event, value 2 click event
    RES_TYPE_CLICK_RECOGNIZE = 9,
    // ace pipeline_context.cpp::PushPage(); value 0: push_page_start, 1: push_page_complete
    RES_TYPE_PUSH_PAGE = 10,
    // ace slide event recognize; value 1: list fling on; 0: list fling off; 3: slide normal begin, 4: slide normal end.
    RES_TYPE_SLIDE_RECOGNIZE = 11,
    // window visibility change, value 1: isVisible, 0: not isVisible, payload:pid,uid,windowId,windowType
    RES_TYPE_WINDOW_VISIBILITY_CHANGE = 12,
    // report mmi_service service; value mmi_service tid; payload:uid,pid
    RES_TYPE_REPORT_MMI_PROCESS = 13,
    // report render thread; value render tid; payload:uid,pid
    RES_TYPE_REPORT_RENDER_THREAD = 14,
    // app install and uninstall event; value 0: uninstall, 1: install; payload:uid,bundleName
    RES_TYPE_APP_INSTALL_UNINSTALL = 15,
    // net connect state; value 0:unknow, 1:idle, 2:connecting, 3:connected, 4:disconnecting, 5:disconnected
    RES_TYPE_WIFI_CONNECT_STATE_CHANGE = 16,
    // user switch, value means the userId which switch to.
    RES_TYPE_USER_SWITCH = 17,
    // user remove, value means the userId which is removed.
    RES_TYPE_USER_REMOVE = 18,
    // screen unlock, value 0 means unlock, value 1 means locked.
    RES_TYPE_SCREEN_LOCK = 19,
    // bluetooth a2dp connect state, value 1: connected, 3: disconnected.
    RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE = 20,
    // network latency request, value 0: low latency, 1: normal latency, payload: identity
    RES_TYPE_NETWORK_LATENCY_REQUEST = 21,
    // call state update; value 0 : active, value 1 : holding, value 2 : dialing, value 3 : alerting,
    // value 4 : incoming, value 5 : waiting, value 6 : disconnected, value 7 : disconnecting, value 8 : idle
    RES_TYPE_CALL_STATE_UPDATE = 22,
    // Other process modify the thread Qos, value for client name id, payload: tid : qos , clientpid, pid
    RES_TYPE_THREAD_QOS_CHANGE = 23,
    // audio render state change; value -1 : RENDERER_INVALID, value 0 : RENDERER_NEW, value 1 : RENDERER_PREPARED,
    // value 2 : RENDERER_RUNNING, value 3 : RENDERER_STOPPED, value 4 : RENDERER_RELEASED, value 5 : RENDERER_PAUSED
    // payload:uid,sessionId
    RES_TYPE_AUDIO_RENDER_STATE_CHANGE = 24,
    // audio ring mode change; value 0 : RINGER_MODE_NORMAL, value 1 : RINGER_MODE_SILENT
    // value 2 : RINGER_MODE_VIBRATE
    RES_TYPE_AUDIO_RING_MODE_CHANGE = 25,
    RES_TYPE_AUDIO_VOLUME_KEY_CHANGE = 26,
    // app_ability_start_event : a very early app startup stub, when the app process has not been pulled up.
    // stub position : ability_runtime ability_manager_service.cpp::StartAbilityInner().
    // specifically : ability type is PAGE and ability launchMode is not SPECIFIED.
    RES_TYPE_APP_ABILITY_START = 27,
    // ace pipeline_context.cpp::PopPage(); value means nothing
    RES_TYPE_POP_PAGE = 28,
    // ace web gesture event recognize; value means nothing
    RES_TYPE_WEB_GESTURE = 29,
    // info from msdp, means device still state change(enter or exit)
    RES_TYPE_DEVICE_STILL_STATE_CHANGE = 30,
    // window resize event; value 0: resize window , value 1: stop resizing window.
    RES_TYPE_RESIZE_WINDOW = 31,
    // window move event; value 0: move window, value 1: stop moving window.
    RES_TYPE_MOVE_WINDOW = 32,
    // animation transition event; value 0: animation begin, value 1: animation end.
    RES_TYPE_SHOW_REMOTE_ANIMATION = 33,
    // load page; value 0: load page begin, value 1: load page end.
    RES_TYPE_LOAD_PAGE = 34,
    // report camera state, value 0: camera connect; value 1: camera disconnect
    RES_TYPE_REPORT_CAMERA_STATE = 35,
    // report runningLock state, value 0: runningLock disable; value 1: runningLock enable;
    // value 2: runningLock is proxied; value 3: runningLock is not proxied
    RES_TYPE_RUNNINGLOCK_STATE = 36,
    // drag status bar event; value 0: start drag, value 1: stop drag.
    RES_TYPE_DRAG_STATUS_BAR = 37,
    // report SceneBoard service, value pid; payload:uid, main_tid, bundleName
    RES_TYPE_REPORT_SCENE_BOARD = 38,
    // report key thread for render, value 0 add key Thread, 1 remove key thread, payload: uid, pid, tid, role
    RES_TYPE_REPORT_KEY_THREAD = 39,
    // report window state, value 0 add 1 remove, payload: uid, pid, windowId, serialNum state: 0 active 1 inactive
    RES_TYPE_REPORT_WINDOW_STATE = 40,
    // report scene sched, value 0 scene on 1 scene off, payload: uid, sceneId
    RES_TYPE_REPORT_SCENE_SCHED = 41,
    // web gesture move event; value 0: web gesture move start, value 1: web gesture move end.
    RES_TYPE_WEB_GESTURE_MOVE = 42,
    // web slide normal event; value 0: web slide normal start, value 1: web slide normal end.
    RES_TYPE_WEB_SLIDE_NORMAL = 43,
    // load url event; value means nothing.
    RES_TYPE_LOAD_URL = 44,
    // mousewheel event; value means nothing.
    RES_TYPE_MOUSEWHEEL = 45,
    // report webview audio status, value 0 start 1 stop, payload: uid, pid, tid
    RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE = 46,
    // report entering the multimodalinput state, value means subscribed multimodalinput state.
    RES_TYPE_MMI_INPUT_STATE = 47,
    // report anco load protect file config
    RES_TYPE_ANCO_CUST = 48,
    // report time zone changed
    RES_TYPE_TIMEZONE_CHANGED = 50,
    // report connection status
    RES_TYPE_CONNECTION_OBSERVER = 51,
    // report av session create event
    RES_TYPE_AV_SESSION_ON_SESSION_CREATE = 52,
    // report av session release event
    RES_TYPE_AV_SESSION_ON_SESSION_RELEASE = 53,
    // report av session change event
    RES_TYPE_AV_SESSION_ON_TOP_SESSION_CHANGE = 54,
    // report OnAppStateChanged event
    RES_TYPE_ON_APP_STATE_CHANGED = 55,
    // report efficiency resources event
    RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED = 56,
    // report av_codec state, value 0:codec start info, value 1:codec stop info.
    RES_TYPE_AV_CODEC_STATE = 57,
    // 58-64 value do not change
    RES_TYPE_NITZ_TIME_CHANGED = 58,
    RES_TYPE_TIME_CHANGED = 59,
    RES_TYPE_NITZ_TIMEZONE_CHANGED = 60,
    RES_TYPE_CHARGING_DISCHARGING = 61,
    RES_TYPE_USB_DEVICE = 62,
    RES_TYPE_CALL_STATE_CHANGED = 63,
    RES_TYPE_WIFI_P2P_STATE_CHANGED = 64,

    // last resType
    //report app associated start to performance radar
    RES_TYPE_APP_ASSOCIATED_START = 65,
    //report thermal state event
    RES_TYPE_THERMAL_STATE = 66,
    // socperf event begin
    RES_TYPE_SOCPERF_CUST_EVENT_BEGIN = 67,
    // socperf event end
    RES_TYPE_SOCPERF_CUST_EVENT_END = 68,
    // window drawing content change event
    RES_TYPE_WINDOW_DRAWING_CONTENT_CHANGE = 69,

    // report vediuo capture start or stop
    RES_TYPE_REPORT_SCREEN_CAPTURE = 70,
    // report long frame, value 0 scene on 1 scene off.
    RES_TYPE_LONG_FRAME = 71,
    // report key perf scene, value 0 enter scene 1 exit scene.
    RES_TYPE_KEY_PERF_SCENE = 72,
    // report super launcher state
    RES_TYPE_SUPER_LAUNCHER = 73,
    // report cast screen state
    RES_TYPE_CAST_SCREEN = 74,
    // report screen collabroation state
    RES_TYPR_SCREEN_COLLABROATION = 75,
    // report sa control app event, eg: start app or stop app
    RES_TYPE_SA_CONTROL_APP_EVENT = 76,
    // report CPU load of the entire machine,payload:cpuPercent
    RES_TYPE_SYSTEM_CPU_LOAD = 77,
    // report download or upload scene,value 0 enter scene 1 exit scene.
    RES_TYPE_UPLOAD_DOWNLOAD = 78,
    // report main screen split,value 0 enter scene 1 exit scene.
    RES_TYPE_SPLIT_SCREEN = 79,
    // report main screen floating window,value 0 enter scene 1 exit scene.
    RES_TYPE_FLOATING_WINDOW = 80,
    // report event distribute tid, value tid, payload uid, pid.
    RES_TYPE_REPORT_DISTRIBUTE_TID = 81,
    // report frame rate
    RES_TYPE_FRAME_RATE_REPORT = 82,

    // report web screen capture, value 0 start, value 1 stop
    RES_TYPE_WEBVIEW_SCREEN_CAPTURE = 83,
    // report video state. value 0 start playing, value 1 stop playing
    RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE = 84,
    // report location status. value 0 app status, value 1 switch status
    RES_TYPE_LOCATION_STATUS_CHANGE = 85,
    // report silent playback
    RES_TYPE_AUDIO_SILENT_PLAYBACK = 86,
    // report display mode event, value status, payload mode.
    RES_TYPE_DEVICE_MODE_STATUS = 88,
    // report distribute component change
    RES_TYPE_REPORT_DISTRIBUTE_COMPONENT_CHANGE = 89,
    // report web drag resize
    RES_TYPE_WEB_DRAG_RESIZE = 90,
    // report formCard create start/end
    RES_TYPE_FORM_STATE_CHANGE_EVENT = 91,
    // report power mode changed
    RES_TYPE_POWER_MODE_CHANGED = 92,
    // report thermal scenario changed
    RES_TYPE_THERMAL_SCENARIO_REPORT = 93,
    // report boot completed
    RES_TYPE_BOOT_COMPLETED = 94,
    // report continuous application startup
    RES_TYPE_CONTINUOUS_STARTUP = 95,
    // report account activating
    RES_TYPE_ACCOUNT_ACTIVATING = 96,
    // report silent playback in renderer
    RES_TYPE_AUDIO_RENDERER_SILENT_PLAYBACK = 97,
    // report continuous application install
    RES_TYPE_CONTINUOUS_INSTALL = 98,
    // report system updated
    RES_TYPE_FIRST_BOOT_AFTER_SYSTEM_UPGRADE = 99,
    // report background perceivable scene
    RES_TYPE_BACKGROUND_PERCEIVABLE_SCENE = 100,
    // user interaction scene
    RES_TYPE_USER_INTERACTION_SCENE = 101,
    // report game sched, value 0 start, value 1 stop
    RES_TYPE_REPORT_GAME_SCHED = 102,
    // report send frame event
    RES_TYPE_SEND_FRAME_EVENT = 103,
    // report app cold start only perf, value 0 start, value 1 stop
    RES_TYPE_ONLY_PERF_APP_COLD_START = 104,
    // report scene rotation, value 0 start, value 1 stop
    RES_TYPE_SCENE_ROTATION = 105,
    // report event vsync tid, value tid, payload pid, tid, uid.
    RES_TYPE_REPORT_VSYNC_TID = 106,
    // report cloud config update
    RES_TYPE_CLOUD_CONFIG_UPDATE = 107,
    // system ability status change
    RES_TYPE_SYSTEM_ABILITY_STATUS_CHANGE = 108,
    // mmi status change
    RES_TYPE_MMI_STATUS_CHANGE = 109,
    // report media output device change
    RES_TYPE_OUTPUT_DEVICE_CHANGE = 110,
    // report device idle
    RES_TYPE_DEVICE_IDLE = 111,
    // report media output device change
    RES_TYPE_BT_SERVICE_EVENT = 112,
    // report to hisi, let bmm_report begin change
    RES_TYPE_BMM_MONITER_CHANGE_EVENT = 113,
    // app frame drop event
    RES_TYPE_APP_FRAME_DROP = 114,
    // report rss cloud config update
    RES_TYPE_RSS_CLOUD_CONFIG_UPDATE = 115,
    // report game info
    RES_TYPE_GAME_INFO_NOTIFY = 116,
    // report power key down
    RES_TYPE_MMI_INPUT_POWER_KEY = 117,
    // report application stopped
    RES_TYPE_APP_STOPPED = 118,
    // last async resType
    ASYNC_RES_TYPE_LAST,
    // first sync resType
    SYNC_RES_TYPE_FIRST = ASYNC_RES_TYPE_LAST,
    // thaw one application
    SYNC_RES_TYPE_THAW_ONE_APP,
    // get all suspend state
    SYNC_RES_TYPE_GET_ALL_SUSPEND_STATE,
    // get thermal data
    SYNC_RES_TYPE_GET_THERMAL_DATA,
    // check shoul force kill process,
    SYNC_RES_TYPE_SHOULD_FORCE_KILL_PROCESS,
    // report to request mutex status
    SYNC_RES_TYPE_REQUEST_MUTEX_STATUS = 500,
    // report to check mutex before start
    SYNC_RES_TYPE_CHECK_MUTEX_BEFORE_START = 501,
    // last sync resType
    SYNC_RES_TYPE_LAST,
    // last resType
    RES_TYPE_LAST = SYNC_RES_TYPE_LAST,
};
} // namespace ResType
} // namespace ResourceSchedule
} // namespace OHOS
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271

接着在调频插件socperf_plugin、待机插件device_standby_plugin、分组策略插件cgroup_sched_plugin中添加对资源调度内部事件的订阅和监听回调处理。
以上三个插件都分别实现了如下三个接口:

接口名接口描述
function OnPluginInit(std::string& libName): bool;插件初始化
function OnPluginDisable(): void;插件退出
function OnDispatchResource(const std::shared_ptr& data):void;获取分发的事件

插件初始化的时候,指定需要注册监听的事件。在这些事件发生的时候,框架会依次分发给各个插件, 此时插件需要快速处理消息接收进行资源调度(需要有耗时任务则需另起线程处理),处理完成后返回。
插件事件处理约束

  • 1、插件可以用C/C++实现。
  • 2、插件的事件处理,必须快速完成,超过1ms会打印相关告警,超过10ms,框架认为插件异常而进行插件退出操作。

以待机插件device_standby_plugin为例,其代码实现路径为:device_standby_plugin.cpp

在init()函数中订阅相关事件,具体代码如下:

// 插件初始化
extern "C" bool OnPluginInit(std::string& libName)
{
    if (libName != LIB_NAME) {
        STANDBYSERVICE_LOGI("DeviceStandbyPlugin::OnPluginInit lib name is not match");
        return false;
    }
    DeviceStandbyPlugin::GetInstance().Init();
    STANDBYSERVICE_LOGI("DeviceStandbyPlugin::OnPluginInit success.");
    return true;
}

void DeviceStandbyPlugin::Init()
{
    resTypes_.insert(RES_TYPE_APP_INSTALL_UNINSTALL);
    resTypes_.insert(RES_TYPE_SCREEN_STATUS);
    resTypes_.insert(RES_TYPE_TIME_CHANGED);
    resTypes_.insert(RES_TYPE_NITZ_TIME_CHANGED);
    resTypes_.insert(RES_TYPE_TIMEZONE_CHANGED);
    resTypes_.insert(RES_TYPE_NITZ_TIMEZONE_CHANGED);
    resTypes_.insert(RES_TYPE_CHARGING_DISCHARGING);
    resTypes_.insert(RES_TYPE_USB_DEVICE);
    resTypes_.insert(RES_TYPE_CALL_STATE_CHANGED);
    resTypes_.insert(RES_TYPE_WIFI_P2P_STATE_CHANGED);
    resTypes_.insert(RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED);
    resTypes_.insert(RES_TYPE_POWER_MODE_CHANGED);
    resTypes_.insert(RES_TYPE_CLICK_RECOGNIZE);
    resTypes_.insert(RES_TYPE_MMI_INPUT_POWER_KEY);

    for (auto resType : resTypes_) {
        PluginMgr::GetInstance().SubscribeResource(LIB_NAME, resType);
    }
    STANDBYSERVICE_LOGI("DevicesStandbyPlugin::Init success");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

待机插件事件分发处理,相关代码如下:

// 获取分发的事件
extern "C" void OnDispatchResource(const std::shared_ptr<ResData>& data)
{
    DeviceStandbyPlugin::GetInstance().DispatchResource(data);
    STANDBYSERVICE_LOGD("DeviceStandbyPlugin::OnDispatchResource success.");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

待机插件退出,相关代码如下:

// 插件退出
extern "C" void OnPluginDisable()
{
    DeviceStandbyPlugin::GetInstance().Disable();
    STANDBYSERVICE_LOGI("DeviceStandbyPlugin::OnPluginDisable success.");
}

void DeviceStandbyPlugin::Disable()
{
    for (auto resType : resTypes_) {
        PluginMgr::GetInstance().UnSubscribeResource(LIB_NAME, resType);
    }
    resTypes_.clear();
    STANDBYSERVICE_LOGI("DevicesStandbyPlugin::Disable success");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在待机部件device_standby中使用事件

待机部件device_standby仓的源代码地址为:https://gitee.com/openharmony/resourceschedule_device_standby
设备待机部件为提高设备续航,降低设备功耗,在设备进入待机空闲状态时,系统会限制后台应用使用资源。开发者可以根据自身情况,为自己的应用申请纳入待机资源管控,或者暂时不被待机资源管控。
图 1 设备待机部件整体架构图
图 1 设备待机部件整体架构图
那么我们以亮屏和灭屏事件为例,看一下设备待机部件device_standby是如何使用资源调度部件resource_schedule_service中定义的事件的?

我们使用git clone https://gitee.com/openharmony/resourceschedule_device_standby.git命令下载好设备待机部件仓的源代码后,使用VScode打开源代码,搜索RES_TYPE_SCREEN_STATUS这个亮屏状态关键字,如下图所示:
搜索亮屏状态
可以看到utils\common\include\res_type.h中保持了一份资源调度模块的事件枚举
的子集,代码如下所示:

namespace OHOS {
namespace DevStandbyMgr {
namespace ResType {
enum : uint32_t {
    // first resType
    RES_TYPE_FIRST = 0,
    // screen status, value 0 means screen off, value 1 means screen on, else are invalid.
    RES_TYPE_SCREEN_STATUS = RES_TYPE_FIRST,
    // app state change event; value means app state; payload:pid,uid,bundleName
    RES_TYPE_APP_STATE_CHANGE = 1,
    // ability state change event; value means ability state; payload:pid,uid,bundleName
    RES_TYPE_ABILITY_STATE_CHANGE = 2,
    // extension state change event; value means extension state; payload:pid,uid,bundleName
    RES_TYPE_EXTENSION_STATE_CHANGE = 3,
    // process state event; value 0:created, 1:died; payload:pid,uid,bundleName
    RES_TYPE_PROCESS_STATE_CHANGE = 4,
    // window focused event; value 0:focused, 1:unfocused; payload:pid,uid,bundleName,windowId,windowType,displayId
    RES_TYPE_WINDOW_FOCUS = 5,
    // transient task event; value 0:start, 1:finish; payload:pid,uid,bundleName
    RES_TYPE_TRANSIENT_TASK = 6,
    // continuous task event; value 0:start, 1:finish; payload:pid,uid,abilityName
    RES_TYPE_CONTINUOUS_TASK = 7,
    /* cgroup change event;
     * value 0:set thread group sched; 1:set thread sched
     * payload: pid,uid,name,oldGroup,newGroup
     */
    RES_TYPE_CGROUP_ADJUSTER = 8,
    // ace gestures click_recognizer; value 1 touch event, value 2 click event
    RES_TYPE_CLICK_RECOGNIZE = 9,
    // ace pipeline_context.cpp::PushPage(); value 0: push_page_start, 1: push_page_complete
    RES_TYPE_PUSH_PAGE = 10,
    // ace slide event recognize; value 1: list fling on; 0: list fling off; 3: slide normal begin, 4: slide normal end.
    RES_TYPE_SLIDE_RECOGNIZE = 11,
    // window visibility change, value 1: isVisible, 0: not isVisible, payload:pid,uid,windowId,windowType
    RES_TYPE_WINDOW_VISIBILITY_CHANGE = 12,
    // report mmi_service service; value mmi_service tid; payload:uid,pid
    RES_TYPE_REPORT_MMI_PROCESS = 13,
    // report render thread; value render tid; payload:uid,pid
    RES_TYPE_REPORT_RENDER_THREAD = 14,
    // app install and uninstall event; value 0: uninstall, 1: install; payload:uid,bundleName
    RES_TYPE_APP_INSTALL_UNINSTALL = 15,
    // net connect state; value 0:unknow, 1:idle, 2:connecting, 3:connected, 4:disconnecting, 5:disconnected
    RES_TYPE_WIFI_CONNECT_STATE_CHANGE = 16,
    // user switch, value means the userId which switch to.
    RES_TYPE_USER_SWITCH = 17,
    // user remove, value means the userId which is removed.
    RES_TYPE_USER_REMOVE = 18,
    // screen unlock, value 0 means unlock, value 1 means locked.
    RES_TYPE_SCREEN_LOCK = 19,
    // bluetooth a2dp connect state, value 1: connected, 3: disconnected.
    RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE = 20,
    // network latency request, value 0: low latency, 1: normal latency, payload: identity
    RES_TYPE_NETWORK_LATENCY_REQUEST = 21,
    // call state update; value 0 : active, value 1 : holding, value 2 : dialing, value 3 : alerting,
    // value 4 : incoming, value 5 : waiting, value 6 : disconnected, value 7 : disconnecting, value 8 : idle
    RES_TYPE_CALL_STATE_UPDATE = 22,
    // Other process modify the thread Qos, value for client name id, payload: tid : qos , clientpid, pid
    RES_TYPE_THREAD_QOS_CHANGE = 23,
    // audio render state change; value -1 : RENDERER_INVALID, value 0 : RENDERER_NEW, value 1 : RENDERER_PREPARED,
    // value 2 : RENDERER_RUNNING, value 3 : RENDERER_STOPPED, value 4 : RENDERER_RELEASED, value 5 : RENDERER_PAUSED
    // payload:uid,sessionId
    RES_TYPE_AUDIO_RENDER_STATE_CHANGE = 24,
    // audio ring mode change; value 0 : RINGER_MODE_NORMAL, value 1 : RINGER_MODE_SILENT
    // value 2 : RINGER_MODE_VIBRATE
    RES_TYPE_AUDIO_RING_MODE_CHANGE = 25,
    RES_TYPE_AUDIO_VOLUME_KEY_CHANGE = 26,
    // app_ability_start_event : a very early app startup stub, when the app process has not been pulled up.
    // stub position : ability_runtime ability_manager_service.cpp::StartAbilityInner().
    // specifically : ability type is PAGE and ability launchMode is not SPECIFIED.
    RES_TYPE_APP_ABILITY_START = 27,
    // ace pipeline_context.cpp::PopPage(); value means nothing
    RES_TYPE_POP_PAGE = 28,
    // ace web gesture event recognize; value means nothing
    RES_TYPE_WEB_GESTURE = 29,
    // info from msdp, means device still state change(enter or exit)
    RES_TYPE_DEVICE_STILL_STATE_CHANGE = 30,
    // window resize event; value 0: resize window , value 1: stop resizing window.
    RES_TYPE_RESIZE_WINDOW = 31,
    // window move event; value 0: move window, value 1: stop moving window.
    RES_TYPE_MOVE_WINDOW = 32,
    // animation transition event; value 0: animation begin, value 1: animation end.
    RES_TYPE_SHOW_REMOTE_ANIMATION = 33,
    // load page; value 0: load page begin, value 1: load page end.
    RES_TYPE_LOAD_PAGE = 34,
    // report camera state, value 0: camera connect; value 1: camera disconnect
    RES_TYPE_REPORT_CAMERA_STATE = 35,
    // value 2: runningLock is proxied; value 3: runningLock is not proxied
    RES_TYPE_RUNNINGLOCK_STATE = 36,
    // drag status bar event; value 0: start drag, value 1: stop drag.
    RES_TYPE_DRAG_STATUS_BAR = 37,
    // report SceneBoard service, value pid; payload:uid, main_tid, bundleName
    RES_TYPE_REPORT_SCENE_BOARD = 38,
    // report key thread for render, value 0 add key Thread, 1 remove key thread, payload: uid, pid, tid, role
    RES_TYPE_REPORT_KEY_THREAD = 39,
    // report window state, value 0 add 1 remove, payload: uid, pid, windowId, serialNum state: 0 active 1 inactive
    RES_TYPE_REPORT_WINDOW_STATE = 40,
    // report scene sched, value 0 scene on 1 scene off, payload: uid, sceneId
    RES_TYPE_REPORT_SCENE_SCHED = 41,
    // web gesture move event; value 0: web gesture move start, value 1: web gesture move end.
    RES_TYPE_WEB_GESTURE_MOVE = 42,
    // web slide normal event; value 0: web slide normal start, value 1: web slide normal end.
    RES_TYPE_WEB_SLIDE_NORMAL = 43,
    // load url event; value means nothing.
    RES_TYPE_LOAD_URL = 44,
    // mousewheel event; value means nothing.
    RES_TYPE_MOUSEWHEEL = 45,
    // report webview audio status, value 0 start 1 stop, payload: uid, pid, tid
    RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE = 46,
    // report entering the multimodalinput state, value means subscribed multimodalinput state.
    RES_TYPE_MMI_INPUT_STATE = 47,
    // report anco load protect file config
    RES_TYPE_ANCO_CUST = 48,
    // report anco app is front
    RES_TYPE_ANCO_APP_FRONT = 49,
    // report time zone changed
    RES_TYPE_TIMEZONE_CHANGED = 50,
    // report connection status
    RES_TYPE_CONNECTION_OBSERVER = 51,
    // report av session create event
    RES_TYPE_AV_SESSION_ON_SESSION_CREATE = 52,
    // report av session release event
    RES_TYPE_AV_SESSION_ON_SESSION_RELEASE = 53,
    // report av session change event
    RES_TYPE_AV_SESSION_ON_TOP_SESSION_CHANGE = 54,
    // report OnAppStateChanged event
    RES_TYPE_ON_APP_STATE_CHANGED = 55,
    // report efficiency resources event
    RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED = 56,
    // report av_codec state, value 0:codec start info, value 1:codec stop info.
    RES_TYPE_AV_CODEC_STATE = 57,
    RES_TYPE_NITZ_TIME_CHANGED = 58,
    RES_TYPE_TIME_CHANGED = 59,
    RES_TYPE_NITZ_TIMEZONE_CHANGED = 60,
    RES_TYPE_CHARGING_DISCHARGING = 61,
    RES_TYPE_USB_DEVICE = 62,
    RES_TYPE_CALL_STATE_CHANGED = 63,
    RES_TYPE_WIFI_P2P_STATE_CHANGED = 64,
    // report power mode changed
    RES_TYPE_POWER_MODE_CHANGED = 92,
    // report power key down
    RES_TYPE_MMI_INPUT_POWER_KEY = 117,
    // last resType
    RES_TYPE_LAST,
};

inline const std::map<uint32_t, std::string> resTypeToStr = {
    { RES_TYPE_SCREEN_STATUS, "SCREEN_STATUS" },
    { RES_TYPE_APP_STATE_CHANGE, "APP_STATE_CHANGE" },
    { RES_TYPE_ABILITY_STATE_CHANGE, "ABILITY_STATE_CHANGE" },
    { RES_TYPE_EXTENSION_STATE_CHANGE, "EXTENSION_STATE_CHANGE" },
    { RES_TYPE_PROCESS_STATE_CHANGE, "PROCESS_STATE_CHANGE" },
    { RES_TYPE_WINDOW_FOCUS, "WINDOW_FOCUS" },
    { RES_TYPE_TRANSIENT_TASK, "TRANSIENT_TASK" },
    { RES_TYPE_CONTINUOUS_TASK, "CONTINUOUS_TASK" },
    { RES_TYPE_CGROUP_ADJUSTER, "CGROUP_ADJUSTER" },
    { RES_TYPE_CLICK_RECOGNIZE, "CLICK_RECOGNIZE" },
    { RES_TYPE_PUSH_PAGE, "PUSH_PAGE" },
    { RES_TYPE_SLIDE_RECOGNIZE, "SLIDE_RECOGNIZE" },
    { RES_TYPE_WINDOW_VISIBILITY_CHANGE, "WINDOW_VISIBILITY_CHANGE" },
    { RES_TYPE_REPORT_MMI_PROCESS, "REPORT_MMI_PROCESS" },
    { RES_TYPE_REPORT_RENDER_THREAD, "REPORT_RENDER_THREAD" },
    { RES_TYPE_APP_INSTALL_UNINSTALL, "APP_INSTALL_UNINSTALL" },
    { RES_TYPE_WIFI_CONNECT_STATE_CHANGE, "WIFI_CONNECT_STATE_CHANGE" },
    { RES_TYPE_USER_SWITCH, "USER_SWITCH" },
    { RES_TYPE_USER_REMOVE, "USER_REMOVE" },
    { RES_TYPE_SCREEN_LOCK, "SCREEN_LOCK" },
    { RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE, "BLUETOOTH_A2DP_CONNECT_STATE_CHANGE" },
    { RES_TYPE_NETWORK_LATENCY_REQUEST, "NETWORK_LATENCY_REQUEST" },
    { RES_TYPE_CALL_STATE_UPDATE, "CALL_STATE_UPDATE" },
    { RES_TYPE_THREAD_QOS_CHANGE, "THREAD_QOS_CHANGE" },
    { RES_TYPE_AUDIO_RENDER_STATE_CHANGE, "AUDIO_RENDER_STATE_CHANGE" },
    { RES_TYPE_AUDIO_RING_MODE_CHANGE, "AUDIO_RING_MODE_CHANGE" },
    { RES_TYPE_AUDIO_VOLUME_KEY_CHANGE, "AUDIO_VOLUME_KEY_CHANGE" },
    { RES_TYPE_APP_ABILITY_START, "APP_ABILITY_START" },
    { RES_TYPE_POP_PAGE, "POP_PAGE" },
    { RES_TYPE_WEB_GESTURE, "WEB_GESTURE" },
    { RES_TYPE_DEVICE_STILL_STATE_CHANGE, "DEVICE_STILL_STATE_CHANGE" },
    { RES_TYPE_RESIZE_WINDOW, "RES_TYPE_RESIZE_WINDOW" },
    { RES_TYPE_MOVE_WINDOW, "RES_TYPE_MOVE_WINDOW" },
    { RES_TYPE_SHOW_REMOTE_ANIMATION, "RES_TYPE_SHOW_REMOTE_ANIMATION" },
    { RES_TYPE_LOAD_PAGE, "RES_TYPE_LOAD_PAGE" },
    { RES_TYPE_REPORT_CAMERA_STATE, "RES_TYPE_REPORT_CAMERA_STATE" },
    { RES_TYPE_RUNNINGLOCK_STATE, "RES_TYPE_RUNNINGLOCK_STATE" },
    { RES_TYPE_DRAG_STATUS_BAR, "RES_TYPE_DRAG_STATUS_BAR" },
    { RES_TYPE_REPORT_SCENE_BOARD, "RES_TYPE_REPORT_SCENE_BOARD" },
    { RES_TYPE_REPORT_KEY_THREAD, "RES_TYPE_REPORT_KEY_THREAD" },
    { RES_TYPE_REPORT_WINDOW_STATE, "RES_TYPE_REPORT_WINDOW_STATE" },
    { RES_TYPE_REPORT_SCENE_SCHED, "RES_TYPE_REPORT_SCENE_SCHED" },
    { RES_TYPE_WEB_GESTURE_MOVE, "RES_TYPE_WEB_GESTURE_MOVE" },
    { RES_TYPE_WEB_SLIDE_NORMAL, "RES_TYPE_WEB_SLIDE_NORMAL" },
    { RES_TYPE_LOAD_URL, "RES_TYPE_LOAD_URL" },
    { RES_TYPE_MOUSEWHEEL, "RES_TYPE_MOUSEWHEEL" },
    { RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE, "RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE" },
    { RES_TYPE_MMI_INPUT_STATE, "RES_TYPE_MMI_INPUT_STATE" },
    { RES_TYPE_ANCO_CUST, "RES_TYPE_ANCO_CUST" },
    { RES_TYPE_ANCO_APP_FRONT, "RES_TYPE_ANCO_APP_FRONT" },
    { RES_TYPE_TIMEZONE_CHANGED, "RES_TYPE_TIMEZONE_CHANGED" },
    { RES_TYPE_TIME_CHANGED, "RES_TYPE_TIME_CHANGED" },
    { RES_TYPE_NITZ_TIME_CHANGED, "RES_TYPE_NITZ_TIME_CHANGED" },
    { RES_TYPE_NITZ_TIMEZONE_CHANGED, "RES_TYPE_NITZ_TIMEZONE_CHANGED" },
    { RES_TYPE_CHARGING_DISCHARGING, "RES_TYPE_CHARGING_DISCHARGING" },
    { RES_TYPE_USB_DEVICE, "RES_TYPE_USB_DEVICE" },
    { RES_TYPE_CALL_STATE_CHANGED, "RES_TYPE_CALL_STATE_CHANGED" },
    { RES_TYPE_WIFI_P2P_STATE_CHANGED, "RES_TYPE_WIFI_P2P_STATE_CHANGED" },
    { RES_TYPE_CONNECTION_OBSERVER, "RES_TYPE_CONNECTION_OBSERVER" },
    { RES_TYPE_AV_SESSION_ON_SESSION_CREATE, "RES_TYPE_AV_SESSION_ON_SESSION_CREATE" },
    { RES_TYPE_AV_SESSION_ON_SESSION_RELEASE, "RES_TYPE_AV_SESSION_ON_SESSION_RELEASE" },
    { RES_TYPE_AV_SESSION_ON_TOP_SESSION_CHANGE, "RES_TYPE_AV_SESSION_ON_TOP_SESSION_CHANGE" },
    { RES_TYPE_ON_APP_STATE_CHANGED, "RES_TYPE_ON_APP_STATE_CHANGED" },
    { RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED, "RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED" },
    { RES_TYPE_AV_CODEC_STATE, "RES_TYPE_AV_CODEC_STATE" },
    { RES_TYPE_POWER_MODE_CHANGED, "RES_TYPE_POWER_MODE_CHANGED" },
};
} // namespace ResType
} // namespace ResourceSchedule
} // namespace OHOS
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216

并且在services\core\src\standby_service_impl.cpp中的 StandbyServiceImpl::HandleCommonEvent接口,实现了对事件的统一处理,代码如下:

ErrCode StandbyServiceImpl::HandleCommonEvent(const uint32_t resType, const int64_t value, const std::string &sceneInfo)
{
    STANDBYSERVICE_LOGI("HandleCommonEvent resType = %{public}u, value = %{public}lld, sceneInfo = %{public}s",
                        resType, (long long)(value), sceneInfo.c_str());
    switch (resType) {
        case ResType::RES_TYPE_SCREEN_STATUS:
            HandleScreenStateChanged(value);
            break;
        case ResType::RES_TYPE_CHARGING_DISCHARGING:
            HandleChargeStateChanged(value);
            break;
        case ResType::RES_TYPE_USB_DEVICE:
            if (value == 0) {
                DispatchEvent(StandbyMessage(StandbyMessageType::COMMON_EVENT,
                                             EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED));
            } else {
                DispatchEvent(StandbyMessage(StandbyMessageType::COMMON_EVENT,
                                             EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED));
            }
            break;
        case ResType::RES_TYPE_CALL_STATE_CHANGED:
            HandleCallStateChanged(sceneInfo);
            break;
        case ResType::RES_TYPE_WIFI_P2P_STATE_CHANGED:
            HandleP2PStateChanged(value);
            break;
        case ResType::RES_TYPE_CLICK_RECOGNIZE:
            HandleScreenClickRecognize(value);
            break;
        case ResType::RES_TYPE_MMI_INPUT_POWER_KEY:
            HandleMmiInputPowerKeyDown(value);
            break;
#ifdef STANDBY_POWER_MANAGER_ENABLE
        case ResType::RES_TYPE_POWER_MODE_CHANGED:
            HandlePowerModeChanged(static_cast<PowerMgr::PowerMode>(value));
            break;
#endif
        case ResType::RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED:
            HandleResourcesStateChanged(value, sceneInfo);
            break;
        default:
            AppEventHandler(resType, value, sceneInfo);
            break;
    }
    return ERR_OK;
}

void StandbyServiceImpl::HandleScreenStateChanged(const int64_t value)
{
    if (value == 1) {
            DispatchEvent(StandbyMessage(StandbyMessageType::COMMON_EVENT,
                                         EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON));
    } else {
            DispatchEvent(StandbyMessage(StandbyMessageType::COMMON_EVENT,
                                         EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
注:本文转载自blog.csdn.net的雪域迷影的文章"https://blog.csdn.net/ccf19881030/article/details/143808234"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

123
硬件开发
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top