blob: 8db92a3bfe8e05879cc994ed782b98ac068b082e [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "consumer_channel.h"
2
3#include <cutils/log.h>
4#include <utils/Trace.h>
5
6#include <thread>
7
8#include <private/dvr/bufferhub_rpc.h>
9#include "producer_channel.h"
10
11using android::pdx::BorrowedHandle;
12using android::pdx::Channel;
13using android::pdx::Message;
14using android::pdx::rpc::DispatchRemoteMethod;
15
16namespace android {
17namespace dvr {
18
19ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id,
20 int channel_id,
21 const std::shared_ptr<Channel> producer)
22 : BufferHubChannel(service, buffer_id, channel_id, kConsumerType),
23 handled_(true),
24 ignored_(false),
25 producer_(producer) {
26 GetProducer()->AddConsumer(this);
27}
28
29ConsumerChannel::~ConsumerChannel() {
30 ALOGD_IF(TRACE, "ConsumerChannel::~ConsumerChannel: channel_id=%d",
31 channel_id());
32
33 if (auto producer = GetProducer()) {
34 if (!handled_) // Producer is waiting for our Release.
35 producer->OnConsumerIgnored();
36 producer->RemoveConsumer(this);
37 }
38}
39
40BufferHubChannel::BufferInfo ConsumerChannel::GetBufferInfo() const {
41 BufferHubChannel::BufferInfo info;
42 if (auto producer = GetProducer()) {
43 // If producer has not hung up, copy most buffer info from the producer.
44 info = producer->GetBufferInfo();
45 }
46 info.id = buffer_id();
47 return info;
48}
49
50std::shared_ptr<ProducerChannel> ConsumerChannel::GetProducer() const {
51 return std::static_pointer_cast<ProducerChannel>(producer_.lock());
52}
53
54void ConsumerChannel::HandleImpulse(Message& message) {
55 ATRACE_NAME("ConsumerChannel::HandleImpulse");
56 switch (message.GetOp()) {
57 case BufferHubRPC::ConsumerRelease::Opcode:
58 OnConsumerRelease(message, {});
59 break;
60 }
61}
62
63bool ConsumerChannel::HandleMessage(Message& message) {
64 ATRACE_NAME("ConsumerChannel::HandleMessage");
65 auto producer = GetProducer();
66 if (!producer)
67 REPLY_ERROR_RETURN(message, EPIPE, true);
68
69 switch (message.GetOp()) {
70 case BufferHubRPC::GetBuffer::Opcode:
71 DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
72 *producer, &ProducerChannel::OnGetBuffer, message);
73 return true;
74
75 case BufferHubRPC::GetBuffers::Opcode:
76 DispatchRemoteMethod<BufferHubRPC::GetBuffers>(
77 *producer, &ProducerChannel::OnGetBuffers, message);
78 return true;
79
80 case BufferHubRPC::NewConsumer::Opcode:
81 DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
82 *producer, &ProducerChannel::OnNewConsumer, message);
83 return true;
84
85 case BufferHubRPC::ConsumerAcquire::Opcode:
86 DispatchRemoteMethod<BufferHubRPC::ConsumerAcquire>(
87 *this, &ConsumerChannel::OnConsumerAcquire, message);
88 return true;
89
90 case BufferHubRPC::ConsumerRelease::Opcode:
91 DispatchRemoteMethod<BufferHubRPC::ConsumerRelease>(
92 *this, &ConsumerChannel::OnConsumerRelease, message);
93 return true;
94
95 case BufferHubRPC::ConsumerSetIgnore::Opcode:
96 DispatchRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(
97 *this, &ConsumerChannel::OnConsumerSetIgnore, message);
98 return true;
99
100 default:
101 return false;
102 }
103}
104
105std::pair<BorrowedFence, ConsumerChannel::MetaData>
106ConsumerChannel::OnConsumerAcquire(Message& message,
107 std::size_t metadata_size) {
108 ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
109 auto producer = GetProducer();
110 if (!producer)
111 REPLY_ERROR_RETURN(message, EPIPE, {});
112
113 if (ignored_ || handled_) {
114 ALOGE(
115 "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
116 "ignored=%d handled=%d channel_id=%d buffer_id=%d",
117 ignored_, handled_, message.GetChannelId(), producer->buffer_id());
118 REPLY_ERROR_RETURN(message, EBUSY, {});
119 } else {
120 ClearAvailable();
121 return producer->OnConsumerAcquire(message, metadata_size);
122 }
123}
124
125int ConsumerChannel::OnConsumerRelease(Message& message,
126 LocalFence release_fence) {
127 ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
128 auto producer = GetProducer();
129 if (!producer)
130 return -EPIPE;
131
132 if (ignored_ || handled_) {
133 ALOGE(
134 "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
135 "ignored=%d handled=%d channel_id=%d buffer_id=%d",
136 ignored_, handled_, message.GetChannelId(), producer->buffer_id());
137 return -EBUSY;
138 } else {
139 ClearAvailable();
140 const int ret =
141 producer->OnConsumerRelease(message, std::move(release_fence));
142 handled_ = ret == 0;
143 return ret;
144 }
145}
146
147int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
148 ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
149 auto producer = GetProducer();
150 if (!producer)
151 return -EPIPE;
152
153 ignored_ = ignored;
154 if (ignored_ && !handled_) {
155 // Update the producer if ignore is set after the consumer acquires the
156 // buffer.
157 ClearAvailable();
158 producer->OnConsumerIgnored();
159 handled_ = false;
160 }
161
162 return 0;
163}
164
165bool ConsumerChannel::OnProducerPosted() {
166 if (ignored_) {
167 handled_ = true;
168 return false;
169 } else {
170 handled_ = false;
171 SignalAvailable();
172 return true;
173 }
174}
175
176void ConsumerChannel::OnProducerClosed() {
177 producer_.reset();
178 Hangup();
179}
180
181} // namespace dvr
182} // namespace android