blob: 6e4705251724df69e5792e44b235557f0bb04d4e [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>
Hongguang90dd6742021-11-23 13:24:00 -080025#include <sys/types.h>
26#include <unistd.h>
Amy Zhang9a9ed602020-12-07 16:37:33 -080027#include <utils/Log.h>
28
Amy Zhang2d7026b2021-01-22 18:07:51 -080029#include "ClientHelper.h"
Amy Zhang9a9ed602020-12-07 16:37:33 -080030
Hongguang56637e92021-07-28 17:32:55 -070031using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
Amy Zhang9a9ed602020-12-07 16:37:33 -080032
33namespace android {
Amy Zhang9a9ed602020-12-07 16:37:33 -080034/////////////// DvrClient ///////////////////////
Amy Zhang2d7026b2021-01-22 18:07:51 -080035DvrClient::DvrClient(shared_ptr<ITunerDvr> tunerDvr) {
36 mTunerDvr = tunerDvr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080037 mFd = -1;
Hongguang56637e92021-07-28 17:32:55 -070038 mDvrMQ = nullptr;
39 mDvrMQEventFlag = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080040}
41
42DvrClient::~DvrClient() {
Hongguang56637e92021-07-28 17:32:55 -070043 mTunerDvr = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080044 mFd = -1;
Hongguang56637e92021-07-28 17:32:55 -070045 mDvrMQ = nullptr;
46 mDvrMQEventFlag = nullptr;
Amy Zhang9a9ed602020-12-07 16:37:33 -080047}
48
Hongguang56637e92021-07-28 17:32:55 -070049void DvrClient::setFd(int32_t fd) {
Amy Zhang9a9ed602020-12-07 16:37:33 -080050 mFd = fd;
51}
52
Hongguang56637e92021-07-28 17:32:55 -070053int64_t DvrClient::readFromFile(int64_t size) {
54 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -080055 ALOGE("Failed to readFromFile. DVR mq is not configured");
56 return -1;
57 }
58 if (mFd < 0) {
59 ALOGE("Failed to readFromFile. File is not configured");
60 return -1;
61 }
62
Hongguang56637e92021-07-28 17:32:55 -070063 int64_t available = mDvrMQ->availableToWrite();
64 int64_t write = min(size, available);
Amy Zhang9a9ed602020-12-07 16:37:33 -080065
Amy Zhang2d7026b2021-01-22 18:07:51 -080066 AidlMQ::MemTransaction tx;
Hongguang56637e92021-07-28 17:32:55 -070067 int64_t ret = 0;
Amy Zhang9a9ed602020-12-07 16:37:33 -080068 if (mDvrMQ->beginWrite(write, &tx)) {
69 auto first = tx.getFirstRegion();
70 auto data = first.getAddress();
Hongguang56637e92021-07-28 17:32:55 -070071 int64_t length = first.getLength();
72 int64_t firstToWrite = min(length, write);
Amy Zhang9a9ed602020-12-07 16:37:33 -080073 ret = read(mFd, data, firstToWrite);
74
75 if (ret < 0) {
76 ALOGE("Failed to read from FD: %s", strerror(errno));
77 return -1;
78 }
79 if (ret < firstToWrite) {
Hongguang56637e92021-07-28 17:32:55 -070080 ALOGW("file to MQ, first region: %" PRIu64 " bytes to write, but %" PRIu64
81 " bytes written",
82 firstToWrite, ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -080083 } else if (firstToWrite < write) {
Hongguang56637e92021-07-28 17:32:55 -070084 ALOGV("write second region: %" PRIu64 " bytes written, %" PRIu64 " bytes in total", ret,
85 write);
Amy Zhang9a9ed602020-12-07 16:37:33 -080086 auto second = tx.getSecondRegion();
87 data = second.getAddress();
88 length = second.getLength();
Hongguang56637e92021-07-28 17:32:55 -070089 int64_t secondToWrite = std::min(length, write - firstToWrite);
Amy Zhang9a9ed602020-12-07 16:37:33 -080090 ret += read(mFd, data, secondToWrite);
91 }
Hongguang56637e92021-07-28 17:32:55 -070092 ALOGV("file to MQ: %" PRIu64 " bytes need to be written, %" PRIu64 " bytes written", write,
93 ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -080094 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
Hongguang56637e92021-07-28 17:32:55 -0700108int64_t DvrClient::readFromBuffer(int8_t* buffer, int64_t size) {
109 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800110 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
Hongguang56637e92021-07-28 17:32:55 -0700118 int64_t available = mDvrMQ->availableToWrite();
Amy Zhang9a9ed602020-12-07 16:37:33 -0800119 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
Hongguang56637e92021-07-28 17:32:55 -0700130int64_t DvrClient::writeToFile(int64_t size) {
131 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800132 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
Hongguang56637e92021-07-28 17:32:55 -0700140 int64_t available = mDvrMQ->availableToRead();
141 int64_t toRead = min(size, available);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800142
Hongguang56637e92021-07-28 17:32:55 -0700143 int64_t ret = 0;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800144 AidlMQ::MemTransaction tx;
Amy Zhang9a9ed602020-12-07 16:37:33 -0800145 if (mDvrMQ->beginRead(toRead, &tx)) {
146 auto first = tx.getFirstRegion();
147 auto data = first.getAddress();
Hongguang56637e92021-07-28 17:32:55 -0700148 int64_t length = first.getLength();
149 int64_t firstToRead = std::min(length, toRead);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800150 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) {
Hongguang56637e92021-07-28 17:32:55 -0700157 ALOGW("MQ to file: %" PRIu64 " bytes read, but %" PRIu64 " bytes written", firstToRead,
158 ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800159 } else if (firstToRead < toRead) {
Hongguang56637e92021-07-28 17:32:55 -0700160 ALOGV("read second region: %" PRIu64 " bytes read, %" PRIu64 " bytes in total", ret,
161 toRead);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800162 auto second = tx.getSecondRegion();
163 data = second.getAddress();
164 length = second.getLength();
Hongguang56637e92021-07-28 17:32:55 -0700165 int32_t secondToRead = toRead - firstToRead;
Amy Zhang9a9ed602020-12-07 16:37:33 -0800166 ret += write(mFd, data, secondToRead);
167 }
Hongguang56637e92021-07-28 17:32:55 -0700168 ALOGV("MQ to file: %" PRIu64 " bytes to be read, %" PRIu64 " bytes written", toRead, ret);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800169 if (!mDvrMQ->commitRead(ret)) {
170 ALOGE("Error: failed to commit read!");
171 return 0;
172 }
173 } else {
174 ALOGE("dvrMq.beginRead failed");
175 }
176 if (ret > 0) {
177 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
178 }
179
180 return ret;
181}
182
Hongguang56637e92021-07-28 17:32:55 -0700183int64_t DvrClient::writeToBuffer(int8_t* buffer, int64_t size) {
184 if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
Amy Zhang9a9ed602020-12-07 16:37:33 -0800185 ALOGE("Failed to writetoBuffer. DVR mq is not configured");
186 return -1;
187 }
188 if (buffer == nullptr) {
189 ALOGE("Failed to writetoBuffer. Buffer can't be null");
190 return -1;
191 }
192
Hongguang56637e92021-07-28 17:32:55 -0700193 int64_t available = mDvrMQ->availableToRead();
Amy Zhang9a9ed602020-12-07 16:37:33 -0800194 size = min(size, available);
195
196 if (mDvrMQ->read(buffer, size)) {
197 mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
198 } else {
199 ALOGD("Failed to write FMQ");
200 return -1;
201 }
202 return size;
203}
204
Hongguang90dd6742021-11-23 13:24:00 -0800205int64_t DvrClient::seekFile(int64_t pos) {
206 if (mFd < 0) {
207 ALOGE("Failed to seekFile. File is not configured");
208 return -1;
209 }
210 return lseek64(mFd, pos, SEEK_SET);
211}
212
Amy Zhang9a9ed602020-12-07 16:37:33 -0800213Result DvrClient::configure(DvrSettings settings) {
Hongguang56637e92021-07-28 17:32:55 -0700214 if (mTunerDvr != nullptr) {
215 Status s = mTunerDvr->configure(settings);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800216 Result res = ClientHelper::getServiceSpecificErrorCode(s);
217 if (res != Result::SUCCESS) {
218 return res;
219 }
220
Amy Zhangb5809be2021-01-26 16:27:23 -0800221 AidlMQDesc aidlMqDesc;
222 s = mTunerDvr->getQueueDesc(&aidlMqDesc);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800223 res = ClientHelper::getServiceSpecificErrorCode(s);
224 if (res != Result::SUCCESS) {
225 return res;
226 }
Amy Zhangb5809be2021-01-26 16:27:23 -0800227 mDvrMQ = new (nothrow) AidlMQ(aidlMqDesc);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800228 EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
229 return res;
230 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800231
Amy Zhang9a9ed602020-12-07 16:37:33 -0800232 return Result::INVALID_STATE;
233}
234
235Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
Hongguang56637e92021-07-28 17:32:55 -0700236 if (filterClient == nullptr) {
237 return Result::INVALID_ARGUMENT;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800238 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800239
Hongguang56637e92021-07-28 17:32:55 -0700240 if (mTunerDvr != nullptr) {
241 Status s = mTunerDvr->attachFilter(filterClient->getAidlFilter());
242 return ClientHelper::getServiceSpecificErrorCode(s);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800243 }
244
245 return Result::INVALID_STATE;
246}
247
248Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
Hongguang56637e92021-07-28 17:32:55 -0700249 if (filterClient == nullptr) {
250 return Result::INVALID_ARGUMENT;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800251 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800252
Hongguang56637e92021-07-28 17:32:55 -0700253 if (mTunerDvr != nullptr) {
254 Status s = mTunerDvr->detachFilter(filterClient->getAidlFilter());
255 return ClientHelper::getServiceSpecificErrorCode(s);
Amy Zhang9a9ed602020-12-07 16:37:33 -0800256 }
257
258 return Result::INVALID_STATE;
259}
260
261Result DvrClient::start() {
Hongguang56637e92021-07-28 17:32:55 -0700262 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800263 Status s = mTunerDvr->start();
264 return ClientHelper::getServiceSpecificErrorCode(s);
265 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800266
Amy Zhang9a9ed602020-12-07 16:37:33 -0800267 return Result::INVALID_STATE;
268}
269
270Result DvrClient::stop() {
Hongguang56637e92021-07-28 17:32:55 -0700271 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800272 Status s = mTunerDvr->stop();
273 return ClientHelper::getServiceSpecificErrorCode(s);
274 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800275
Amy Zhang9a9ed602020-12-07 16:37:33 -0800276 return Result::INVALID_STATE;
277}
278
279Result DvrClient::flush() {
Hongguang56637e92021-07-28 17:32:55 -0700280 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800281 Status s = mTunerDvr->flush();
282 return ClientHelper::getServiceSpecificErrorCode(s);
283 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800284
Amy Zhang9a9ed602020-12-07 16:37:33 -0800285 return Result::INVALID_STATE;
286}
287
288Result DvrClient::close() {
Hongguang56637e92021-07-28 17:32:55 -0700289 if (mDvrMQEventFlag != nullptr) {
Henry Fangbc30a4b2021-03-15 13:27:37 -0700290 EventFlag::deleteEventFlag(&mDvrMQEventFlag);
Gareth Fenn0f6338852021-11-04 16:28:44 +0000291 mDvrMQEventFlag = nullptr;
Henry Fangbc30a4b2021-03-15 13:27:37 -0700292 }
Gareth Fenn0f6338852021-11-04 16:28:44 +0000293 if (mDvrMQ != nullptr) {
294 delete mDvrMQ;
295 mDvrMQ = nullptr;
296 }
Henry Fangbc30a4b2021-03-15 13:27:37 -0700297
Hongguang56637e92021-07-28 17:32:55 -0700298 if (mTunerDvr != nullptr) {
Amy Zhang2d7026b2021-01-22 18:07:51 -0800299 Status s = mTunerDvr->close();
Hongguang56637e92021-07-28 17:32:55 -0700300 mTunerDvr = nullptr;
Amy Zhang2d7026b2021-01-22 18:07:51 -0800301 return ClientHelper::getServiceSpecificErrorCode(s);
302 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800303
Amy Zhang9a9ed602020-12-07 16:37:33 -0800304 return Result::INVALID_STATE;
305}
Ray Chinf0a1ec82022-09-15 14:28:37 +0800306Result DvrClient::setStatusCheckIntervalHint(int64_t durationInMs) {
307 if (mTunerDvr == nullptr) {
308 return Result::INVALID_STATE;
309 }
310 if (durationInMs < 0) {
311 return Result::INVALID_ARGUMENT;
312 }
Amy Zhang9a9ed602020-12-07 16:37:33 -0800313
Ray Chinf0a1ec82022-09-15 14:28:37 +0800314 Status s = mTunerDvr->setStatusCheckIntervalHint(durationInMs);
315 return ClientHelper::getServiceSpecificErrorCode(s);
316}
Amy Zhang2d7026b2021-01-22 18:07:51 -0800317/////////////// TunerDvrCallback ///////////////////////
Amy Zhang2d7026b2021-01-22 18:07:51 -0800318TunerDvrCallback::TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)
319 : mDvrClientCallback(dvrClientCallback) {}
320
Hongguang56637e92021-07-28 17:32:55 -0700321Status TunerDvrCallback::onRecordStatus(RecordStatus status) {
322 if (mDvrClientCallback != nullptr) {
323 mDvrClientCallback->onRecordStatus(status);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800324 return Status::ok();
325 }
326 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
327}
328
Hongguang56637e92021-07-28 17:32:55 -0700329Status TunerDvrCallback::onPlaybackStatus(PlaybackStatus status) {
330 if (mDvrClientCallback != nullptr) {
331 mDvrClientCallback->onPlaybackStatus(status);
Amy Zhang2d7026b2021-01-22 18:07:51 -0800332 return Status::ok();
333 }
334 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
335}
336
Amy Zhang9a9ed602020-12-07 16:37:33 -0800337} // namespace android