一. 简介

有些子系统能为上层提供可订阅的数据,如传感器子系统等。应用端通过onoff函数订阅或取消订阅某些事件,当订阅时能接收xx子系统底层过来的数据/事件。应用端可展示这些数据或进展这些数据、事件进行某些操作(下面的代码,功能已可用但不完善)。

img

上图展示了代码的大概的层级结构和数据上报模块的大体工作流程,详细见下面两部分

二. 注册数据接收

  1. frameworks/js/napi/display/src/display_setting.cpp 中定义观察者:
namespace {
std::shared_ptr<DisplayAccessObserver> g_displayAccessObserver = std::make_shared<DisplayAccessObserver>();
}

初始化DisplaySetting::Init() 时调用RegisterAccessObserverToHost(),将g_displayAccessObserver传到services/client/src/xxmw_client_manager.cpp中,通过DisplayHostObserverImp中Register函数保存到观察者对象列表中

void DisplaySetting::RegisterAccessObserverToHost()
{
    XXMW_DEBUG_LOG("DisplaySetting::RegisterAccessObserverToHost in");
    XXMWClientManager *host = &XxMWClientManager::GetInstance();
    host->RegisterObserver(g_displayAccessObserver);
}
void XxMWClientManager::RegisterObserver(std::shared_ptr<DisplayHostObserver> observer)
{
    XXMW_DEBUG_LOG("RegisterObserver enter");
    if (pimpl == nullptr) {
        XXMW_ERR_LOG("pimpl is null.");
        return;
    }
    pimpl->observers_.Register(observer);
}
DisplayObserverList<DisplayHostObserver> observers_;
  1. hap应用种调用on/off接口,注册/注销事件
    @ohos.xxservice.displaySetting.d.ts对上层应用提供事件订阅接口,如:
  function off(type: 'sourcePlugIn', callback?: Callback<number>): void;
  function  on(type: 'sourcePlugIn', callback:  Callback<number>): void;

  function off(type: 'sourcePlugOut', callback?: Callback<number>): void;
  function  on(type: 'sourcePlugOut', callback:  Callback<number>): void;
  ... ...

sourcePlugIn, sourcePlugOut代表事件名称, on(订阅)函数必须要由callback参数,用以接收返回的数据,off的callback参数可有可无

  1. display_setting.cpp 中定义观察者g_displayAccessObserver, 定义on/off函数,对应RegisterObserver/DeregisterObserver函数:
    // on/off state observer
    BindNativeFunction(env, exportObj, "on", moduleName, DisplaySetting::RegisterObserver);
    BindNativeFunction(env, exportObj, "off", moduleName, DisplaySetting::DeregisterObserver);
napi_value DisplaySetting::RegisterObserver(napi_env env, napi_callback_info info)
{
    XXMW_DEBUG_LOG("DisplaySetting::RegisterObserver in");
    if (g_displayAccessObserver) {
        // 通过观察者中的事件订阅模块,注册订阅的事件和对应的callback到事件订阅模块
        auto status = g_displayAccessObserver->eventSubscribe_.Register(env, info);
        if (status != napi_ok) {
            NError(ERR_PARAM_NUMBER).ThrowErr(env, "Register error!");
            return nullptr;
        }
    }
    return NapiGetUndefined(env);
}

napi_value DisplaySetting::DeregisterObserver(napi_env env, napi_callback_info info)
{
    XXMW_DEBUG_LOG("DisplaySetting::DeregisterObserver in");
    if (g_displayAccessObserver) {
        // 注销事件订阅模块中的某个事件和对应的callback
        auto status = g_displayAccessObserver->eventSubscribe_.Deregister(env, info);
        if (status != napi_ok) {
            NError(ERR_PARAM_NUMBER).ThrowErr(env, "Deregister error!");
            return nullptr;
        }
    }
    return NapiGetUndefined(env);
}

观察者对象中有事件订阅模块(class EventSubscribeModule, interfaces/kits/js/napi/event_subscribe_module.h),通过display_setting.cpp : RegisterObserver()函数调用订阅模块的Register()可将应用层的订阅事件和对应callback保存到事件订阅模块中,备后续使用

  1. 连接服务端(services/client/src/xxmw_client_manager.cpp : Connect()),连接服务端时将xxmw_client_manager.cpp中,将DisplayHostObserverImp对象(保存有观察者对象列表)送到服务端stub
int32_t XxMWClientManager::Connect()
{
    if (g_sProxy != nullptr) {
        return SUS;
    }

    ... ...
   
    g_sProxy = iface_cast<IXxMWAbility>(object);
    RETURN_IF_WITH_RET_WITH_LOG(g_sProxy == nullptr, FAIL, "Convert Proxy is Failed");
    g_sProxy->RegisterObserver(pimpl->observerImp_);

    XXMW_DEBUG_LOG("Connect Success");
    return SUS;
}
  1. 服务端stub(services/server/src/xxmw_ability_stub.cpp)接收到注册观察者函数调用时保存传过来的DisplayHostObserverImp对象,然后调用services/server/src/xxmw_system_ability.cpp中的RegisterObserver()函数注册保存
    stubFuncMap_[REGISTER_OBSERVER] = &XxMWAbilityStub::RegisterObserverInternal;
    stubFuncMap_[DEREGISTER_OBSERVER] = &XxMWAbilityStub::DeregisterObserverInternal;
