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