/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HIDL_CALLBACK_UTIL_H_ #define HIDL_CALLBACK_UTIL_H_ #include #include namespace { // Type of callback invoked by the death handler. using on_death_cb_function = std::function; // Private class used to keep track of death of individual // callbacks stored in HidlCallbackHandler. template class HidlDeathHandler : public android::hardware::hidl_death_recipient { public: HidlDeathHandler(const on_death_cb_function& user_cb_function) : cb_function_(user_cb_function) {} ~HidlDeathHandler() = default; // Death notification for callbacks. void serviceDied( uint64_t cookie, const android::wp& /* who */) override { cb_function_(cookie); } private: on_death_cb_function cb_function_; DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler); }; } // namespace namespace android { namespace hardware { namespace wifi { namespace V1_2 { namespace implementation { namespace hidl_callback_util { template // Provides a class to manage callbacks for the various HIDL interfaces and // handle the death of the process hosting each callback. class HidlCallbackHandler { public: HidlCallbackHandler() : death_handler_(new HidlDeathHandler( std::bind(&HidlCallbackHandler::onObjectDeath, this, std::placeholders::_1))) {} ~HidlCallbackHandler() = default; bool addCallback(const sp& cb) { // TODO(b/33818800): Can't compare proxies yet. So, use the cookie // (callback proxy's raw pointer) to track the death of individual // clients. uint64_t cookie = reinterpret_cast(cb.get()); if (cb_set_.find(cb) != cb_set_.end()) { LOG(WARNING) << "Duplicate death notification registration"; return true; } if (!cb->linkToDeath(death_handler_, cookie)) { LOG(ERROR) << "Failed to register death notification"; return false; } cb_set_.insert(cb); return true; } const std::set>& getCallbacks() { return cb_set_; } // Death notification for callbacks. void onObjectDeath(uint64_t cookie) { CallbackType* cb = reinterpret_cast(cookie); const auto& iter = cb_set_.find(cb); if (iter == cb_set_.end()) { LOG(ERROR) << "Unknown callback death notification received"; return; } cb_set_.erase(iter); LOG(DEBUG) << "Dead callback removed from list"; } void invalidate() { for (const sp& cb : cb_set_) { if (!cb->unlinkToDeath(death_handler_)) { LOG(ERROR) << "Failed to deregister death notification"; } } cb_set_.clear(); } private: std::set> cb_set_; sp> death_handler_; DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); }; } // namespace hidl_callback_util } // namespace implementation } // namespace V1_2 } // namespace wifi } // namespace hardware } // namespace android #endif // HIDL_CALLBACK_UTIL_H_