blob: dd08491d3a9fb19a945c9e91e5b5fa79f002764e [file] [log] [blame]
Amy Zhang9a9ed602020-12-07 16:37:33 -08001/*
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 <utils/Log.h>
21
22#include "DvrClient.h"
23
24using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
25using ::android::hardware::tv::tuner::V1_0::Result;
26
27namespace android {
28
29/////////////// DvrClient ///////////////////////
30
31// TODO: pending aidl interface
32DvrClient::DvrClient() {
33 //mTunerDvr = tunerDvr;
34 mFd = -1;
35 mDvrMQ = NULL;
36 mDvrMQEventFlag = NULL;
37}
38
39DvrClient::~DvrClient() {
40 //mTunerDvr = NULL;
41 mDvr = NULL;
42 mFd = -1;
43 mDvrMQ = NULL;
44 mDvrMQEventFlag = NULL;
45}
46
47// TODO: remove after migration to Tuner Service is done.
48void DvrClient::setHidlDvr(sp<IDvr> dvr) {
49 mDvr = dvr;
50}
51
52void DvrClient::setFd(int fd) {
53 mFd = fd;
54}
55
56long DvrClient::readFromFile(long size) {
57 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
58 ALOGE("Failed to readFromFile. DVR mq is not configured");
59 return -1;
60 }
61 if (mFd < 0) {
62 ALOGE("Failed to readFromFile. File is not configured");
63 return -1;
64 }
65
66 long available = mDvrMQ->availableToWrite();
67 long write = min(size, available);
68
69 MQ::MemTransaction tx;
70 long ret = 0;
71 if (mDvrMQ->beginWrite(write, &tx)) {
72 auto first = tx.getFirstRegion();
73 auto data = first.getAddress();
74 long length = first.getLength();
75 long firstToWrite = min(length, write);
76 ret = read(mFd, data, firstToWrite);
77
78 if (ret < 0) {
79 ALOGE("Failed to read from FD: %s", strerror(errno));
80 return -1;
81 }
82 if (ret < firstToWrite) {
83 ALOGW("file to MQ, first region: %ld bytes to write, but %ld bytes written",
84 firstToWrite, ret);
85 } else if (firstToWrite < write) {
86 ALOGD("write second region: %ld bytes written, %ld bytes in total", ret, write);
87 auto second = tx.getSecondRegion();
88 data = second.getAddress();
89 length = second.getLength();
90 int secondToWrite = std::min(length, write - firstToWrite);
91 ret += read(mFd, data, secondToWrite);
92 }
93 ALOGD("file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
94 if (!mDvrMQ->commitWrite(ret)) {
95 ALOGE("Error: failed to commit write!");
96 return -1;
97 }
98 } else {
99 ALOGE("dvrMq.beginWrite failed");
100 }
101
102 if (ret > 0) {
103 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
104 }
105 return ret;
106}
107
108long DvrClient::readFromBuffer(uint8_t* buffer, long size) {
109 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
110 ALOGE("Failed to readFromBuffer. DVR mq is not configured");
111 return -1;
112 }
113 if (buffer == nullptr) {
114 ALOGE("Failed to readFromBuffer. Buffer can't be null");
115 return -1;
116 }
117
118 long available = mDvrMQ->availableToWrite();
119 size = min(size, available);
120
121 if (mDvrMQ->write(buffer, size)) {
122 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
123 } else {
124 ALOGD("Failed to write FMQ");
125 return -1;
126 }
127 return size;
128}
129
130long DvrClient::writeToFile(long size) {
131 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
132 ALOGE("Failed to writeToFile. DVR mq is not configured");
133 return -1;
134 }
135 if (mFd < 0) {
136 ALOGE("Failed to writeToFile. File is not configured");
137 return -1;
138 }
139
140 long available = mDvrMQ->availableToRead();
141 long toRead = min(size, available);
142
143 long ret = 0;
144 MQ::MemTransaction tx;
145 if (mDvrMQ->beginRead(toRead, &tx)) {
146 auto first = tx.getFirstRegion();
147 auto data = first.getAddress();
148 long length = first.getLength();
149 long firstToRead = std::min(length, toRead);
150 ret = write(mFd, data, firstToRead);
151
152 if (ret < 0) {
153 ALOGE("Failed to write to FD: %s", strerror(errno));
154 return -1;
155 }
156 if (ret < firstToRead) {
157 ALOGW("MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
158 } else if (firstToRead < toRead) {
159 ALOGD("read second region: %ld bytes read, %ld bytes in total", ret, toRead);
160 auto second = tx.getSecondRegion();
161 data = second.getAddress();
162 length = second.getLength();
163 int secondToRead = toRead - firstToRead;
164 ret += write(mFd, data, secondToRead);
165 }
166 ALOGD("MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
167 if (!mDvrMQ->commitRead(ret)) {
168 ALOGE("Error: failed to commit read!");
169 return 0;
170 }
171 } else {
172 ALOGE("dvrMq.beginRead failed");
173 }
174 if (ret > 0) {
175 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
176 }
177
178 return ret;
179}
180
181long DvrClient::writeToBuffer(uint8_t* buffer, long size) {
182 if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
183 ALOGE("Failed to writetoBuffer. DVR mq is not configured");
184 return -1;
185 }
186 if (buffer == nullptr) {
187 ALOGE("Failed to writetoBuffer. Buffer can't be null");
188 return -1;
189 }
190
191 long available = mDvrMQ->availableToRead();
192 size = min(size, available);
193
194 if (mDvrMQ->read(buffer, size)) {
195 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
196 } else {
197 ALOGD("Failed to write FMQ");
198 return -1;
199 }
200 return size;
201}
202
203Result DvrClient::configure(DvrSettings settings) {
204 // pending aidl interface
205
206 if (mDvr != NULL) {
207 Result res = mDvr->configure(settings);
208 if (res == Result::SUCCESS) {
209 MQDescriptorSync<uint8_t> dvrMQDesc;
210 res = getQueueDesc(dvrMQDesc);
211 if (res == Result::SUCCESS) {
212 mDvrMQ = make_unique<MQ>(dvrMQDesc, true);
213 EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
214 }
215 }
216 return res;
217 }
218
219 return Result::INVALID_STATE;
220}
221
222Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
223 // pending aidl interface
224
225 if (mDvr != NULL) {
226 sp<IFilter> hidlFilter = filterClient->getHalFilter();
227 if (hidlFilter == NULL) {
228 return Result::INVALID_ARGUMENT;
229 }
230 return mDvr->attachFilter(hidlFilter);
231 }
232
233 return Result::INVALID_STATE;
234}
235
236Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
237 // pending aidl interface
238
239 if (mDvr != NULL) {
240 sp<IFilter> hidlFilter = filterClient->getHalFilter();
241 if (hidlFilter == NULL) {
242 return Result::INVALID_ARGUMENT;
243 }
244 return mDvr->detachFilter(hidlFilter);
245 }
246
247 return Result::INVALID_STATE;
248}
249
250Result DvrClient::start() {
251 // pending aidl interface
252
253 if (mDvr != NULL) {
254 return mDvr->start();
255 }
256
257 return Result::INVALID_STATE;
258}
259
260Result DvrClient::stop() {
261 // pending aidl interface
262
263 if (mDvr != NULL) {
264 return mDvr->stop();
265 }
266
267 return Result::INVALID_STATE;
268}
269
270Result DvrClient::flush() {
271 // pending aidl interface
272
273 if (mDvr != NULL) {
274 return mDvr->flush();
275 }
276
277 return Result::INVALID_STATE;
278}
279
280Result DvrClient::close() {
281 // pending aidl interface
282
283 if (mDvr != NULL) {
284 Result res = mDvr->close();
285 if (res == Result::SUCCESS) {
286 mDvr = NULL;
287 }
288 return res;
289 }
290
291 return Result::INVALID_STATE;
292}
293
294/////////////// IDvrCallback ///////////////////////
295
296HidlDvrCallback::HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback)
297 : mDvrClientCallback(dvrClientCallback) {}
298
299Return<void> HidlDvrCallback::onRecordStatus(const RecordStatus status) {
300 if (mDvrClientCallback != NULL) {
301 mDvrClientCallback->onRecordStatus(status);
302 }
303 return Void();
304}
305
306Return<void> HidlDvrCallback::onPlaybackStatus(const PlaybackStatus status) {
307 if (mDvrClientCallback != NULL) {
308 mDvrClientCallback->onPlaybackStatus(status);
309 }
310 return Void();
311}
312
313/////////////// DvrClient Helper Methods ///////////////////////
314
315Result DvrClient::getQueueDesc(MQDesc& dvrMQDesc) {
316 // pending aidl interface
317
318 if (mDvr != NULL) {
319 Result res = Result::UNKNOWN_ERROR;
320 mDvr->getQueueDesc([&](Result r, const MQDesc& desc) {
321 dvrMQDesc = desc;
322 res = r;
323 });
324 return res;
325 }
326
327 return Result::INVALID_STATE;
328}
329} // namespace android