1 /*
2  * Copyright (C) 2018 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 ANDROID_CAMERA_HYBRIDINTERFACE_H
18 #define ANDROID_CAMERA_HYBRIDINTERFACE_H
19 
20 #include <vector>
21 #include <mutex>
22 
23 #include <binder/Parcel.h>
24 #include <hidl/HidlSupport.h>
25 
26 namespace android {
27 namespace camerahybrid {
28 typedef ::android::hidl::base::V1_0::IBase HInterface;
29 
30 template <
31         typename HINTERFACE,
32         typename INTERFACE,
33         typename BNINTERFACE >
34 class H2BConverter : public BNINTERFACE {
35 public:
36     typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE> CBase; // Converter Base
37     typedef INTERFACE BaseInterface;
38     typedef HINTERFACE HalInterface;
39 
H2BConverter(const sp<HalInterface> & base)40     H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
getHalInterface()41     virtual sp<HalInterface> getHalInterface() { return mBase; }
42     virtual status_t linkToDeath(
43             const sp<IBinder::DeathRecipient>& recipient,
44             void* cookie = nullptr,
45             uint32_t flags = 0);
46     virtual status_t unlinkToDeath(
47             const wp<IBinder::DeathRecipient>& recipient,
48             void* cookie = nullptr,
49             uint32_t flags = 0,
50             wp<IBinder::DeathRecipient>* outRecipient = nullptr);
51 
52 protected:
53     sp<HalInterface> mBase;
54     struct Obituary : public hardware::hidl_death_recipient {
55         wp<IBinder::DeathRecipient> recipient;
56         void* cookie;
57         uint32_t flags;
58         wp<IBinder> who;
ObituaryObituary59         Obituary(
60                 const wp<IBinder::DeathRecipient>& r,
61                 void* c, uint32_t f,
62                 const wp<IBinder>& w) :
63             recipient(r), cookie(c), flags(f), who(w) {
64         }
ObituaryObituary65         Obituary(const Obituary& o) :
66             recipient(o.recipient),
67             cookie(o.cookie),
68             flags(o.flags),
69             who(o.who) {
70         }
71         Obituary& operator=(const Obituary& o) {
72             recipient = o.recipient;
73             cookie = o.cookie;
74             flags = o.flags;
75             who = o.who;
76             return *this;
77         }
serviceDiedObituary78         void serviceDied(uint64_t, const wp<HInterface>&) override {
79             sp<IBinder::DeathRecipient> dr = recipient.promote();
80             if (dr != nullptr) {
81                 dr->binderDied(who);
82             }
83         }
84     };
85     std::mutex mObituariesLock;
86     std::vector<sp<Obituary> > mObituaries;
87 };
88 
89 template <
90         typename HINTERFACE,
91         typename INTERFACE,
92         typename BNINTERFACE>
93 status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE>::
linkToDeath(const sp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags)94         linkToDeath(
95         const sp<IBinder::DeathRecipient>& recipient,
96         void* cookie, uint32_t flags) {
97     LOG_ALWAYS_FATAL_IF(recipient == nullptr,
98             "linkToDeath(): recipient must be non-nullptr");
99     {
100         std::lock_guard<std::mutex> lock(mObituariesLock);
101         mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
102         if (!mBase->linkToDeath(mObituaries.back(), 0)) {
103            return DEAD_OBJECT;
104         }
105     }
106     return NO_ERROR;
107 }
108 
109 template <
110         typename HINTERFACE,
111         typename INTERFACE,
112         typename BNINTERFACE>
113 status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE>::
unlinkToDeath(const wp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags,wp<IBinder::DeathRecipient> * outRecipient)114         unlinkToDeath(
115         const wp<IBinder::DeathRecipient>& recipient,
116         void* cookie, uint32_t flags,
117         wp<IBinder::DeathRecipient>* outRecipient) {
118     std::lock_guard<std::mutex> lock(mObituariesLock);
119     for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) {
120         if ((flags = (*i)->flags) && (
121                 (recipient == (*i)->recipient) ||
122                 ((recipient == nullptr) && (cookie == (*i)->cookie)))) {
123             if (outRecipient != nullptr) {
124                 *outRecipient = (*i)->recipient;
125             }
126             bool success = mBase->unlinkToDeath(*i);
127             mObituaries.erase(i);
128             return success ? NO_ERROR : DEAD_OBJECT;
129         }
130     }
131     return NAME_NOT_FOUND;
132 }
133 
134 } // namespace camerahybrid
135 } // namespace android
136 
137 #endif // ANDROID_CAMERA_HYBRIDINTERFACE_H
138 
139