blob: 30278382c8ecf4242900940cf3c4faeb6a194f2c [file] [log] [blame]
Amy Zhang9a9ed602020-12-07 16:37:33 -08001/*
Hongguang56637e92021-07-28 17:32:55 -07002 * Copyright 2021 The Android Open Source Project
Amy Zhang9a9ed602020-12-07 16:37:33 -08003 *
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
Hongguang56637e92021-07-28 17:32:55 -070017//#define LOG_NDEBUG 0
Amy Zhang9a9ed602020-12-07 16:37:33 -080018#define LOG_TAG "DvrClient"
19
Hongguang56637e92021-07-28 17:32:55 -070020#include "DvrClient.h"
21
22#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
Amy Zhang9a9ed602020-12-07 16:37:33 -080023#include <android-base/logging.h>
Hongguang56637e92021-07-28 17:32:55 -070024#include <inttypes.h>
Amy Zhang9a9ed602020-12-07 16:37:33 -080025#include <utils/Log.h>
26
Amy Zhang2d7026b2021-01-22 18:07:51 -080027#include "ClientHelper.h"
Amy Zhang9a9ed602020-12-07 16:37:33 -080028
Hongguang56637e92021-07-28 17:32:55 -070029using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
Amy Zhang9a9ed602020-12-07 16:37:33 -080030
31namespace android {
Amy Zhang9a9ed602020-12-07 16:37:33 -080032/////////////// DvrClient ///////////////////////
Amy Zhang2d7026b2021-01-22 18:07:51 -080033DvrClient::DvrClient(shared_ptr<ITunerDvr> tunerDvr) {
34 mTunerDvr = tunerDvr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080035 mFd = -1;
Hongguang56637e92021-07-28 17:32:55 -070036 mDvrMQ = nullptr;
37 mDvrMQEventFlag = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080038}
39
40DvrClient::~DvrClient() {
Hongguang56637e92021-07-28 17:32:55 -070041 mTunerDvr = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080042 mFd = -1;
Hongguang56637e92021-07-28 17:32:55 -070043 mDvrMQ = nullptr;
44 mDvrMQEventFlag = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080045}
46
Hongguang56637e92021-07-28 17:32:55 -070047void DvrClient::setFd(int32_t fd) {
Amy Zhang9a9ed602020-12-07 16:37:33 -080048 mFd = fd;
49}
50
Hongguang56637e92021-07-28 17:32:55 -070051int64_t DvrClient::readFromFile(int64_t size) {
52 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -080053 ALOGE("Failed to readFromFile. DVR mq is not configured");
54 return -1;
55 }
56 if (mFd < 0) {
57 ALOGE("Failed to readFromFile. File is not configured");
58 return -1;
59 }
60
Hongguang56637e92021-07-28 17:32:55 -070061 int64_t available = mDvrMQ->availableToWrite();
62 int64_t write = min(size, available);
Amy Zhang9a9ed602020-12-07 16:37:33 -080063
Amy Zhang2d7026b2021-01-22 18:07:51 -080064 AidlMQ::MemTransaction tx;
Hongguang56637e92021-07-28 17:32:55 -070065 int64_t ret = 0;
Amy Zhang9a9ed602020-12-07 16:37:33 -080066 if (mDvrMQ->beginWrite(write, &tx)) {
67 auto first = tx.getFirstRegion();
68 auto data = first.getAddress();
Hongguang56637e92021-07-28 17:32:55 -070069 int64_t length = first.getLength();
70 int64_t firstToWrite = min(length, write);
Amy Zhang9a9ed602020-12-07 16:37:33 -080071 ret = read(mFd, data, firstToWrite);
72
73 if (ret < 0) {
74 ALOGE("Failed to read from FD: %s", strerror(errno));
75 return -1;
76 }
77 if (ret < firstToWrite) {
Hongguang56637e92021-07-28 17:32:55 -070078 ALOGW("file to MQ, first region: %" PRIu64 " bytes to write, but %" PRIu64
79 " bytes written",
80 firstToWrite, ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -080081 } else if (firstToWrite < write) {
Hongguang56637e92021-07-28 17:32:55 -070082 ALOGV("write second region: %" PRIu64 " bytes written, %" PRIu64 " bytes in total", ret,
83 write);
Amy Zhang9a9ed602020-12-07 16:37:33 -080084 auto second = tx.getSecondRegion();
85 data = second.getAddress();
86 length = second.getLength();
Hongguang56637e92021-07-28 17:32:55 -070087 int64_t secondToWrite = std::min(length, write - firstToWrite);
Amy Zhang9a9ed602020-12-07 16:37:33 -080088 ret += read(mFd, data, secondToWrite);
89 }
Hongguang56637e92021-07-28 17:32:55 -070090 ALOGV("file to MQ: %" PRIu64 " bytes need to be written, %" PRIu64 " bytes written", write,
91 ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -080092 if (!mDvrMQ->commitWrite(ret)) {
93 ALOGE("Error: failed to commit write!");
94 return -1;
95 }
96 } else {
97 ALOGE("dvrMq.beginWrite failed");
98 }
99
100 if (ret > 0) {
101 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
102 }
103 return ret;
104}
105
Hongguang56637e92021-07-28 17:32:55 -0700106int64_t DvrClient::readFromBuffer(int8_t* buffer, int64_t size) {
107 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800108 ALOGE("Failed to readFromBuffer. DVR mq is not configured");
109 return -1;
110 }
111 if (buffer == nullptr) {
112 ALOGE("Failed to readFromBuffer. Buffer can't be null");
113 return -1;
114 }
115
Hongguang56637e92021-07-28 17:32:55 -0700116 int64_t available = mDvrMQ->availableToWrite();
Amy Zhang9a9ed602020-12-07 16:37:33 -0800117 size = min(size, available);
118
119 if (mDvrMQ->write(buffer, size)) {
120 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
121 } else {
122 ALOGD("Failed to write FMQ");
123 return -1;
124 }
125 return size;
126}
127
Hongguang56637e92021-07-28 17:32:55 -0700128int64_t DvrClient::writeToFile(int64_t size) {
129 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800130 ALOGE("Failed to writeToFile. DVR mq is not configured");
131 return -1;
132 }
133 if (mFd < 0) {
134 ALOGE("Failed to writeToFile. File is not configured");
135 return -1;
136 }
137
Hongguang56637e92021-07-28 17:32:55 -0700138 int64_t available = mDvrMQ->availableToRead();
139 int64_t toRead = min(size, available);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800140
Hongguang56637e92021-07-28 17:32:55 -0700141 int64_t ret = 0;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800142 AidlMQ::MemTransaction tx;
Amy Zhang9a9ed602020-12-07 16:37:33 -0800143 if (mDvrMQ->beginRead(toRead, &tx)) {
144 auto first = tx.getFirstRegion();
145 auto data = first.getAddress();
Hongguang56637e92021-07-28 17:32:55 -0700146 int64_t length = first.getLength();
147 int64_t firstToRead = std::min(length, toRead);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800148 ret = write(mFd, data, firstToRead);
149
150 if (ret < 0) {
151 ALOGE("Failed to write to FD: %s", strerror(errno));
152 return -1;
153 }
154 if (ret < firstToRead) {
Hongguang56637e92021-07-28 17:32:55 -0700155 ALOGW("MQ to file: %" PRIu64 " bytes read, but %" PRIu64 " bytes written", firstToRead,
156 ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800157 } else if (firstToRead < toRead) {
Hongguang56637e92021-07-28 17:32:55 -0700158 ALOGV("read second region: %" PRIu64 " bytes read, %" PRIu64 " bytes in total", ret,
159 toRead);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800160 auto second = tx.getSecondRegion();
161 data = second.getAddress();
162 length = second.getLength();
Hongguang56637e92021-07-28 17:32:55 -0700163 int32_t secondToRead = toRead - firstToRead;
Amy Zhang9a9ed602020-12-07 16:37:33 -0800164 ret += write(mFd, data, secondToRead);
165 }
Hongguang56637e92021-07-28 17:32:55 -0700166 ALOGV("MQ to file: %" PRIu64 " bytes to be read, %" PRIu64 " bytes written", toRead, ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800167 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
Hongguang56637e92021-07-28 17:32:55 -0700181int64_t DvrClient::writeToBuffer(int8_t* buffer, int64_t size) {
182 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800183 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
Hongguang56637e92021-07-28 17:32:55 -0700191 int64_t available = mDvrMQ->availableToRead();
Amy Zhang9a9ed602020-12-07 16:37:33 -0800192 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) {
Hongguang56637e92021-07-28 17:32:55 -0700204 if (mTunerDvr != nullptr) {
205 Status s = mTunerDvr->configure(settings);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800206 Result res = ClientHelper::getServiceSpecificErrorCode(s);
207 if (res != Result::SUCCESS) {
208 return res;
209 }
210
Amy Zhangb5809be2021-01-26 16:27:23 -0800211 AidlMQDesc aidlMqDesc;
212 s = mTunerDvr->getQueueDesc(&aidlMqDesc);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800213 res = ClientHelper::getServiceSpecificErrorCode(s);
214 if (res != Result::SUCCESS) {
215 return res;
216 }
Amy Zhangb5809be2021-01-26 16:27:23 -0800217 mDvrMQ = new (nothrow) AidlMQ(aidlMqDesc);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800218 EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
219 return res;
220 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800221
Amy Zhang9a9ed602020-12-07 16:37:33 -0800222 return Result::INVALID_STATE;
223}
224
225Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
Hongguang56637e92021-07-28 17:32:55 -0700226 if (filterClient == nullptr) {
227 return Result::INVALID_ARGUMENT;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800228 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800229
Hongguang56637e92021-07-28 17:32:55 -0700230 if (mTunerDvr != nullptr) {
231 Status s = mTunerDvr->attachFilter(filterClient->getAidlFilter());
232 return ClientHelper::getServiceSpecificErrorCode(s);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800233 }
234
235 return Result::INVALID_STATE;
236}
237
238Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
Hongguang56637e92021-07-28 17:32:55 -0700239 if (filterClient == nullptr) {
240 return Result::INVALID_ARGUMENT;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800241 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800242
Hongguang56637e92021-07-28 17:32:55 -0700243 if (mTunerDvr != nullptr) {
244 Status s = mTunerDvr->detachFilter(filterClient->getAidlFilter());
245 return ClientHelper::getServiceSpecificErrorCode(s);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800246 }
247
248 return Result::INVALID_STATE;
249}
250
251Result DvrClient::start() {
Hongguang56637e92021-07-28 17:32:55 -0700252 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800253 Status s = mTunerDvr->start();
254 return ClientHelper::getServiceSpecificErrorCode(s);
255 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800256
Amy Zhang9a9ed602020-12-07 16:37:33 -0800257 return Result::INVALID_STATE;
258}
259
260Result DvrClient::stop() {
Hongguang56637e92021-07-28 17:32:55 -0700261 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800262 Status s = mTunerDvr->stop();
263 return ClientHelper::getServiceSpecificErrorCode(s);
264 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800265
Amy Zhang9a9ed602020-12-07 16:37:33 -0800266 return Result::INVALID_STATE;
267}
268
269Result DvrClient::flush() {
Hongguang56637e92021-07-28 17:32:55 -0700270 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800271 Status s = mTunerDvr->flush();
272 return ClientHelper::getServiceSpecificErrorCode(s);
273 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800274
Amy Zhang9a9ed602020-12-07 16:37:33 -0800275 return Result::INVALID_STATE;
276}
277
278Result DvrClient::close() {
Hongguang56637e92021-07-28 17:32:55 -0700279 if (mDvrMQEventFlag != nullptr) {
Henry Fangbc30a4b2021-03-15 13:27:37 -0700280 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
Gareth Fenn0f6338852021-11-04 16:28:44 +0000281 mDvrMQEventFlag = nullptr;
Henry Fangbc30a4b2021-03-15 13:27:37 -0700282 }
Gareth Fenn0f6338852021-11-04 16:28:44 +0000283 if (mDvrMQ != nullptr) {
284 delete mDvrMQ;
285 mDvrMQ = nullptr;
286 }
Henry Fangbc30a4b2021-03-15 13:27:37 -0700287
Hongguang56637e92021-07-28 17:32:55 -0700288 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800289 Status s = mTunerDvr->close();
Hongguang56637e92021-07-28 17:32:55 -0700290 mTunerDvr = nullptr;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800291 return ClientHelper::getServiceSpecificErrorCode(s);
292 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800293
Amy Zhang9a9ed602020-12-07 16:37:33 -0800294 return Result::INVALID_STATE;
295}
296
Amy Zhang2d7026b2021-01-22 18:07:51 -0800297/////////////// TunerDvrCallback ///////////////////////
Amy Zhang2d7026b2021-01-22 18:07:51 -0800298TunerDvrCallback::TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)
299 : mDvrClientCallback(dvrClientCallback) {}
300
Hongguang56637e92021-07-28 17:32:55 -0700301Status TunerDvrCallback::onRecordStatus(RecordStatus status) {
302 if (mDvrClientCallback != nullptr) {
303 mDvrClientCallback->onRecordStatus(status);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800304 return Status::ok();
305 }
306 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
307}
308
Hongguang56637e92021-07-28 17:32:55 -0700309Status TunerDvrCallback::onPlaybackStatus(PlaybackStatus status) {
310 if (mDvrClientCallback != nullptr) {
311 mDvrClientCallback->onPlaybackStatus(status);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800312 return Status::ok();
313 }
314 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
315}
316
Amy Zhang9a9ed602020-12-07 16:37:33 -0800317} // namespace android