consumer_channel.cpp revision 4d3590f3fd0fd65f4e8758d3228de9f55cf135d0
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "consumer_channel.h"
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include <log/log.h>
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <utils/Trace.h>
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include <thread>
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <private/dvr/bufferhub_rpc.h>
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "producer_channel.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::ErrorStatus;
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::BorrowedHandle;
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::Channel;
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::Message;
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::Status;
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing android::pdx::rpc::DispatchRemoteMethod;
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comnamespace android {
1961a237e319a63b7ed6d38c2f3cd9b597816c3a46fmalitanamespace dvr {
2061a237e319a63b7ed6d38c2f3cd9b597816c3a46fmalita
214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id,
224e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                 int channel_id,
234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                 const std::shared_ptr<Channel> producer)
244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    : BufferHubChannel(service, buffer_id, channel_id, kConsumerType),
254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com      handled_(true),
264200dfe9c1a2c0e99a7155a63fbffb01e9d1fd28bungeman@google.com      ignored_(false),
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      producer_(producer) {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  GetProducer()->AddConsumer(this);
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comConsumerChannel::~ConsumerChannel() {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ALOGD_IF(TRACE,
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           "ConsumerChannel::~ConsumerChannel: channel_id=%d buffer_id=%d",
34f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org           channel_id(), buffer_id());
3546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (auto producer = GetProducer()) {
37a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    if (!handled_)  // Producer is waiting for our Release.
38971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com      producer->OnConsumerIgnored();
39a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    producer->RemoveConsumer(this);
40971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com  }
41a9baa652bb329b5a286e1638938f63433701efcakkinnunen}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comBufferHubChannel::BufferInfo ConsumerChannel::GetBufferInfo() const {
444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com  BufferHubChannel::BufferInfo info;
454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com  if (auto producer = GetProducer()) {
46971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com    // If producer has not hung up, copy most buffer info from the producer.
47971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com    info = producer->GetBufferInfo();
484e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com  }
49971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com  info.id = buffer_id();
5015e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com  return info;
5115e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com}
5215e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstd::shared_ptr<ProducerChannel> ConsumerChannel::GetProducer() const {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  return std::static_pointer_cast<ProducerChannel>(producer_.lock());
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
56
57void ConsumerChannel::HandleImpulse(Message& message) {
58  ATRACE_NAME("ConsumerChannel::HandleImpulse");
59  switch (message.GetOp()) {
60    case BufferHubRPC::ConsumerRelease::Opcode:
61      OnConsumerRelease(message, {});
62      break;
63  }
64}
65
66bool ConsumerChannel::HandleMessage(Message& message) {
67  ATRACE_NAME("ConsumerChannel::HandleMessage");
68  auto producer = GetProducer();
69  if (!producer)
70    REPLY_ERROR_RETURN(message, EPIPE, true);
71
72  switch (message.GetOp()) {
73    case BufferHubRPC::GetBuffer::Opcode:
74      DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
75          *producer, &ProducerChannel::OnGetBuffer, message);
76      return true;
77
78    case BufferHubRPC::NewConsumer::Opcode:
79      DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
80          *producer, &ProducerChannel::OnNewConsumer, message);
81      return true;
82
83    case BufferHubRPC::ConsumerAcquire::Opcode:
84      DispatchRemoteMethod<BufferHubRPC::ConsumerAcquire>(
85          *this, &ConsumerChannel::OnConsumerAcquire, message);
86      return true;
87
88    case BufferHubRPC::ConsumerRelease::Opcode:
89      DispatchRemoteMethod<BufferHubRPC::ConsumerRelease>(
90          *this, &ConsumerChannel::OnConsumerRelease, message);
91      return true;
92
93    case BufferHubRPC::ConsumerSetIgnore::Opcode:
94      DispatchRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(
95          *this, &ConsumerChannel::OnConsumerSetIgnore, message);
96      return true;
97
98    default:
99      return false;
100  }
101}
102
103Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
104ConsumerChannel::OnConsumerAcquire(Message& message,
105                                   std::size_t metadata_size) {
106  ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
107  auto producer = GetProducer();
108  if (!producer)
109    return ErrorStatus(EPIPE);
110
111  if (ignored_ || handled_) {
112    ALOGE(
113        "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
114        "ignored=%d handled=%d channel_id=%d buffer_id=%d",
115        ignored_, handled_, message.GetChannelId(), producer->buffer_id());
116    return ErrorStatus(EBUSY);
117  } else {
118    ClearAvailable();
119    return producer->OnConsumerAcquire(message, metadata_size);
120  }
121}
122
123Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
124                                                LocalFence release_fence) {
125  ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
126  auto producer = GetProducer();
127  if (!producer)
128    return ErrorStatus(EPIPE);
129
130  if (ignored_ || handled_) {
131    ALOGE(
132        "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
133        "ignored=%d handled=%d channel_id=%d buffer_id=%d",
134        ignored_, handled_, message.GetChannelId(), producer->buffer_id());
135    return ErrorStatus(EBUSY);
136  } else {
137    ClearAvailable();
138    auto status =
139        producer->OnConsumerRelease(message, std::move(release_fence));
140    handled_ = !!status;
141    return status;
142  }
143}
144
145Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
146  ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
147  auto producer = GetProducer();
148  if (!producer)
149    return ErrorStatus(EPIPE);
150
151  ignored_ = ignored;
152  if (ignored_ && !handled_) {
153    // Update the producer if ignore is set after the consumer acquires the
154    // buffer.
155    ClearAvailable();
156    producer->OnConsumerIgnored();
157    handled_ = false;
158  }
159
160  return {};
161}
162
163bool ConsumerChannel::OnProducerPosted() {
164  if (ignored_) {
165    handled_ = true;
166    return false;
167  } else {
168    handled_ = false;
169    SignalAvailable();
170    return true;
171  }
172}
173
174void ConsumerChannel::OnProducerClosed() {
175  producer_.reset();
176  Hangup();
177}
178
179}  // namespace dvr
180}  // namespace android
181