1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef HIDL_CALLBACK_UTIL_H_
18 #define HIDL_CALLBACK_UTIL_H_
19 
20 #include <set>
21 
22 #include <hidl/HidlSupport.h>
23 
24 namespace {
25 // Type of callback invoked by the death handler.
26 using on_death_cb_function = std::function<void(uint64_t)>;
27 
28 // Private class used to keep track of death of individual
29 // callbacks stored in HidlCallbackHandler.
30 template <typename CallbackType>
31 class HidlDeathHandler : public android::hardware::hidl_death_recipient {
32  public:
HidlDeathHandler(const on_death_cb_function & user_cb_function)33   HidlDeathHandler(const on_death_cb_function& user_cb_function)
34       : cb_function_(user_cb_function) {}
35   ~HidlDeathHandler() = default;
36 
37   // Death notification for callbacks.
serviceDied(uint64_t cookie,const android::wp<android::hidl::base::V1_0::IBase> &)38   void serviceDied(
39       uint64_t cookie,
40       const android::wp<android::hidl::base::V1_0::IBase>& /* who */) override {
41     cb_function_(cookie);
42   }
43 
44  private:
45   on_death_cb_function cb_function_;
46 
47   DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
48 };
49 }  // namespace
50 
51 namespace android {
52 namespace hardware {
53 namespace wifi {
54 namespace V1_0 {
55 namespace implementation {
56 namespace hidl_callback_util {
57 template <typename CallbackType>
58 // Provides a class to manage callbacks for the various HIDL interfaces and
59 // handle the death of the process hosting each callback.
60 class HidlCallbackHandler {
61  public:
HidlCallbackHandler()62   HidlCallbackHandler()
63       : death_handler_(new HidlDeathHandler<CallbackType>(
64             std::bind(&HidlCallbackHandler::onObjectDeath,
65                       this,
66                       std::placeholders::_1))) {}
67   ~HidlCallbackHandler() = default;
68 
addCallback(const sp<CallbackType> & cb)69   bool addCallback(const sp<CallbackType>& cb) {
70     // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
71     // (callback proxy's raw pointer) to track the death of individual clients.
72     uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
73     if (cb_set_.find(cb) != cb_set_.end()) {
74       LOG(WARNING) << "Duplicate death notification registration";
75       return true;
76     }
77     if (!cb->linkToDeath(death_handler_, cookie)) {
78       LOG(ERROR) << "Failed to register death notification";
79       return false;
80     }
81     cb_set_.insert(cb);
82     return true;
83   }
84 
getCallbacks()85   const std::set<android::sp<CallbackType>>& getCallbacks() { return cb_set_; }
86 
87   // Death notification for callbacks.
onObjectDeath(uint64_t cookie)88   void onObjectDeath(uint64_t cookie) {
89     CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
90     const auto& iter = cb_set_.find(cb);
91     if (iter == cb_set_.end()) {
92       LOG(ERROR) << "Unknown callback death notification received";
93       return;
94     }
95     cb_set_.erase(iter);
96     LOG(DEBUG) << "Dead callback removed from list";
97   }
98 
invalidate()99   void invalidate() {
100     for (const sp<CallbackType>& cb : cb_set_) {
101       if (!cb->unlinkToDeath(death_handler_)) {
102         LOG(ERROR) << "Failed to deregister death notification";
103       }
104     }
105     cb_set_.clear();
106   }
107 
108  private:
109   std::set<sp<CallbackType>> cb_set_;
110   sp<HidlDeathHandler<CallbackType>> death_handler_;
111 
112   DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
113 };
114 
115 }  // namespace hidl_callback_util
116 }  // namespace implementation
117 }  // namespace V1_0
118 }  // namespace wifi
119 }  // namespace hardware
120 }  // namespace android
121 #endif  // HIDL_CALLBACK_UTIL_H_
122