Android R(11) 为HIDL服务添加观察者模式(Observer Pattern)的支持(十)

1.观察者模式(Observer Pattern)简介

  当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。通俗的举个例子,以前没有电热水器的时候,我们需要将水壶放到炉灶上加热,并且守在旁边或者隔一段时间主动的来查看水壶中的水是否被烧开,如果烧开了就停止加热,反之则继续等待。但是现在我们有了电热水壶,此时我们可以给电热水壶设置一个指定的温度,让其达到这个温度时发出铃声来主动通知我。这里的设定温度(观察者注册listener)以及电热水壶的主动通知(通过注册的listener回调通知观察者)就类似观察者模式的运作。Observer Pattern的关系图大致如下
Android R(11) 为HIDL服务添加观察者模式(Observer Pattern)的支持(十)_第1张图片

2. 源码修改概览

  下面就让我们自定的HIDL service支持电热水壶的主动通知功能,整体源码的修改如下。

flagstaff@flagstaff-pc:~/aosp_r.lns/test/flagstaffTest$ git show HEAD --stat
commit 527add63b05a34f3c5fc21a8f5097965742885cc (HEAD -> master)
Author: flagstaff <flagstaff@fake.com>
Date:   Mon Feb 7 20:59:18 2022 +0800

    1.Supportting observer pattern for CustomHardware HIDL service.
    2.serviceModelClient supports registerWaterTemperatureListener.

    Signed-off-by: flagstaff <flagstaff@fake.com>

 hardware/interfaces/custom_hardware/1.0/Android.bp                                |  1 +
 hardware/interfaces/custom_hardware/1.0/ICustomHardware.hal                       |  4 ++++
 hardware/interfaces/custom_hardware/1.0/IWaterTemperatureListener.hal             |  6 ++++++
 hardware/interfaces/custom_hardware/1.0/default/include/CustomHardware.h          | 20 ++++++++++++++++++--
 hardware/interfaces/custom_hardware/1.0/default/src/CustomHardware.cpp            | 47 ++++++++++++++++++++++++++++++++++++++---------
 hardware/interfaces/custom_hardware/1.0/serviceModelClient/serviceModelClient.cpp | 23 +++++++++++++++++++++++
 6 files changed, 90 insertions(+), 11 deletions(-)

  IWaterTemperatureListener.hal 用于接口定义,在开启电热水壶前我们会将其实现注册到 HIDL service中去,接着电热水壶烧好水后则会回调该接口去通知观察者。
  程序的运行流程如下
   a)client 实现接口类IWaterTemperatureListener并注册温度及其实现到HIDL service。
   b)HIDL service 被启动烧水功能后,在水温达到client的注册温度时,回调client的IWaterTemperatureListener接口类实现。
   c)client打印HIDL service此时的水温,实际上也就是当时注册时的温度。

3.Android.bp

