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