1 /*
2 * Copyright 2020 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 #define LOG_TAG "DvrClient"
18
19 #include <android-base/logging.h>
20 #include <fmq/ConvertMQDescriptors.h>
21 #include <utils/Log.h>
22
23 #include "ClientHelper.h"
24 #include "DvrClient.h"
25
26 using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
27 using ::android::hardware::tv::tuner::V1_0::Result;
28
29 namespace android {
30
31 /////////////// DvrClient ///////////////////////
32
DvrClient(shared_ptr<ITunerDvr> tunerDvr)33 DvrClient::DvrClient(shared_ptr<ITunerDvr> tunerDvr) {
34 mTunerDvr = tunerDvr;
35 mFd = -1;
36 mDvrMQ = NULL;
37 mDvrMQEventFlag = NULL;
38 }
39
~DvrClient()40 DvrClient::~DvrClient() {
41 mTunerDvr = NULL;
42 mDvr = NULL;
43 mFd = -1;
44 mDvrMQ = NULL;
45 mDvrMQEventFlag = NULL;
46 }
47
48 // TODO: remove after migration to Tuner Service is done.
setHidlDvr(sp<IDvr> dvr)49 void DvrClient::setHidlDvr(sp<IDvr> dvr) {
50 mDvr = dvr;
51 }
52
setFd(int fd)53 void DvrClient::setFd(int fd) {
54 mFd = fd;
55 }
56
readFromFile(long size)57 long DvrClient::readFromFile(long size) {
58 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
59 ALOGE("Failed to readFromFile. DVR mq is not configured");
60 return -1;
61 }
62 if (mFd < 0) {
63 ALOGE("Failed to readFromFile. File is not configured");
64 return -1;
65 }
66
67 long available = mDvrMQ->availableToWrite();
68 long write = min(size, available);
69
70 AidlMQ::MemTransaction tx;
71 long ret = 0;
72 if (mDvrMQ->beginWrite(write, &tx)) {
73 auto first = tx.getFirstRegion();
74 auto data = first.getAddress();
75 long length = first.getLength();
76 long firstToWrite = min(length, write);
77 ret = read(mFd, data, firstToWrite);
78
79 if (ret < 0) {
80 ALOGE("Failed to read from FD: %s", strerror(errno));
81 return -1;
82 }
83 if (ret < firstToWrite) {
84 ALOGW("file to MQ, first region: %ld bytes to write, but %ld bytes written",
85 firstToWrite, ret);
86 } else if (firstToWrite < write) {
87 ALOGD("write second region: %ld bytes written, %ld bytes in total", ret, write);
88 auto second = tx.getSecondRegion();
89 data = second.getAddress();
90 length = second.getLength();
91 int secondToWrite = std::min(length, write - firstToWrite);
92 ret += read(mFd, data, secondToWrite);
93 }
94 ALOGD("file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
95 if (!mDvrMQ->commitWrite(ret)) {
96 ALOGE("Error: failed to commit write!");
97 return -1;
98 }
99 } else {
100 ALOGE("dvrMq.beginWrite failed");
101 }
102
103 if (ret > 0) {
104 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
105 }
106 return ret;
107 }
108
readFromBuffer(int8_t * buffer,long size)109 long DvrClient::readFromBuffer(int8_t* buffer, long size) {
110 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
111 ALOGE("Failed to readFromBuffer. DVR mq is not configured");
112 return -1;
113 }
114 if (buffer == nullptr) {
115 ALOGE("Failed to readFromBuffer. Buffer can't be null");
116 return -1;
117 }
118
119 long available = mDvrMQ->availableToWrite();
120 size = min(size, available);
121
122 if (mDvrMQ->write(buffer, size)) {
123 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
124 } else {
125 ALOGD("Failed to write FMQ");
126 return -1;
127 }
128 return size;
129 }
130
writeToFile(long size)131 long DvrClient::writeToFile(long size) {
132 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
133 ALOGE("Failed to writeToFile. DVR mq is not configured");
134 return -1;
135 }
136 if (mFd < 0) {
137 ALOGE("Failed to writeToFile. File is not configured");
138 return -1;
139 }
140
141 long available = mDvrMQ->availableToRead();
142 long toRead = min(size, available);
143
144 long ret = 0;
145 AidlMQ::MemTransaction tx;
146 if (mDvrMQ->beginRead(toRead, &tx)) {
147 auto first = tx.getFirstRegion();
148 auto data = first.getAddress();
149 long length = first.getLength();
150 long firstToRead = std::min(length, toRead);
151 ret = write(mFd, data, firstToRead);
152
153 if (ret < 0) {
154 ALOGE("Failed to write to FD: %s", strerror(errno));
155 return -1;
156 }
157 if (ret < firstToRead) {
158 ALOGW("MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
159 } else if (firstToRead < toRead) {
160 ALOGD("read second region: %ld bytes read, %ld bytes in total", ret, toRead);
161 auto second = tx.getSecondRegion();
162 data = second.getAddress();
163 length = second.getLength();
164 int secondToRead = toRead - firstToRead;
165 ret += write(mFd, data, secondToRead);
166 }
167 ALOGD("MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
168 if (!mDvrMQ->commitRead(ret)) {
169 ALOGE("Error: failed to commit read!");
170 return 0;
171 }
172 } else {
173 ALOGE("dvrMq.beginRead failed");
174 }
175 if (ret > 0) {
176 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
177 }
178
179 return ret;
180 }
181
writeToBuffer(int8_t * buffer,long size)182 long DvrClient::writeToBuffer(int8_t* buffer, long size) {
183 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
184 ALOGE("Failed to writetoBuffer. DVR mq is not configured");
185 return -1;
186 }
187 if (buffer == nullptr) {
188 ALOGE("Failed to writetoBuffer. Buffer can't be null");
189 return -1;
190 }
191
192 long available = mDvrMQ->availableToRead();
193 size = min(size, available);
194
195 if (mDvrMQ->read(buffer, size)) {
196 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
197 } else {
198 ALOGD("Failed to write FMQ");
199 return -1;
200 }
201 return size;
202 }
203
configure(DvrSettings settings)204 Result DvrClient::configure(DvrSettings settings) {
205 if (mTunerDvr != NULL) {
206 TunerDvrSettings dvrSettings = getAidlDvrSettingsFromHidl(settings);
207 Status s = mTunerDvr->configure(dvrSettings);
208 Result res = ClientHelper::getServiceSpecificErrorCode(s);
209 if (res != Result::SUCCESS) {
210 return res;
211 }
212
213 AidlMQDesc aidlMqDesc;
214 s = mTunerDvr->getQueueDesc(&aidlMqDesc);
215 res = ClientHelper::getServiceSpecificErrorCode(s);
216 if (res != Result::SUCCESS) {
217 return res;
218 }
219 mDvrMQ = new (nothrow) AidlMQ(aidlMqDesc);
220 EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
221 return res;
222 }
223
224 if (mDvr != NULL) {
225 Result res = mDvr->configure(settings);
226 if (res == Result::SUCCESS) {
227 MQDescriptorSync<uint8_t> dvrMQDesc;
228 res = getQueueDesc(dvrMQDesc);
229 if (res == Result::SUCCESS) {
230 AidlMQDesc aidlMQDesc;
231 unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
232 dvrMQDesc, &aidlMQDesc);
233 mDvrMQ = new (nothrow) AidlMessageQueue(aidlMQDesc);
234 EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
235 }
236 }
237 return res;
238 }
239
240 return Result::INVALID_STATE;
241 }
242
attachFilter(sp<FilterClient> filterClient)243 Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
244 if (mTunerDvr != NULL) {
245 Status s = mTunerDvr->attachFilter(filterClient->getAidlFilter());
246 return ClientHelper::getServiceSpecificErrorCode(s);
247 }
248
249 if (mDvr != NULL) {
250 sp<IFilter> hidlFilter = filterClient->getHalFilter();
251 if (hidlFilter == NULL) {
252 return Result::INVALID_ARGUMENT;
253 }
254 return mDvr->attachFilter(hidlFilter);
255 }
256
257 return Result::INVALID_STATE;
258 }
259
detachFilter(sp<FilterClient> filterClient)260 Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
261 if (mTunerDvr != NULL) {
262 Status s = mTunerDvr->detachFilter(filterClient->getAidlFilter());
263 return ClientHelper::getServiceSpecificErrorCode(s);
264 }
265
266 if (mDvr != NULL) {
267 sp<IFilter> hidlFilter = filterClient->getHalFilter();
268 if (hidlFilter == NULL) {
269 return Result::INVALID_ARGUMENT;
270 }
271 return mDvr->detachFilter(hidlFilter);
272 }
273
274 return Result::INVALID_STATE;
275 }
276
start()277 Result DvrClient::start() {
278 if (mTunerDvr != NULL) {
279 Status s = mTunerDvr->start();
280 return ClientHelper::getServiceSpecificErrorCode(s);
281 }
282
283 if (mDvr != NULL) {
284 return mDvr->start();
285 }
286
287 return Result::INVALID_STATE;
288 }
289
stop()290 Result DvrClient::stop() {
291 if (mTunerDvr != NULL) {
292 Status s = mTunerDvr->stop();
293 return ClientHelper::getServiceSpecificErrorCode(s);
294 }
295
296 if (mDvr != NULL) {
297 return mDvr->stop();
298 }
299
300 return Result::INVALID_STATE;
301 }
302
flush()303 Result DvrClient::flush() {
304 if (mTunerDvr != NULL) {
305 Status s = mTunerDvr->flush();
306 return ClientHelper::getServiceSpecificErrorCode(s);
307 }
308
309 if (mDvr != NULL) {
310 return mDvr->flush();
311 }
312
313 return Result::INVALID_STATE;
314 }
315
close()316 Result DvrClient::close() {
317 if (mDvrMQEventFlag != NULL) {
318 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
319 }
320 mDvrMQ = NULL;
321
322 if (mTunerDvr != NULL) {
323 Status s = mTunerDvr->close();
324 mTunerDvr = NULL;
325 return ClientHelper::getServiceSpecificErrorCode(s);
326 }
327
328 if (mDvr != NULL) {
329 Result res = mDvr->close();
330 mDvr = NULL;
331 return res;
332 }
333
334 return Result::INVALID_STATE;
335 }
336
337 /////////////// IDvrCallback ///////////////////////
338
HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback)339 HidlDvrCallback::HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback)
340 : mDvrClientCallback(dvrClientCallback) {}
341
onRecordStatus(const RecordStatus status)342 Return<void> HidlDvrCallback::onRecordStatus(const RecordStatus status) {
343 if (mDvrClientCallback != NULL) {
344 mDvrClientCallback->onRecordStatus(status);
345 }
346 return Void();
347 }
348
onPlaybackStatus(const PlaybackStatus status)349 Return<void> HidlDvrCallback::onPlaybackStatus(const PlaybackStatus status) {
350 if (mDvrClientCallback != NULL) {
351 mDvrClientCallback->onPlaybackStatus(status);
352 }
353 return Void();
354 }
355
356 /////////////// TunerDvrCallback ///////////////////////
357
TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)358 TunerDvrCallback::TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)
359 : mDvrClientCallback(dvrClientCallback) {}
360
onRecordStatus(int status)361 Status TunerDvrCallback::onRecordStatus(int status) {
362 if (mDvrClientCallback != NULL) {
363 mDvrClientCallback->onRecordStatus(static_cast<RecordStatus>(status));
364 return Status::ok();
365 }
366 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
367 }
368
onPlaybackStatus(int status)369 Status TunerDvrCallback::onPlaybackStatus(int status) {
370 if (mDvrClientCallback != NULL) {
371 mDvrClientCallback->onPlaybackStatus(static_cast<PlaybackStatus>(status));
372 return Status::ok();
373 }
374 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
375 }
376
377 /////////////// DvrClient Helper Methods ///////////////////////
378
getQueueDesc(MQDesc & dvrMQDesc)379 Result DvrClient::getQueueDesc(MQDesc& dvrMQDesc) {
380 if (mDvr != NULL) {
381 Result res = Result::UNKNOWN_ERROR;
382 mDvr->getQueueDesc([&](Result r, const MQDesc& desc) {
383 dvrMQDesc = desc;
384 res = r;
385 });
386 return res;
387 }
388
389 return Result::INVALID_STATE;
390 }
391
getAidlDvrSettingsFromHidl(DvrSettings settings)392 TunerDvrSettings DvrClient::getAidlDvrSettingsFromHidl(DvrSettings settings) {
393 TunerDvrSettings s;
394 switch (settings.getDiscriminator()) {
395 case DvrSettings::hidl_discriminator::record: {
396 s.statusMask = static_cast<int>(settings.record().statusMask);
397 s.lowThreshold = static_cast<int>(settings.record().lowThreshold);
398 s.highThreshold = static_cast<int>(settings.record().highThreshold);
399 s.dataFormat = static_cast<int>(settings.record().dataFormat);
400 s.packetSize = static_cast<int>(settings.record().packetSize);
401 return s;
402 }
403 case DvrSettings::hidl_discriminator::playback: {
404 s.statusMask = static_cast<int>(settings.playback().statusMask);
405 s.lowThreshold = static_cast<int>(settings.playback().lowThreshold);
406 s.highThreshold = static_cast<int>(settings.playback().highThreshold);
407 s.dataFormat = static_cast<int>(settings.playback().dataFormat);
408 s.packetSize = static_cast<int>(settings.playback().packetSize);
409 return s;
410 }
411 default:
412 break;
413 }
414 return s;
415 }
416 } // namespace android
417