blob: a6d2dbb60c2b2921be2206a2120149cfd11ed95c [file] [log] [blame]
#include "consumer_channel.h"
#include <log/log.h>
#include <utils/Trace.h>
#include <thread>
#include <private/dvr/bufferhub_rpc.h>
#include "producer_channel.h"
using android::pdx::BorrowedHandle;
using android::pdx::Channel;
using android::pdx::ErrorStatus;
using android::pdx::Message;
using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
namespace dvr {
ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id,
int channel_id, uint64_t consumer_state_bit,
const std::shared_ptr<Channel> producer)
: BufferHubChannel(service, buffer_id, channel_id, kConsumerType),
consumer_state_bit_(consumer_state_bit),
producer_(producer) {
GetProducer()->AddConsumer(this);
}
ConsumerChannel::~ConsumerChannel() {
ALOGD_IF(TRACE,
"ConsumerChannel::~ConsumerChannel: channel_id=%d buffer_id=%d",
channel_id(), buffer_id());
if (auto producer = GetProducer()) {
producer->RemoveConsumer(this);
}
}
BufferHubChannel::BufferInfo ConsumerChannel::GetBufferInfo() const {
BufferHubChannel::BufferInfo info;
if (auto producer = GetProducer()) {
// If producer has not hung up, copy most buffer info from the producer.
info = producer->GetBufferInfo();
} else {
info.signaled_mask = consumer_state_bit();
}
info.id = buffer_id();
return info;
}
std::shared_ptr<ProducerChannel> ConsumerChannel::GetProducer() const {
return std::static_pointer_cast<ProducerChannel>(producer_.lock());
}
void ConsumerChannel::HandleImpulse(Message& message) {
ATRACE_NAME("ConsumerChannel::HandleImpulse");
switch (message.GetOp()) {
case BufferHubRPC::ConsumerAcquire::Opcode:
OnConsumerAcquire(message);
break;
case BufferHubRPC::ConsumerRelease::Opcode:
OnConsumerRelease(message, {});
break;
}
}
bool ConsumerChannel::HandleMessage(Message& message) {
ATRACE_NAME("ConsumerChannel::HandleMessage");
auto producer = GetProducer();
if (!producer)
REPLY_ERROR_RETURN(message, EPIPE, true);
switch (message.GetOp()) {
case BufferHubRPC::GetBuffer::Opcode:
DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
*this, &ConsumerChannel::OnGetBuffer, message);
return true;
case BufferHubRPC::NewConsumer::Opcode:
DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
*producer, &ProducerChannel::OnNewConsumer, message);
return true;
case BufferHubRPC::ConsumerAcquire::Opcode:
DispatchRemoteMethod<BufferHubRPC::ConsumerAcquire>(
*this, &ConsumerChannel::OnConsumerAcquire, message);
return true;
case BufferHubRPC::ConsumerRelease::Opcode:
DispatchRemoteMethod<BufferHubRPC::ConsumerRelease>(
*this, &ConsumerChannel::OnConsumerRelease, message);
return true;
case BufferHubRPC::ConsumerSetIgnore::Opcode:
DispatchRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(
*this, &ConsumerChannel::OnConsumerSetIgnore, message);
return true;
default:
return false;
}
}
Status<BufferDescription<BorrowedHandle>> ConsumerChannel::OnGetBuffer(
Message& /*message*/) {
ATRACE_NAME("ConsumerChannel::OnGetBuffer");
ALOGD_IF(TRACE, "ConsumerChannel::OnGetBuffer: buffer=%d", buffer_id());
if (auto producer = GetProducer()) {
return {producer->GetBuffer(consumer_state_bit_)};
} else {
return ErrorStatus(EPIPE);
}
}
Status<LocalFence> ConsumerChannel::OnConsumerAcquire(Message& message) {
ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
auto producer = GetProducer();
if (!producer)
return ErrorStatus(EPIPE);
if (acquired_ || released_) {
ALOGE(
"ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
"ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
ignored_, acquired_, released_, message.GetChannelId(),
producer->buffer_id());
return ErrorStatus(EBUSY);
} else {
auto status = producer->OnConsumerAcquire(message);
if (status) {
ClearAvailable();
acquired_ = true;
}
return status;
}
}
Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
LocalFence release_fence) {
ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
auto producer = GetProducer();
if (!producer)
return ErrorStatus(EPIPE);
if (!acquired_ || released_) {
ALOGE(
"ConsumerChannel::OnConsumerRelease: Release when not acquired: "
"ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
ignored_, acquired_, released_, message.GetChannelId(),
producer->buffer_id());
return ErrorStatus(EBUSY);
} else {
auto status =
producer->OnConsumerRelease(message, std::move(release_fence));
if (status) {
ClearAvailable();
acquired_ = false;
released_ = true;
}
return status;
}
}
Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
auto producer = GetProducer();
if (!producer)
return ErrorStatus(EPIPE);
ignored_ = ignored;
if (ignored_ && acquired_) {
// Update the producer if ignore is set after the consumer acquires the
// buffer.
ClearAvailable();
producer->OnConsumerIgnored();
acquired_ = false;
released_ = true;
}
return {};
}
bool ConsumerChannel::OnProducerPosted() {
if (ignored_) {
acquired_ = false;
released_ = true;
return false;
} else {
acquired_ = false;
released_ = false;
SignalAvailable();
return true;
}
}
void ConsumerChannel::OnProducerClosed() {
producer_.reset();
Hangup();
}
} // namespace dvr
} // namespace android