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 24namespace { 25// Type of callback invoked by the death handler. 26using 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. 30template <typename CallbackType> 31class HidlDeathHandler : public android::hardware::hidl_death_recipient { 32 public: 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. 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 52namespace android { 53namespace hardware { 54namespace wifi { 55namespace V1_2 { 56namespace implementation { 57namespace hidl_callback_util { 58template <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. 61class HidlCallbackHandler { 62 public: 63 HidlCallbackHandler() 64 : death_handler_(new HidlDeathHandler<CallbackType>( 65 std::bind(&HidlCallbackHandler::onObjectDeath, this, 66 std::placeholders::_1))) {} 67 ~HidlCallbackHandler() = default; 68 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 86 const std::set<android::sp<CallbackType>>& getCallbacks() { 87 return cb_set_; 88 } 89 90 // Death notification for callbacks. 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 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_2 121} // namespace wifi 122} // namespace hardware 123} // namespace android 124#endif // HIDL_CALLBACK_UTIL_H_ 125