OpenHarmony源码解析之获取显示状态功能

系统 OpenHarmony
本文主要和大家分享了OpenHarmony电源管理子系统中获取显示状态功能的实现细节,对NAPI接口、显示服务请求端及显示服务提供端流程等,做了较为详细的代码说明。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

本文以OpenHarmony 3.1 Release - powermgr_display_manager源码为基础进行分析。

1、简介

显示能效管理组件是OpenHarmony电源管理子系统的一个组件,主要负责如下功能:

  1. 显示屏的亮/灭。
  2. 显示屏亮度调节。
  3. 获取显示状态。

本文主要分析获取显示状态功能,包括NAPI接口及功能实现的整个流程。

#夏日挑战赛#OpenHarmony源码解析之获取显示状态功能-开源基础软件社区

图1 电源管理子系统架构图

#夏日挑战赛#OpenHarmony源码解析之获取显示状态功能-开源基础软件社区

图2 显示能效管理组件架构图

2、显示能效管理组件代码目录

base/powermgr/display_manager
├── figures # 架构图
├── frameworks # FrameWork层
├── napi # NAPI
└── native # Native层
├── interfaces # 接口层
├── innerkits # 内部 APIs
└── kits # 外部接口 APIs
├── sa_profile # SA 配置文件
├── service # 服务层
├── native # Native
└── zidl # zidl 接口层
├── test # 测试用例
└── utils # 工具和通用层

3、获取显示状态整体流程

#夏日挑战赛#OpenHarmony源码解析之获取显示状态功能-开源基础软件社区

图3 获取显示状态时序图

流程描述:

  1. JavaScript应用调用getState获取显示状态。
  2. getState调用brightness.cpp注册的NAPI接口GetDisplayState,GetDisplayState会将获取显示屏亮度委托给DisplayPowerMgrClient对象的GetDisplayState方法。
  3. GetDisplayState首先获取显示服务代理端DisplayPowerMgrProxy对象,然后调用DisplayPowerMgrProxy的GetDisplayState方法。
  4. 显示服务代理端对象的GetDisplayState方法调用SendRequest向显示服务提供方DisplayPowerMgrService发送获取显示状态请求。
  5. DisplayPowerMgrService通过父类DisplayPowerMgrStub的OnRemoteRequest方法收到获取显示状态请求后,调用父类DisplayPowerMgrStub的GetDisplayStateStub方法。
  6. GetDisplayStateStub继续调用DisplayPowerMgrService的GetDisplayState方法。
  7. GetDisplayState根据设备id找到对应的ScreenController对象,然后调用ScreenController对象的GetState方法。
  8. ScreenController调用其自身的公共方法GetState方法,直接返回自身的私有成员变量state_,state_变量在构造ScreenController对象时默认设置为on状态,并且可通过ScreenController对象的公共方法UpdateState去改变。

(1)显示能效管理服务注册

  1. 调用System Ability的MakeAndRegisterAbility接口注册Display Power Manager Service实例。
//rk3568/base/powermgr/display_manager/service/native/src/display_system_ability.cpp
REGISTER_SYSTEM_ABILITY_BY_ID(DisplaySystemAbility, DISPLAY_MANAGER_SERVICE_ID, true);
//rk3568/foundation/distributedschedule/safwk/interfaces/innerkits/safwk/system_ability.h
#define REGISTER_SYSTEM_ABILITY_BY_ID(abilityClassName, systemAbilityId, runOnCreate) \
const bool abilityClassName##_##RegisterResult = \
SystemAbility::MakeAndRegisterAbility(new abilityClassName(systemAbilityId, runOnCreate));
  1. System Ability调用Display Power Manager Service的OnStart函数实现显示能效管理服务组件的启动。
//rk3568/base/powermgr/display_manager/service/native/src/display_system_ability.cpp

void DisplaySystemAbility::OnStart()
{
DISPLAY_HILOGI(MODULE_SERVICE, "Start service");
//将Display Power Manager Service服务发布到System Ability,此时DisplayPowerMgrService成为了显示能效管理服务提供端
if (!Publish(DelayedSpSingleton<DisplayPowerMgrService>::GetInstance())) {
DISPLAY_HILOGE(MODULE_SERVICE, "Failed to publish service");
}
}

