当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。通俗的举个例子,以前没有电热水器的时候,我们需要将水壶放到炉灶上加热,并且守在旁边或者隔一段时间主动的来查看水壶中的水是否被烧开,如果烧开了就停止加热,反之则继续等待。但是现在我们有了电热水壶,此时我们可以给电热水壶设置一个指定的温度,让其达到这个温度时发出铃声来主动通知我。这里的设定温度(观察者注册listener)以及电热水壶的主动通知(通过注册的listener回调通知观察者)就类似观察者模式的运作。Observer Pattern的关系图大致如下
下面就让我们自定的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此时的水温,实际上也就是当时注册时的温度。
@@ -6,6 +6,7 @@ hidl_interface {
system_ext_specific: true,
srcs: [
"ICustomHardware.hal",
+ "IWaterTemperatureListener.hal",
],
interfaces: [
"[email protected]",
IWaterTemperatureListener.hal实际上和cpp/java等后缀源码在概念上是一样的,也就是HIDL 框架中的源代码,故新添加一个文件需要在Makefile中指出。
+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的实现。
@@ -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是否正确处理该通知。
+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注册的接口类的实现。
+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就会收到通知并开始做它自己感兴趣的事情了。
+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的打印。
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的电热水壶功能。
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
module source code
https://gitee.com/solo-king/android-rhidl-about/compare/664f06ea7456f093261425980a8d1565db87efd0...527add63b05a34f3c5fc21a8f5097965742885cc
另外如果有问题,欢迎留言或者email([email protected])我,技术升级在于交流~~