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 */)
41         override {
42         cb_function_(cookie);
43     }
44 
45    private:
46     on_death_cb_function cb_function_;
47 
48     DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
49 };
50 }  // namespace
51 
52 namespace android {
53 namespace hardware {
54 namespace wifi {
55 namespace V1_4 {
56 namespace implementation {
57 namespace hidl_callback_util {
58 template <typename CallbackType>
59 // Provides a class to manage callbacks for the various HIDL interfaces and
60 // handle the death of the process hosting each callback.
61 class HidlCallbackHandler {
62    public:
HidlCallbackHandler()63     HidlCallbackHandler()
64         : death_handler_(new HidlDeathHandler<CallbackType>(
65               std::bind(&HidlCallbackHandler::onObjectDeath, 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
72         // clients.
73         uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
74         if (cb_set_.find(cb) != cb_set_.end()) {
75             LOG(WARNING) << "Duplicate death notification registration";
76             return true;
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() {
87         return cb_set_;
88     }
89 
90     // Death notification for callbacks.
onObjectDeath(uint64_t cookie)91     void onObjectDeath(uint64_t cookie) {
92         CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
93         const auto& iter = cb_set_.find(cb);
94         if (iter == cb_set_.end()) {
95             LOG(ERROR) << "Unknown callback death notification received";
96             return;
97         }
98         cb_set_.erase(iter);
99         LOG(DEBUG) << "Dead callback removed from list";
100     }
101 
invalidate()102     void invalidate() {
103         for (const sp<CallbackType>& cb : cb_set_) {
104             if (!cb->unlinkToDeath(death_handler_)) {
105                 LOG(ERROR) << "Failed to deregister death notification";
106             }
107         }
108         cb_set_.clear();
109     }
110 
111    private:
112     std::set<sp<CallbackType>> cb_set_;
113     sp<HidlDeathHandler<CallbackType>> death_handler_;
114 
115     DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
116 };
117 
118 }  // namespace hidl_callback_util
119 }  // namespace implementation
120 }  // namespace V1_4
121 }  // namespace wifi
122 }  // namespace hardware
123 }  // namespace android
124 #endif  // HIDL_CALLBACK_UTIL_H_
125