blob: baf01127bc0d13ada0382f8d40b46b9fbf85985c [file] [log] [blame]
/*
* Copyright (C) 2018 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 ANDROID_CAMERA_HYBRIDINTERFACE_H
#define ANDROID_CAMERA_HYBRIDINTERFACE_H
#include <vector>
#include <mutex>
#include <binder/Parcel.h>
#include <hidl/HidlSupport.h>
namespace android {
namespace camerahybrid {
typedef ::android::hidl::base::V1_0::IBase HInterface;
template <
typename HINTERFACE,
typename INTERFACE,
typename BNINTERFACE >
class H2BConverter : public BNINTERFACE {
public:
typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE> CBase; // Converter Base
typedef INTERFACE BaseInterface;
typedef HINTERFACE HalInterface;
H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
virtual sp<HalInterface> getHalInterface() { return mBase; }
virtual status_t linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath(
const wp<IBinder::DeathRecipient>& recipient,
void* cookie = nullptr,
uint32_t flags = 0,
wp<IBinder::DeathRecipient>* outRecipient = nullptr);
protected:
sp<HalInterface> mBase;
struct Obituary : public hardware::hidl_death_recipient {
wp<IBinder::DeathRecipient> recipient;
void* cookie;
uint32_t flags;
wp<IBinder> who;
Obituary(
const wp<IBinder::DeathRecipient>& r,
void* c, uint32_t f,
const wp<IBinder>& w) :
recipient(r), cookie(c), flags(f), who(w) {
}
Obituary(const Obituary& o) :
recipient(o.recipient),
cookie(o.cookie),
flags(o.flags),
who(o.who) {
}
Obituary& operator=(const Obituary& o) {
recipient = o.recipient;
cookie = o.cookie;
flags = o.flags;
who = o.who;
return *this;
}
void serviceDied(uint64_t, const wp<HInterface>&) override {
sp<IBinder::DeathRecipient> dr = recipient.promote();
if (dr != nullptr) {
dr->binderDied(who);
}
}
};
std::mutex mObituariesLock;
std::vector<sp<Obituary> > mObituaries;
};
template <
typename HINTERFACE,
typename INTERFACE,
typename BNINTERFACE>
status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE>::
linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-nullptr");
{
std::lock_guard<std::mutex> lock(mObituariesLock);
mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
if (!mBase->linkToDeath(mObituaries.back(), 0)) {
return DEAD_OBJECT;
}
}
return NO_ERROR;
}
template <
typename HINTERFACE,
typename INTERFACE,
typename BNINTERFACE>
status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE>::
unlinkToDeath(
const wp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags,
wp<IBinder::DeathRecipient>* outRecipient) {
std::lock_guard<std::mutex> lock(mObituariesLock);
for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) {
if ((flags = (*i)->flags) && (
(recipient == (*i)->recipient) ||
((recipient == nullptr) && (cookie == (*i)->cookie)))) {
if (outRecipient != nullptr) {
*outRecipient = (*i)->recipient;
}
bool success = mBase->unlinkToDeath(*i);
mObituaries.erase(i);
return success ? NO_ERROR : DEAD_OBJECT;
}
}
return NAME_NOT_FOUND;
}
} // namespace camerahybrid
} // namespace android
#endif // ANDROID_CAMERA_HYBRIDINTERFACE_H