(2)显示屏亮度调节NAPI接口定义及实现

  1. NAPI接口声明。
//rk3568/base/powermgr/display_manager/interfaces/kits/js/@ohos.brightness.d.ts
import { AsyncCallback } from './basic';
declare namespace brightness {
function getState(): number;
...
}
export default brightness;
  1. NAPI接口实现,NAPI接口GetDisplayState会进一步调用显示屏亮度调节客户端DisplayPowerMgrClient对象提供的GetDisplayState方法。
//rk3568/base/powermgr/display_manager/frameworks/napi/brightness.cpp
// 获取显示状态的NAPI接口初始化
static napi_value Init(napi_env env, napi_value exports)
{
// 将JavaScript调用的getState NAPI接口实现声明为GetDisplayState函数
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("getState", GetDisplayState),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
DISPLAY_HILOGD(MODULE_JS_NAPI, "return");
return exports;
}
//获取显示状态接口NAPI实现
static napi_value GetDisplayState(napi_env env, napi_callback_info info)
{
DISPLAY_HILOGD(MODULE_JS_NAPI, "enter");
size_t argc = 0;//参数个数
napi_value args[1] = { 0 };//参数定义
napi_value jsthis;//JS对象的this参数
void *data = nullptr;//回调数据指针
/* 根据环境变量获取参数 */
napi_status status = napi_get_cb_info(env, info, &argc, args, &jsthis, &data);
NAPI_ASSERT(env, (status == napi_ok) && (argc >= 0), "Bad parameters");
napi_value result;
// 调用客户端DisplayPowerMgrClient对象提供的GetDisplayState方法
DisplayState state = DisplayPowerMgrClient::GetInstance().GetDisplayState();
//创建js接口的返回值
napi_create_uint32(env, static_cast<uint32_t>(state), &result);
DISPLAY_HILOGD(MODULE_JS_NAPI, "return");
return result;
}

(3)获取显示状态客户端实现

  1. DisplayPowerMgrClient首先会调用GetProxy方法,GetProxy会通过GetSystemAbilityManager方法获取SystemAbilityManager实例,然后通过CheckSystemAbility方法检查对应的SA是否存在,并返回remoteObject对象,最后通过iface_cast构造proxy对象,此时创建了PowerMgrProxy实例。
  2. 然后DisplayPowerMgrClient会将显示状态获取委托给显示服务代理端DisplayPowerMgrProxy对象的GetDisplayState方法处理。
//rk3568/base/powermgr/display_manager/frameworks/native/display_power_mgr_client.cpp
// 调用方不提供id参数,id默认为0,表示本地显示设备
DisplayState DisplayPowerMgrClient::GetDisplayState(uint32_t id)
{
// 获取显示服务的代理端,这里返回的是DisplayPowerMgrProxy对象(service/zidl/src/display_power_mgr_proxy.cpp)
auto proxy = GetProxy();
if (proxy == nullptr) {
//如果没有获取到proxy,则显示状态返回unknown
return DisplayState::DISPLAY_UNKNOWN;
}
// 调用DisplayPowerMgrProxy的GetDisplayState,通过ipc方式获取显示状态结果
return proxy->GetDisplayState(id);
}
// 获取显示管理服务提供的代理对象
sptr<IDisplayPowerMgr> DisplayPowerMgrClient::GetProxy()
{
std::lock_guard lock(mutex_);
if (proxy_ != nullptr) {
return proxy_;
}
// 获取本设备内注册的SA的proxy
sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sam == nullptr) {
DISPLAY_HILOGE(MODULE_INNERKIT, "Failed to get system ability manager");
return nullptr;
}
// 检查显示管理服务是否注册
sptr<IRemoteObject> obj = sam->CheckSystemAbility(DISPLAY_MANAGER_SERVICE_ID);
if (obj == nullptr) {
DISPLAY_HILOGE(MODULE_INNERKIT, "Failed to get display manager service");
return nullptr;
}
sptr<IRemoteObject::DeathRecipient> dr = new DisplayDeathRecipient(*this);
if ((obj->IsProxyObject()) && (!obj->AddDeathRecipient(dr))) {
DISPLAY_HILOGE(MODULE_INNERKIT, "Failed to add death recipient");
return nullptr;
}
// 将obj转换成IDisplayPowerMgr具体类型:DisplayPowerMgrProxy
proxy_ = iface_cast<IDisplayPowerMgr>(obj);
deathRecipient_ = dr;
DISPLAY_HILOGI(MODULE_INNERKIT, "Succeed to connect display manager service");
// 返回DisplayPowerMgrProxy对象
return proxy_;
}