void XxMWAbilityStub::RegisterObserverInternal(MessageParcel &data, MessageParcel &reply)
{
    XXMW_DEBUG_LOG("RegisterObserverInternal entered");
    sptr<IRemoteObject> remote = data.ReadRemoteObject();
    const sptr<IXxMWObserver> observer = OHOS::iface_cast<IXxMWObserver>(remote);
    RegisterObserver(observer);
}

void XxMWAbilityStub::DeregisterObserverInternal(MessageParcel &data, MessageParcel &reply)
{
    XXMW_DEBUG_LOG("DeregisterObserverInternal entered");
    sptr<IRemoteObject> remote = data.ReadRemoteObject();
    const sptr<IXxMWObserver> observer = OHOS::iface_cast<IXxMWObserver>(remote);
    DeregisterObserver(observer);
}

三. 数据上报及接口调用

  1. services/server/src/xxmw_system_ability.cpp 接收到hdi传上来的数据
  2. 如SetBootCompletedSaturation等函数可收到hdi返回的数据,可在services/server/src/xxmw_system_ability.cpp中收到数据后调用mAdapterManager->OnAdapterSourcePlugIn()等函数,将事件传递上去
  3. 调用mAdapterManager->OnAdapterSourcePlugIn()等事件上报函数时,会遍历各个注册过的观察者,然后调用xxmw_system_ability.cpp中的AdapterObserver对象中的OnSourcePlugIn()等函数
// services/server/src/xxmw_adapter_manager.cpp
void XxMWAdapterManager::OnAdapterSourcePlugIn(int32_t sourcePlugIn)
{
    XXMW_DEBUG_LOG("OnAdapterSourcePlugIn sourcePlugIn is %{public}d", sourcePlugIn);
    std::lock_guard<std::recursive_mutex> lock(pimpl->syncMutex_);
    pimpl->adapterObservers_.ForEach(
        [sourcePlugIn](IAdapterObserver &observer) { observer.OnSourcePlugIn(sourcePlugIn); });
}
// services/server/src/xxmw_system_ability.cpp
void OnSourcePlugIn(int32_t sourcePlugIn) override
{
    if (!impl_) {
        XXMW_ERR_LOG("OnSourcePlugIn err");
        return;
    }
    impl_->observers_.ForEach([this, sourcePlugIn](sptr<IXxMWObserver> observer) {
        int32_t pid = this->impl_->observersPid_.ReadVal(observer->AsObject());
        uint32_t tokenId = this->impl_->observersToken_.ReadVal(observer->AsObject());
        XXMW_INFO_LOG("OnSourcePlugIn pid:%d, tokenId:%d", pid, tokenId);
        observer->OnSourcePlugIn(sourcePlugIn);
    });
}
  1. 然后调用代理对象的函数如:services/server/src/display_host_observer_proxy.cpp:OnSourcePlugIn(),通过ipc发送数据到xxservice客户端
void DisplayHostObserverProxy::OnSourcePlugIn(int32_t sourcePlugIn)
{
    MessageParcel data;

    if (!data.WriteInterfaceToken(DisplayHostObserverProxy::GetDescriptor())) {
        XXMW_ERR_LOG("DisplayHostObserverProxy::OnSourcePlugIn WriteInterfaceToken error");
        return;
    }

    if (!data.WriteInt32(sourcePlugIn)) {
        XXMW_ERR_LOG("DisplayHostObserverProxy::OnSourcePlugIn write sourcePlugIn type error");
        return;
    }

    MessageParcel reply;
    MessageOption option = {MessageOption::TF_ASYNC};

    ErrCode result = InnerTransact(OBSERVER_SOURCE_PLUG_IN, option, data, reply);
    if (result != ERR_NONE) {
        XXMW_ERR_LOG("DisplayHostObserverProxy::OnSourcePlugIn done fail, error: %{public}d", result);
        return;
    }
}
  1. 客户端通过services/client/src/display_host_observer_stub.cpp接收服务端事件上报,
void DisplayHostObserverStub::OnSourcePlugInInner(MessageParcel &data, MessageParcel &reply)
{
    XXMW_DEBUG_LOG("OnSourcePlugInInner entered");
    int32_t value = data.ReadInt32();
    XXMW_DEBUG_LOG("OnSourcePlugInInner value = %{public}d", value);
    OnSourcePlugIn(value);
    XXMW_DEBUG_LOG("DisplayHostObserverStub:OnSourcePlugInInner internal exit");
}

再调用到xxmw_client_manager.cpp中XxMWClientManager::impl::DisplayHostObserverImp下OnSourcePlugIn()函数, 然后遍历注册的对应事件和回调函数,传递数据到上层应用中的on函数

void OnSourcePlugIn(int32_t sourcePlugIn) override
{
    host_.observers_.ForEach([sourcePlugIn](std::shared_ptr<DisplayHostObserver> observer) {
        observer->OnSourcePlugIn(sourcePlugIn);
    });
}
  1. 服务端(services/server/src/xxmw_system_ability.cpp)收到数据后上报方法:根据事件对应的函数调用mAdapterManager->OnAdapterSourcePlugIn()等函数,其他函数见xxmw_adapter_manager.h中声明;
    如果在其他模块或文件中调用数据上报,可通过XxMWAdapterManager::GetInstance()获取mAdapterManager(mAdapterManager是XxMWAdapterManager对象,变量名可自行定义)

    后续还要解耦优化,如:将数据上报的接口从xxmw_adapter_manager.h中拆出来,使用更方便

  2. 大体的目录结构参考(不通的子系统通常有所不同)

img

img

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