• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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