• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <hidl/HidlTransportSupport.h>
24 
25 namespace {
26 // Type of callback invoked by the death handler.
27 using on_death_cb_function = std::function<void(uint64_t)>;
28 
29 // Private class used to keep track of death of individual
30 // callbacks stored in HidlCallbackHandler.
31 template <typename CallbackType>
32 class HidlDeathHandler : public android::hardware::hidl_death_recipient {
33   public:
HidlDeathHandler(const on_death_cb_function & user_cb_function)34     HidlDeathHandler(const on_death_cb_function& user_cb_function)
35         : cb_function_(user_cb_function) {}
36     ~HidlDeathHandler() = default;
37 
38     // Death notification for callbacks.
serviceDied(uint64_t cookie,const android::wp<android::hidl::base::V1_0::IBase> &)39     void serviceDied(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_6 {
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, this, std::placeholders::_1))) {}
65     ~HidlCallbackHandler() = default;
66 
addCallback(const sp<CallbackType> & cb)67     bool addCallback(const sp<CallbackType>& cb) {
68         // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
69         // (callback proxy's raw pointer) to track the death of individual
70         // clients.
71         uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
72         for (const auto& s : cb_set_) {
73             if (interfacesEqual(cb, s)) {
74                 LOG(ERROR) << "Duplicate death notification registration";
75                 return true;
76             }
77         }
78         if (!cb->linkToDeath(death_handler_, cookie)) {
79             LOG(ERROR) << "Failed to register death notification";
80             return false;
81         }
82         cb_set_.insert(cb);
83         return true;
84     }
85 
getCallbacks()86     const std::set<android::sp<CallbackType>>& getCallbacks() { return cb_set_; }
87 
88     // Death notification for callbacks.
onObjectDeath(uint64_t cookie)89     void onObjectDeath(uint64_t cookie) {
90         CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
91         const auto& iter = cb_set_.find(cb);
92         if (iter == cb_set_.end()) {
93             LOG(ERROR) << "Unknown callback death notification received";
94             return;
95         }
96         cb_set_.erase(iter);
97         LOG(DEBUG) << "Dead callback removed from list";
98     }
99 
invalidate()100     void invalidate() {
101         for (const sp<CallbackType>& cb : cb_set_) {
102             if (!cb->unlinkToDeath(death_handler_)) {
103                 LOG(ERROR) << "Failed to deregister death notification";
104             }
105         }
106         cb_set_.clear();
107     }
108 
109   private:
110     std::set<sp<CallbackType>> cb_set_;
111     sp<HidlDeathHandler<CallbackType>> death_handler_;
112 
113     DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
114 };
115 
116 }  // namespace hidl_callback_util
117 }  // namespace implementation
118 }  // namespace V1_6
119 }  // namespace wifi
120 }  // namespace hardware
121 }  // namespace android
122 #endif  // HIDL_CALLBACK_UTIL_H_
123