(4)获取显示状态服务代理端实现

DisplayPowerMgrProxy对象会将获取显示状态请求以IPC方式发送给显示服务提供端DisplayPowerMgrService对象处理。

//rk3568/base/powermgr/display_manager/service/zidl/src/display_power_mgr_proxy.cpp
// 显示服务代理端显示状态获取功能实现
DisplayState DisplayPowerMgrProxy::GetDisplayState(uint32_t id)
{
sptr<IRemoteObject> remote = Remote();
RETURN_IF_WITH_RET(remote == nullptr, DisplayState::DISPLAY_UNKNOWN);
uint32_t result = 0;
MessageParcel data;
MessageParcel reply;
MessageOption option;
if (!data.WriteInterfaceToken(DisplayPowerMgrProxy::GetDescriptor())) {
DISPLAY_HILOGE(MODULE_INNERKIT, "DisplayPowerMgrClient::%{public}s write descriptor failed!", __func__);
return DisplayState::DISPLAY_UNKNOWN;
}
WRITE_PARCEL_WITH_RET(data, Uint32, id, DisplayState::DISPLAY_UNKNOWN);
// 将请求发送给显示服务的stub端,消息类型是GET_DISPLAY_STATE
int ret = remote->SendRequest(static_cast<int>(IDisplayPowerMgr::GET_DISPLAY_STATE),
data, reply, option);
if (ret != ERR_OK) {
DISPLAY_HILOGE(MODULE_INNERKIT, "DisplayPowerMgrProxy::%{public}s SendRequest is failed,%d", __func__, ret);
return DisplayState::DISPLAY_UNKNOWN;
}
// 获取显示服务stub显示状态获取结果,如果无法获取结果,则返回unknown
if (!reply.ReadUint32(result)) {
DISPLAY_HILOGE(MODULE_INNERKIT, "Readback fail!");
return DisplayState::DISPLAY_UNKNOWN;
}
// 返回显示服务stub端执行结果
return static_cast<DisplayState>(result);
}

(5)获取显示状态服务提供端实现

DisplayPowerMgrStub会将获取显示状态转发给子类DisplayPowerMgrService的SetBrightness方法处理。