@@ -6,6 +6,7 @@ hidl_interface {
     system_ext_specific: true,
     srcs: [
         "ICustomHardware.hal",
+        "IWaterTemperatureListener.hal",
     ],
     interfaces: [
         "[email protected]",

  IWaterTemperatureListener.hal实际上和cpp/java等后缀源码在概念上是一样的,也就是HIDL 框架中的源代码,故新添加一个文件需要在Makefile中指出。

4.ICustomHardware.hal的改变

+import @1.0::IWaterTemperatureListener;
+
 interface ICustomHardware {
     enableHardware(bool data) generates (bool ret);
+    registerWaterTemperatureListener(int8_t waterTemperature,
+            IWaterTemperatureListener listener) generates (bool ret);
 };

  新增加的接口registerWaterTemperatureListener,入参(waterTemperature)为client期望被通知时电热水壶中的水温,入参(listener)则是client对接口类IWaterTemperatureListener的实现。

5.IWaterTemperatureListener

@@ -0,0 +1,6 @@
+package flagstaff.hardware.custom_hardware@1.0;
+
+interface IWaterTemperatureListener{
+    notifyWaterTemperature(int8_t curWaterTemperature)
+                            generates (bool ret);
+};

  接口类包含的接口很简单,入参为client告诉HIDL service回调它的电热水壶的水温,返回值为布尔类型,可以用于后期拓展,例如告知HIDL service client是否正确处理该通知。

6.CustomHardware的实现

6.1 registerWaterTemperatureListener

+Return<bool> CustomHardware::registerWaterTemperatureListener(int8_t waterTemperature,
+    const sp<IWaterTemperatureListener>& listener) {
+        LOG(ERROR)<<__func__<<":[waterTemperature]"<<std::to_string(waterTemperature);
+        mWTListenerWait = waterTemperature;
+        mWTListenersMap = listener;
+        return true;
+}

  registerWaterTemperatureListener 接口用于注册client的期望水温及其回调实现。一般程序是需要支持多个监听者的,这里为了简单展示就只支持单一监听者了。
mWTListenerWait用于记录client的期望水温,mWTListenersMap则用于记录client注册的接口类的实现。

6.2 enableHardware

+Return<bool> CustomHardware::enableHardware(bool data) {
+    //if(data && !mIsMakeBoilWater.load()){
+    if(data){
+        new thread([this](){
+            int8_t preWTListenerWait = mWTListenerWait;
+            LOG(ERROR)<<"start one thread to simulate making boil water.[mWTListenerWait]"
+                <<std::to_string(mWTListenerWait);
+            mIsMakeBoilWater.store(true);
+            while(--preWTListenerWait){
+                sleep(1);
+            }
+            //calls the callback from listeners
+            notifyTemperatureDone();
+            mWTListenerWait = 101;
+            mIsMakeBoilWater.store(false);
+        });
+    }
+    return bool {true};
+}

  a)enableHardware 实现的比较简单,在client调用该接口开始烧水后,会用在线程中倒计时的方式来模拟烧水需要消耗的时间,这里按一度水一秒的速度为水加热。
  b)在烧完热水后再回调client的接口类实现

+void CustomHardware::notifyTemperatureDone() {
+    LOG(ERROR)<<__func__;
+    if(mWTListenersMap)
+        mWTListenersMap->notifyWaterTemperature(mWTListenerWait);
 }

  在水温达到client的期望值后,就直接回调client的接口实现,紧接着client就会收到通知并开始做它自己感兴趣的事情了。

7.serviceModelClient 支持使用电热水壶功能

7.1 IWaterTemperatureListener的实现

+class MyWaterTemperatureListener : public IWaterTemperatureListener{
+public:
+       ::android::hardware::Return<bool>
+               notifyWaterTemperature(int8_t curWaterTemperature) override{
+                       LOG(ERROR)<<__func__<<":[curWaterTemperature]"<<std::to_string(curWaterTemperature);
+                       return true;
+       }
+};

  接口类的实现,此处只进行log的打印。

7.2 注册及开启电热水壶加热功能

 int main(int /* argc */, char** /* argv */) {
     ...
+       sp<MyWaterTemperatureListener> l = new MyWaterTemperatureListener();
+       mService->registerWaterTemperatureListener(5, l)
+       mService->enableHardware(true).isOk()

  HIDL service的电热水壶在client中的调用序列如下
   a)实例化我们对接口类IWaterTemperatureListener的实现。
   b)向HIDL service注册接口类实现。
   c)是能HIDL service的电热水壶功能。

8.电热水壶的运行

generic_x86_64:/ # /vendor/bin/hw/serviceModelClient
//HIDL service tid为2071,此时client调用了接口registerWaterTemperatureListener,注册温度为5s
02-15 22:09:29.413  2070  2071 E flagstaff.hardware.custom_hardware: registerWaterTemperatureListener:[waterTemperature]5
//client 调用了enableHardware,开启电热水壶。所以HIDL service启动线程(tid:2073)模拟加热
02-15 22:09:29.414  2070  2073 E flagstaff.hardware.custom_hardware: start one thread to simulate making boil water.[mWTListenerWait]5
//HIDL service发现水温达到了client的预设水温,从而准备回调client
02-15 22:09:33.415  2070  2073 E flagstaff.hardware.custom_hardware: notifyTemperatureDone
//client线程,pid为2072
02-15 22:09:33.415  2072  2072 E serviceModelClient: notifyWaterTemperature:[curWaterTemperature]5

9.源码

module source code

https://gitee.com/solo-king/android-rhidl-about/compare/664f06ea7456f093261425980a8d1565db87efd0...527add63b05a34f3c5fc21a8f5097965742885cc

  另外如果有问题,欢迎留言或者email([email protected])我,技术升级在于交流~~

你可能感兴趣的:(android,观察者模式,framework,hardware,cpp)