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