//rk3568/base/powermgr/display_manager/service/zidl/src/display_power_mgr_stub.cpp
// 处理显示管理代理端发送的请求
int32_t DisplayPowerMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
MessageOption &option)
{
DISPLAY_HILOGD(MODULE_SERVICE, "DisplayPowerMgrStub::OnRemoteRequest, cmd = %d, flags= %d",
code, option.GetFlags());
std::u16string descripter = DisplayPowerMgrStub::GetDescriptor();
std::u16string remoteDescripter = data.ReadInterfaceToken();
if (descripter != remoteDescripter) {
DISPLAY_HILOGE(MODULE_SERVICE, "DisplayPowerMgrStub::OnRemoteRequest failed, descriptor is not matched!");
return E_GET_POWER_SERVICE_FAILED;
}
switch (code) {
...
// 消息类型为GET_BRIGHTNESS的处理函数
case static_cast<int32_t>(IDisplayPowerMgr::GET_DISPLAY_STATE):
ret = GetDisplayStateStub(data, reply);
break;
...
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
}
// 显示亮度获取stub端处理函数
int32_t DisplayPowerMgrStub::GetDisplayStateStub(MessageParcel& data, MessageParcel& reply)
{
uint32_t id = 0;
READ_PARCEL_WITH_RET(data, Uint32, id, E_READ_PARCEL_ERROR);
// 调用子类DisplayPowerMgrService的GetDisplayState方法
DisplayState ret = GetDisplayState(id);
// 将调用结果发送给显示管理代理端
if (!reply.WriteUint32(static_cast<uint32_t>(ret))) {
DISPLAY_HILOGE(MODULE_SERVICE, "Failed to write GetDisplayStateStub return value");
return E_WRITE_PARCEL_ERROR;
}
return ERR_OK;
}

DisplayPowerMgrService会根据设备id找到对应的ScreenController对象,然后将显示状态获取转发给ScreenController对象的GetState方法处理。

//rk3568/base/powermgr/display_manager/service/native/src/display_power_mgr_service.cpp
// 显示管理服务端获取显示状态实现函数
DisplayState DisplayPowerMgrService::GetDisplayState(uint32_t id)
{
DISPLAY_HILOGI(MODULE_SERVICE, "GetDisplayState %{public}d", id);
//根据设备id找到对应的ScreenController对象,如果没找到则返回unknown
auto iterater = controllerMap_.find(id);
if (iterater == controllerMap_.end()) {
return DisplayState::DISPLAY_UNKNOWN;
}
// 返回ScreenController的GetState调用结果
return iterater->second->GetState();
}

(6)屏幕控制器实现

  1. ScreenController调用其自身的公共方法,直接返回自身的私有成员变量state_。
  2. ScreenController在构造时会加载系统所支持的四个状态(on,dim,off,suspend)到map中,此时state_默认构造为on状态。
  3. ScreenController私有成员变量state_可通过其公共方法UpdateState去改变。
//rk3568/base/powermgr/display_manager/service/native/src/screen_controller.cpp
class ScreenController :
public AnimateCallback,
public std::enable_shared_from_this<ScreenController> {
public:
...
DisplayState GetState()
{
//直接返回自身的私有成员变量state_
return state_;
};
//ScreenController私有成员变量state_可通过其公共方法UpdateState去改变
bool UpdateState(DisplayState state, uint32_t reason);
...
private:
...
DisplayState state_;
std::map<DisplayState, uint32_t> stateValues_;
...
};
//ScreenController在构造时会加载系统所支持的四个状态(on,dim,off,suspend)到map中,此时state_默认构造为on状态
ScreenController::ScreenController(uint64_t devId, std::shared_ptr<ScreenAction> action)
: devId_(devId), state_(DisplayState::DISPLAY_ON), action_(action)
{
DISPLAY_HILOGI(MODULE_SERVICE, "ScreenController created: %{public}d", static_cast<uint32_t>(devId_));
stateValues_.emplace(DisplayState::DISPLAY_ON, DISPLAY_FULL_BRIGHTNESS);
stateValues_.emplace(DisplayState::DISPLAY_DIM, DISPLAY_DIM_BRIGHTNESS);
stateValues_.emplace(DisplayState::DISPLAY_OFF, DISPLAY_OFF_BRIGHTNESS);
stateValues_.emplace(DisplayState::DISPLAY_SUSPEND, DISPLAY_SUSPEND_BRIGHTNESS);
animator_ = nullptr;
}

总结

本文主要和大家分享了OpenHarmony电源管理子系统中获取显示状态功能的实现细节,对NAPI接口、显示服务请求端及显示服务提供端流程等,做了较为详细的代码说明,希望通过本文您能初步掌握电源管理子系统的关键功能和核心流程。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-08-12 19:07:58

电源管理子系统鸿蒙

2022-06-13 14:18:39

电源管理子系统耗电量服务

2021-12-14 14:45:38

鸿蒙HarmonyOS应用

2022-02-14 14:47:11

SystemUIOpenHarmon鸿蒙

2022-05-17 10:42:36

reboot源码解析

2021-09-16 15:08:08

鸿蒙HarmonyOS应用

2022-02-17 20:57:07

OpenHarmon操作系统鸿蒙

2021-11-25 09:54:54

鸿蒙HarmonyOS应用

2022-01-06 16:17:58

鸿蒙HarmonyOS应用

2021-12-17 16:42:09

鸿蒙HarmonyOS应用

2021-11-08 15:04:47

鸿蒙HarmonyOS应用

2021-09-18 14:40:37

鸿蒙HarmonyOS应用

2021-12-08 15:07:51

鸿蒙HarmonyOS应用

2022-05-20 10:32:49

事件循环器事件队列鸿蒙

2022-01-20 14:33:29

openharmonwayland协议鸿蒙

2022-01-10 15:30:11

鸿蒙HarmonyOS应用

2021-08-30 18:09:57

鸿蒙HarmonyOS应用

2022-07-19 20:04:31

NAPI模块鸿蒙

2023-04-12 15:31:11

系统服务管理鸿蒙

2021-12-06 06:19:03

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号