1d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius/* 2d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * Copyright (C) 2017 The Android Open Source Project 3d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * 4d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * Licensed under the Apache License, Version 2.0 (the "License"); 5d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * you may not use this file except in compliance with the License. 6d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * You may obtain a copy of the License at 7d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * 8d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * http://www.apache.org/licenses/LICENSE-2.0 9d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * 10d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * Unless required by applicable law or agreed to in writing, software 11d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * distributed under the License is distributed on an "AS IS" BASIS, 12d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * See the License for the specific language governing permissions and 14d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius * limitations under the License. 15d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius */ 16d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 17d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius#ifndef HIDL_CALLBACK_UTIL_H_ 18d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius#define HIDL_CALLBACK_UTIL_H_ 19d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 20d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius#include <set> 21d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 22d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius#include <hidl/HidlSupport.h> 23d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 24d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace { 25d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius// Type of callback invoked by the death handler. 26d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piususing on_death_cb_function = std::function<void(uint64_t)>; 27d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 28d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius// Private class used to keep track of death of individual 29d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius// callbacks stored in HidlCallbackHandler. 30d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piustemplate <typename CallbackType> 31d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusclass HidlDeathHandler : public android::hardware::hidl_death_recipient { 32abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius public: 33abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius HidlDeathHandler(const on_death_cb_function& user_cb_function) 34abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius : cb_function_(user_cb_function) {} 35abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius ~HidlDeathHandler() = default; 36abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 37abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius // Death notification for callbacks. 38abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius void serviceDied( 39abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius uint64_t cookie, 40abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius const android::wp<android::hidl::base::V1_0::IBase>& /* who */) 41abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius override { 42abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius cb_function_(cookie); 43abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 44abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 45abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius private: 46abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius on_death_cb_function cb_function_; 47abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 48abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler); 49d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius}; 50d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace 51d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 52d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace android { 53d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace hardware { 54d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace wifi { 556ce509085453637ddd3d0a1a88a26fed18072167Etan Cohennamespace V1_2 { 56d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace implementation { 57d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusnamespace hidl_callback_util { 58d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piustemplate <typename CallbackType> 59d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius// Provides a class to manage callbacks for the various HIDL interfaces and 60d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius// handle the death of the process hosting each callback. 61d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Piusclass HidlCallbackHandler { 62abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius public: 63abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius HidlCallbackHandler() 64abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius : death_handler_(new HidlDeathHandler<CallbackType>( 65abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius std::bind(&HidlCallbackHandler::onObjectDeath, this, 66abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius std::placeholders::_1))) {} 67abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius ~HidlCallbackHandler() = default; 68abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 69abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius bool addCallback(const sp<CallbackType>& cb) { 70abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius // TODO(b/33818800): Can't compare proxies yet. So, use the cookie 71abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius // (callback proxy's raw pointer) to track the death of individual 72abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius // clients. 73abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius uint64_t cookie = reinterpret_cast<uint64_t>(cb.get()); 74abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius if (cb_set_.find(cb) != cb_set_.end()) { 75abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius LOG(WARNING) << "Duplicate death notification registration"; 76abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius return true; 77abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 78abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius if (!cb->linkToDeath(death_handler_, cookie)) { 79abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius LOG(ERROR) << "Failed to register death notification"; 80abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius return false; 81abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 82abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius cb_set_.insert(cb); 83abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius return true; 84d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius } 85abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 86abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius const std::set<android::sp<CallbackType>>& getCallbacks() { 87abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius return cb_set_; 88d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius } 89abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 90abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius // Death notification for callbacks. 91abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius void onObjectDeath(uint64_t cookie) { 92abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius CallbackType* cb = reinterpret_cast<CallbackType*>(cookie); 93abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius const auto& iter = cb_set_.find(cb); 94abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius if (iter == cb_set_.end()) { 95abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius LOG(ERROR) << "Unknown callback death notification received"; 96abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius return; 97abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 98abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius cb_set_.erase(iter); 99abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius LOG(DEBUG) << "Dead callback removed from list"; 100d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius } 101abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius 102abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius void invalidate() { 103abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius for (const sp<CallbackType>& cb : cb_set_) { 104abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius if (!cb->unlinkToDeath(death_handler_)) { 105abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius LOG(ERROR) << "Failed to deregister death notification"; 106abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 107abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius } 108abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius cb_set_.clear(); 109d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius } 110d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 111abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius private: 112abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius std::set<sp<CallbackType>> cb_set_; 113abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius sp<HidlDeathHandler<CallbackType>> death_handler_; 114d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 115abcf78fe9056edb405db4f8f00bf7e6cd6700621Roshan Pius DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); 116d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius}; 117d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius 118d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace hidl_callback_util 119d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace implementation 1206ce509085453637ddd3d0a1a88a26fed18072167Etan Cohen} // namespace V1_2 121d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace wifi 122d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace hardware 123d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius} // namespace android 124d37341f1e57b91a5f8bf6fe85b99861717720e5fRoshan Pius#endif // HIDL_CALLBACK_UTIL_H_ 125