Add DvrClient and DvrClientCallback
Test: make libmedia_tv_tuner Bug: 174095851 Change-Id: I0614a8ca7ca8d177da3f8ad07dbe70c3f57d6f1e
This commit is contained in:
@@ -140,6 +140,7 @@ cc_library_shared {
|
||||
srcs: [
|
||||
"android_media_tv_Tuner.cpp",
|
||||
"tuner/DemuxClient.cpp",
|
||||
"tuner/DvrClient.cpp",
|
||||
"tuner/FilterClient.cpp",
|
||||
"tuner/FrontendClient.cpp",
|
||||
"tuner/TunerClient.cpp",
|
||||
|
||||
@@ -261,70 +261,38 @@ sp<ILnb> Lnb::getILnb() {
|
||||
return mLnbSp;
|
||||
}
|
||||
|
||||
/////////////// DvrCallback ///////////////////////
|
||||
Return<void> DvrCallback::onRecordStatus(RecordStatus status) {
|
||||
ALOGD("DvrCallback::onRecordStatus");
|
||||
/////////////// DvrClientCallbackImpl ///////////////////////
|
||||
void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
|
||||
ALOGD("DvrClientCallbackImpl::onRecordStatus");
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(
|
||||
mDvr,
|
||||
mDvrObj,
|
||||
gFields.onDvrRecordStatusID,
|
||||
(jint) status);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus status) {
|
||||
ALOGD("DvrCallback::onPlaybackStatus");
|
||||
void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
|
||||
ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(
|
||||
mDvr,
|
||||
mDvrObj,
|
||||
gFields.onDvrPlaybackStatusID,
|
||||
(jint) status);
|
||||
return Void();
|
||||
}
|
||||
|
||||
void DvrCallback::setDvr(const jobject dvr) {
|
||||
ALOGD("DvrCallback::setDvr");
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
mDvr = env->NewWeakGlobalRef(dvr);
|
||||
void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
|
||||
ALOGD("DvrClientCallbackImpl::setDvr");
|
||||
mDvrObj = dvrObj;
|
||||
}
|
||||
|
||||
DvrCallback::~DvrCallback() {
|
||||
DvrClientCallbackImpl::~DvrClientCallbackImpl() {
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
if (mDvr != NULL) {
|
||||
env->DeleteWeakGlobalRef(mDvr);
|
||||
mDvr = NULL;
|
||||
if (mDvrObj != NULL) {
|
||||
env->DeleteWeakGlobalRef(mDvrObj);
|
||||
mDvrObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////// Dvr ///////////////////////
|
||||
|
||||
Dvr::Dvr(sp<IDvr> sp, jobject obj) : mDvrSp(sp), mDvrMQEventFlag(nullptr) {
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
mDvrObj = env->NewWeakGlobalRef(obj);
|
||||
}
|
||||
|
||||
Dvr::~Dvr() {
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
env->DeleteWeakGlobalRef(mDvrObj);
|
||||
mDvrObj = NULL;
|
||||
}
|
||||
|
||||
jint Dvr::close() {
|
||||
Result r = mDvrSp->close();
|
||||
if (r == Result::SUCCESS) {
|
||||
EventFlag::deleteEventFlag(&mDvrMQEventFlag);
|
||||
}
|
||||
return (jint) r;
|
||||
}
|
||||
|
||||
sp<IDvr> Dvr::getIDvr() {
|
||||
return mDvrSp;
|
||||
}
|
||||
|
||||
MQ& Dvr::getDvrMQ() {
|
||||
return *mDvrMQ;
|
||||
}
|
||||
|
||||
/////////////// C2DataIdInfo ///////////////////////
|
||||
|
||||
C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) {
|
||||
@@ -1840,9 +1808,7 @@ jobject JTuner::openDescrambler() {
|
||||
|
||||
jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
|
||||
if (mDemux == NULL || mDemuxClient == NULL) {
|
||||
if (openDemux() != Result::SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<FilterClient> filterClient;
|
||||
@@ -1906,21 +1872,14 @@ jobject JTuner::openTimeFilter() {
|
||||
|
||||
jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
|
||||
ALOGD("JTuner::openDvr");
|
||||
if (mDemux == NULL) {
|
||||
if (openDemux() != Result::SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
if (mDemuxClient == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sp<IDvr> iDvrSp;
|
||||
sp<DvrCallback> callback = new DvrCallback();
|
||||
Result res;
|
||||
mDemux->openDvr(type, (uint32_t) bufferSize, callback,
|
||||
[&](Result r, const sp<IDvr>& dvr) {
|
||||
res = r;
|
||||
iDvrSp = dvr;
|
||||
});
|
||||
sp<DvrClient> dvrClient;
|
||||
sp<DvrClientCallbackImpl> callback = new DvrClientCallbackImpl();
|
||||
dvrClient = mDemuxClient->openDvr(type, (int) bufferSize, callback);
|
||||
|
||||
if (res != Result::SUCCESS || iDvrSp == NULL) {
|
||||
if (dvrClient == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1932,21 +1891,19 @@ jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
|
||||
env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
|
||||
gFields.dvrRecorderInitID,
|
||||
mObject);
|
||||
sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
|
||||
dvrSp->incStrong(dvrObj);
|
||||
env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrSp.get());
|
||||
dvrClient->incStrong(dvrObj);
|
||||
env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrClient.get());
|
||||
} else {
|
||||
dvrObj =
|
||||
env->NewObject(
|
||||
env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
|
||||
gFields.dvrPlaybackInitID,
|
||||
mObject);
|
||||
sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
|
||||
dvrSp->incStrong(dvrObj);
|
||||
env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrSp.get());
|
||||
dvrClient->incStrong(dvrObj);
|
||||
env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrClient.get());
|
||||
}
|
||||
|
||||
callback->setDvr(dvrObj);
|
||||
callback->setDvr(env->NewWeakGlobalRef(dvrObj));
|
||||
|
||||
return dvrObj;
|
||||
}
|
||||
@@ -3304,12 +3261,12 @@ static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder
|
||||
return dvrSettings;
|
||||
}
|
||||
|
||||
static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) {
|
||||
static sp<DvrClient> getDvrClient(JNIEnv *env, jobject dvr) {
|
||||
bool isRecorder =
|
||||
env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
|
||||
jfieldID fieldId =
|
||||
isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext;
|
||||
return (Dvr *)env->GetLongField(dvr, fieldId);
|
||||
return (DvrClient *)env->GetLongField(dvr, fieldId);
|
||||
}
|
||||
|
||||
static void android_media_tv_Tuner_native_init(JNIEnv *env) {
|
||||
@@ -3910,33 +3867,6 @@ static Result configureIpFilterContextId(
|
||||
return filterClient->configureIpFilterContextId(cid);
|
||||
}
|
||||
|
||||
static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
|
||||
jlong offset, jlong size) {
|
||||
ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset);
|
||||
|
||||
jlong available = mq->availableToRead();
|
||||
ALOGD("copyData, available=%ld", (long) available);
|
||||
size = std::min(size, available);
|
||||
|
||||
jboolean isCopy;
|
||||
jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
|
||||
ALOGD("copyData, isCopy=%d", isCopy);
|
||||
if (dst == nullptr) {
|
||||
jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mq->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
|
||||
env->ReleaseByteArrayElements(buffer, dst, 0);
|
||||
flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
|
||||
} else {
|
||||
jniThrowRuntimeException(env, "Failed to read FMQ");
|
||||
env->ReleaseByteArrayElements(buffer, dst, 0);
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool isAvFilterSettings(DemuxFilterSettings filterSettings) {
|
||||
return (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts
|
||||
&& filterSettings.ts().filterSettings.getDiscriminator()
|
||||
@@ -4068,7 +3998,7 @@ static jint android_media_tv_Tuner_read_filter_fmq(
|
||||
if (filterClient == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Failed to read filter FMQ: filter client not found");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
jboolean isCopy;
|
||||
@@ -4076,14 +4006,11 @@ static jint android_media_tv_Tuner_read_filter_fmq(
|
||||
ALOGD("copyData, isCopy=%d", isCopy);
|
||||
if (dst == nullptr) {
|
||||
jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
int realReadSize = filterClient->read(reinterpret_cast<uint8_t*>(dst) + offset, size);
|
||||
env->ReleaseByteArrayElements(buffer, dst, 0);
|
||||
if (realReadSize < 0) {
|
||||
return (jint) Result::UNKNOWN_ERROR;
|
||||
}
|
||||
return (jint) Result::SUCCESS;
|
||||
return (jint) realReadSize;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
|
||||
@@ -4283,106 +4210,80 @@ static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jin
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<FilterClient> filterClient = getFilterClient(env, filter);
|
||||
if (filterClient == NULL) {
|
||||
return (jint) Result::INVALID_ARGUMENT;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
// TODO: use filter client once dvrClient is ready
|
||||
sp<IFilter> iFilterSp = filterClient->getHalFilter();
|
||||
Result result = iDvrSp->attachFilter(iFilterSp);
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
Result result = dvrClient->attachFilter(filterClient);
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<FilterClient> filterClient = getFilterClient(env, filter);
|
||||
if (filterClient == NULL) {
|
||||
return (jint) Result::INVALID_ARGUMENT;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
// TODO: use filter client once dvrClient is ready
|
||||
sp<IFilter> iFilterSp = filterClient->getHalFilter();
|
||||
Result result = iDvrSp->detachFilter(iFilterSp);
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
Result result = dvrClient->detachFilter(filterClient);
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to configure dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to configure dvr: dvr client not found");
|
||||
return (int)Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
bool isRecorder =
|
||||
env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
|
||||
Result result = iDvrSp->configure(getDvrSettings(env, settings, isRecorder));
|
||||
if (result != Result::SUCCESS) {
|
||||
return (jint) result;
|
||||
}
|
||||
MQDescriptorSync<uint8_t> dvrMQDesc;
|
||||
Result getQueueDescResult = Result::UNKNOWN_ERROR;
|
||||
iDvrSp->getQueueDesc(
|
||||
[&](Result r, const MQDescriptorSync<uint8_t>& desc) {
|
||||
dvrMQDesc = desc;
|
||||
getQueueDescResult = r;
|
||||
ALOGD("getDvrQueueDesc");
|
||||
});
|
||||
if (getQueueDescResult == Result::SUCCESS) {
|
||||
dvrSp->mDvrMQ = std::make_unique<MQ>(dvrMQDesc, true);
|
||||
EventFlag::createEventFlag(
|
||||
dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
|
||||
}
|
||||
return (jint) getQueueDescResult;
|
||||
Result result = dvrClient->configure(getDvrSettings(env, settings, isRecorder));
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to start dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to start dvr: dvr client not found");
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
Result result = iDvrSp->start();
|
||||
Result result = dvrClient->start();
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to stop dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to stop dvr: dvr client not found");
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
Result result = iDvrSp->stop();
|
||||
Result result = dvrClient->stop();
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to flush dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to flush dvr: dvr client not found");
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
sp<IDvr> iDvrSp = dvrSp->getIDvr();
|
||||
Result result = iDvrSp->flush();
|
||||
Result result = dvrClient->flush();
|
||||
return (jint) result;
|
||||
}
|
||||
|
||||
static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to close dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to close dvr: dvr client not found");
|
||||
return (jint) Result::NOT_INITIALIZED;
|
||||
}
|
||||
return dvrSp->close();
|
||||
return (jint) dvrClient->close();
|
||||
}
|
||||
|
||||
static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) {
|
||||
@@ -4427,170 +4328,76 @@ static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
|
||||
}
|
||||
|
||||
static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jint fd) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGD("Failed to set FD for dvr: dvr not found");
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGD("Failed to set FD for dvr: dvr client not found");
|
||||
return;
|
||||
}
|
||||
dvrSp->mFd = (int) fd;
|
||||
ALOGD("set fd = %d", dvrSp->mFd);
|
||||
dvrClient->setFd((int)fd);
|
||||
ALOGD("set fd = %d", fd);
|
||||
}
|
||||
|
||||
static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Failed to read dvr: dvr not found");
|
||||
return 0;
|
||||
"Failed to read dvr: dvr client not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long available = dvrSp->mDvrMQ->availableToWrite();
|
||||
long write = std::min((long) size, available);
|
||||
|
||||
MQ::MemTransaction tx;
|
||||
long ret = 0;
|
||||
if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
|
||||
auto first = tx.getFirstRegion();
|
||||
auto data = first.getAddress();
|
||||
long length = first.getLength();
|
||||
long firstToWrite = std::min(length, write);
|
||||
ret = read(dvrSp->mFd, data, firstToWrite);
|
||||
|
||||
if (ret < 0) {
|
||||
ALOGE("[DVR] Failed to read from FD: %s", strerror(errno));
|
||||
jniThrowRuntimeException(env, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (ret < firstToWrite) {
|
||||
ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
|
||||
firstToWrite, ret);
|
||||
} else if (firstToWrite < write) {
|
||||
ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
|
||||
auto second = tx.getSecondRegion();
|
||||
data = second.getAddress();
|
||||
length = second.getLength();
|
||||
int secondToWrite = std::min(length, write - firstToWrite);
|
||||
ret += read(dvrSp->mFd, data, secondToWrite);
|
||||
}
|
||||
ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
|
||||
if (!dvrSp->mDvrMQ->commitWrite(ret)) {
|
||||
ALOGE("[DVR] Error: failed to commit write!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
ALOGE("dvrMq.beginWrite failed");
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
|
||||
}
|
||||
return (jlong) ret;
|
||||
return (jlong) dvrClient->readFromFile(size);
|
||||
}
|
||||
|
||||
static jlong android_media_tv_Tuner_read_dvr_from_array(
|
||||
JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGW("Failed to read dvr: dvr not found");
|
||||
return 0;
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGW("Failed to read dvr: dvr client not found");
|
||||
return -1;
|
||||
}
|
||||
if (dvrSp->mDvrMQ == NULL) {
|
||||
ALOGW("Failed to read dvr: dvr not configured");
|
||||
return 0;
|
||||
}
|
||||
|
||||
jlong available = dvrSp->mDvrMQ->availableToWrite();
|
||||
size = std::min(size, available);
|
||||
|
||||
jboolean isCopy;
|
||||
jbyte *src = env->GetByteArrayElements(buffer, &isCopy);
|
||||
if (src == nullptr) {
|
||||
ALOGD("Failed to GetByteArrayElements");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
long realSize = dvrClient->readFromBuffer(reinterpret_cast<unsigned char*>(src) + offset, size);
|
||||
env->ReleaseByteArrayElements(buffer, src, 0);
|
||||
return (jlong) realSize;
|
||||
|
||||
if (dvrSp->mDvrMQ->write(reinterpret_cast<unsigned char*>(src) + offset, size)) {
|
||||
env->ReleaseByteArrayElements(buffer, src, 0);
|
||||
dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
|
||||
} else {
|
||||
ALOGD("Failed to write FMQ");
|
||||
env->ReleaseByteArrayElements(buffer, src, 0);
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Failed to write dvr: dvr not found");
|
||||
return 0;
|
||||
"Failed to write dvr: dvr client not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dvrSp->mDvrMQ == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"Failed to write dvr: dvr not configured");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MQ& dvrMq = dvrSp->getDvrMQ();
|
||||
|
||||
long available = dvrMq.availableToRead();
|
||||
long toRead = std::min((long) size, available);
|
||||
|
||||
long ret = 0;
|
||||
MQ::MemTransaction tx;
|
||||
if (dvrMq.beginRead(toRead, &tx)) {
|
||||
auto first = tx.getFirstRegion();
|
||||
auto data = first.getAddress();
|
||||
long length = first.getLength();
|
||||
long firstToRead = std::min(length, toRead);
|
||||
ret = write(dvrSp->mFd, data, firstToRead);
|
||||
|
||||
if (ret < 0) {
|
||||
ALOGE("[DVR] Failed to write to FD: %s", strerror(errno));
|
||||
jniThrowRuntimeException(env, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (ret < firstToRead) {
|
||||
ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
|
||||
} else if (firstToRead < toRead) {
|
||||
ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
|
||||
auto second = tx.getSecondRegion();
|
||||
data = second.getAddress();
|
||||
length = second.getLength();
|
||||
int secondToRead = toRead - firstToRead;
|
||||
ret += write(dvrSp->mFd, data, secondToRead);
|
||||
}
|
||||
ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
|
||||
if (!dvrMq.commitRead(ret)) {
|
||||
ALOGE("[DVR] Error: failed to commit read!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
ALOGE("dvrMq.beginRead failed");
|
||||
}
|
||||
if (ret > 0) {
|
||||
dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
|
||||
}
|
||||
|
||||
return (jlong) ret;
|
||||
return (jlong) dvrClient->writeToFile(size);
|
||||
}
|
||||
|
||||
static jlong android_media_tv_Tuner_write_dvr_to_array(
|
||||
JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
|
||||
sp<Dvr> dvrSp = getDvr(env, dvr);
|
||||
if (dvrSp == NULL) {
|
||||
ALOGW("Failed to write dvr: dvr not found");
|
||||
return 0;
|
||||
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
|
||||
if (dvrClient == NULL) {
|
||||
ALOGW("Failed to read dvr: dvr client not found");
|
||||
return -1;
|
||||
}
|
||||
if (dvrSp->mDvrMQ == NULL) {
|
||||
ALOGW("Failed to write dvr: dvr not configured");
|
||||
return 0;
|
||||
|
||||
jboolean isCopy;
|
||||
jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
|
||||
ALOGD("copyData, isCopy=%d", isCopy);
|
||||
if (dst == nullptr) {
|
||||
jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
|
||||
return -1;
|
||||
}
|
||||
return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size);
|
||||
|
||||
long realSize = dvrClient->writeToBuffer(reinterpret_cast<unsigned char*>(dst) + offset, size);
|
||||
env->ReleaseByteArrayElements(buffer, dst, 0);
|
||||
return (jlong) realSize;
|
||||
}
|
||||
|
||||
static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) {
|
||||
|
||||
@@ -105,29 +105,14 @@ struct Lnb : public RefBase {
|
||||
jweak mLnbObj;
|
||||
};
|
||||
|
||||
struct DvrCallback : public IDvrCallback {
|
||||
~DvrCallback();
|
||||
virtual Return<void> onRecordStatus(RecordStatus status);
|
||||
virtual Return<void> onPlaybackStatus(PlaybackStatus status);
|
||||
struct DvrClientCallbackImpl : public DvrClientCallback {
|
||||
~DvrClientCallbackImpl();
|
||||
virtual void onRecordStatus(RecordStatus status);
|
||||
virtual void onPlaybackStatus(PlaybackStatus status);
|
||||
|
||||
void setDvr(const jobject dvr);
|
||||
void setDvr(jweak dvrObj);
|
||||
private:
|
||||
jweak mDvr;
|
||||
};
|
||||
|
||||
struct Dvr : public RefBase {
|
||||
Dvr(sp<IDvr> sp, jweak obj);
|
||||
~Dvr();
|
||||
jint close();
|
||||
MQ& getDvrMQ();
|
||||
sp<IDvr> getIDvr();
|
||||
// TODO: remove after migrate to client lib
|
||||
sp<IDvr> mDvrSp;
|
||||
jweak mDvrObj;
|
||||
std::unique_ptr<MQ> mDvrMQ;
|
||||
EventFlag* mDvrMQEventFlag;
|
||||
std::string mFilePath;
|
||||
int mFd;
|
||||
};
|
||||
|
||||
struct MediaEvent : public RefBase {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "FrontendClient"
|
||||
#define LOG_TAG "DemuxClient"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <utils/Log.h>
|
||||
@@ -116,7 +116,21 @@ long DemuxClient::getAvSyncTime(int avSyncHwId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//DvrClient openDvr(int dvbType, int bufferSize, DvrClientCallback cb);
|
||||
sp<DvrClient> DemuxClient::openDvr(DvrType dvbType, int bufferSize, sp<DvrClientCallback> cb) {
|
||||
// TODO: pending aidl interface
|
||||
|
||||
if (mDemux != NULL) {
|
||||
sp<HidlDvrCallback> callback = new HidlDvrCallback(cb);
|
||||
sp<IDvr> hidlDvr = openHidlDvr(dvbType, bufferSize, callback);
|
||||
if (hidlDvr != NULL) {
|
||||
sp<DvrClient> dvrClient = new DvrClient();
|
||||
dvrClient->setHidlDvr(hidlDvr);
|
||||
return dvrClient;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Result DemuxClient::connectCiCam(int ciCamId) {
|
||||
// pending aidl interface
|
||||
@@ -173,4 +187,24 @@ sp<IFilter> DemuxClient::openHidlFilter(DemuxFilterType type, int bufferSize,
|
||||
|
||||
return hidlFilter;
|
||||
}
|
||||
|
||||
sp<IDvr> DemuxClient::openHidlDvr(DvrType dvrType, int bufferSize,
|
||||
sp<HidlDvrCallback> callback) {
|
||||
if (mDemux == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<IDvr> hidlDvr;
|
||||
Result res;
|
||||
mDemux->openDvr(dvrType, bufferSize, callback,
|
||||
[&](Result r, const sp<IDvr>& dvr) {
|
||||
hidlDvr = dvr;
|
||||
res = r;
|
||||
});
|
||||
if (res != Result::SUCCESS || hidlDvr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hidlDvr;
|
||||
}
|
||||
} // namespace android
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <android/hardware/tv/tuner/1.0/IDemux.h>
|
||||
#include <android/hardware/tv/tuner/1.1/types.h>
|
||||
|
||||
#include "DvrClient.h"
|
||||
#include "DvrClientCallback.h"
|
||||
#include "FilterClient.h"
|
||||
#include "FilterClientCallback.h"
|
||||
#include "FrontendClient.h"
|
||||
@@ -28,6 +30,7 @@
|
||||
//using ::aidl::android::media::tv::tuner::ITunerDemux;
|
||||
|
||||
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
|
||||
using ::android::hardware::tv::tuner::V1_0::DvrType;
|
||||
using ::android::hardware::tv::tuner::V1_0::IDemux;
|
||||
|
||||
using namespace std;
|
||||
@@ -68,8 +71,7 @@ public:
|
||||
/**
|
||||
* Open a DVR (Digital Video Record) client.
|
||||
*/
|
||||
// TODO: handle DvrClient and callback
|
||||
//DvrClient openDvr(int dvbType, int bufferSize, DvrClientCallback cb);
|
||||
sp<DvrClient> openDvr(DvrType dvbType, int bufferSize, sp<DvrClientCallback> cb);
|
||||
|
||||
/**
|
||||
* Connect Conditional Access Modules (CAM) through Common Interface (CI).
|
||||
@@ -88,6 +90,7 @@ public:
|
||||
|
||||
private:
|
||||
sp<IFilter> openHidlFilter(DemuxFilterType type, int bufferSize, sp<HidlFilterCallback> cb);
|
||||
sp<IDvr> openHidlDvr(DvrType type, int bufferSize, sp<HidlDvrCallback> cb);
|
||||
|
||||
/**
|
||||
* An AIDL Tuner Demux Singleton assigned at the first time the Tuner Client
|
||||
|
||||
329
media/jni/tuner/DvrClient.cpp
Normal file
329
media/jni/tuner/DvrClient.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DvrClient"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "DvrClient.h"
|
||||
|
||||
using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
|
||||
using ::android::hardware::tv::tuner::V1_0::Result;
|
||||
|
||||
namespace android {
|
||||
|
||||
/////////////// DvrClient ///////////////////////
|
||||
|
||||
// TODO: pending aidl interface
|
||||
DvrClient::DvrClient() {
|
||||
//mTunerDvr = tunerDvr;
|
||||
mFd = -1;
|
||||
mDvrMQ = NULL;
|
||||
mDvrMQEventFlag = NULL;
|
||||
}
|
||||
|
||||
DvrClient::~DvrClient() {
|
||||
//mTunerDvr = NULL;
|
||||
mDvr = NULL;
|
||||
mFd = -1;
|
||||
mDvrMQ = NULL;
|
||||
mDvrMQEventFlag = NULL;
|
||||
}
|
||||
|
||||
// TODO: remove after migration to Tuner Service is done.
|
||||
void DvrClient::setHidlDvr(sp<IDvr> dvr) {
|
||||
mDvr = dvr;
|
||||
}
|
||||
|
||||
void DvrClient::setFd(int fd) {
|
||||
mFd = fd;
|
||||
}
|
||||
|
||||
long DvrClient::readFromFile(long size) {
|
||||
if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
|
||||
ALOGE("Failed to readFromFile. DVR mq is not configured");
|
||||
return -1;
|
||||
}
|
||||
if (mFd < 0) {
|
||||
ALOGE("Failed to readFromFile. File is not configured");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long available = mDvrMQ->availableToWrite();
|
||||
long write = min(size, available);
|
||||
|
||||
MQ::MemTransaction tx;
|
||||
long ret = 0;
|
||||
if (mDvrMQ->beginWrite(write, &tx)) {
|
||||
auto first = tx.getFirstRegion();
|
||||
auto data = first.getAddress();
|
||||
long length = first.getLength();
|
||||
long firstToWrite = min(length, write);
|
||||
ret = read(mFd, data, firstToWrite);
|
||||
|
||||
if (ret < 0) {
|
||||
ALOGE("Failed to read from FD: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret < firstToWrite) {
|
||||
ALOGW("file to MQ, first region: %ld bytes to write, but %ld bytes written",
|
||||
firstToWrite, ret);
|
||||
} else if (firstToWrite < write) {
|
||||
ALOGD("write second region: %ld bytes written, %ld bytes in total", ret, write);
|
||||
auto second = tx.getSecondRegion();
|
||||
data = second.getAddress();
|
||||
length = second.getLength();
|
||||
int secondToWrite = std::min(length, write - firstToWrite);
|
||||
ret += read(mFd, data, secondToWrite);
|
||||
}
|
||||
ALOGD("file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
|
||||
if (!mDvrMQ->commitWrite(ret)) {
|
||||
ALOGE("Error: failed to commit write!");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ALOGE("dvrMq.beginWrite failed");
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
long DvrClient::readFromBuffer(uint8_t* buffer, long size) {
|
||||
if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
|
||||
ALOGE("Failed to readFromBuffer. DVR mq is not configured");
|
||||
return -1;
|
||||
}
|
||||
if (buffer == nullptr) {
|
||||
ALOGE("Failed to readFromBuffer. Buffer can't be null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long available = mDvrMQ->availableToWrite();
|
||||
size = min(size, available);
|
||||
|
||||
if (mDvrMQ->write(buffer, size)) {
|
||||
mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
|
||||
} else {
|
||||
ALOGD("Failed to write FMQ");
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
long DvrClient::writeToFile(long size) {
|
||||
if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
|
||||
ALOGE("Failed to writeToFile. DVR mq is not configured");
|
||||
return -1;
|
||||
}
|
||||
if (mFd < 0) {
|
||||
ALOGE("Failed to writeToFile. File is not configured");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long available = mDvrMQ->availableToRead();
|
||||
long toRead = min(size, available);
|
||||
|
||||
long ret = 0;
|
||||
MQ::MemTransaction tx;
|
||||
if (mDvrMQ->beginRead(toRead, &tx)) {
|
||||
auto first = tx.getFirstRegion();
|
||||
auto data = first.getAddress();
|
||||
long length = first.getLength();
|
||||
long firstToRead = std::min(length, toRead);
|
||||
ret = write(mFd, data, firstToRead);
|
||||
|
||||
if (ret < 0) {
|
||||
ALOGE("Failed to write to FD: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret < firstToRead) {
|
||||
ALOGW("MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
|
||||
} else if (firstToRead < toRead) {
|
||||
ALOGD("read second region: %ld bytes read, %ld bytes in total", ret, toRead);
|
||||
auto second = tx.getSecondRegion();
|
||||
data = second.getAddress();
|
||||
length = second.getLength();
|
||||
int secondToRead = toRead - firstToRead;
|
||||
ret += write(mFd, data, secondToRead);
|
||||
}
|
||||
ALOGD("MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
|
||||
if (!mDvrMQ->commitRead(ret)) {
|
||||
ALOGE("Error: failed to commit read!");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ALOGE("dvrMq.beginRead failed");
|
||||
}
|
||||
if (ret > 0) {
|
||||
mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long DvrClient::writeToBuffer(uint8_t* buffer, long size) {
|
||||
if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
|
||||
ALOGE("Failed to writetoBuffer. DVR mq is not configured");
|
||||
return -1;
|
||||
}
|
||||
if (buffer == nullptr) {
|
||||
ALOGE("Failed to writetoBuffer. Buffer can't be null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
long available = mDvrMQ->availableToRead();
|
||||
size = min(size, available);
|
||||
|
||||
if (mDvrMQ->read(buffer, size)) {
|
||||
mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
|
||||
} else {
|
||||
ALOGD("Failed to write FMQ");
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
Result DvrClient::configure(DvrSettings settings) {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
Result res = mDvr->configure(settings);
|
||||
if (res == Result::SUCCESS) {
|
||||
MQDescriptorSync<uint8_t> dvrMQDesc;
|
||||
res = getQueueDesc(dvrMQDesc);
|
||||
if (res == Result::SUCCESS) {
|
||||
mDvrMQ = make_unique<MQ>(dvrMQDesc, true);
|
||||
EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
sp<IFilter> hidlFilter = filterClient->getHalFilter();
|
||||
if (hidlFilter == NULL) {
|
||||
return Result::INVALID_ARGUMENT;
|
||||
}
|
||||
return mDvr->attachFilter(hidlFilter);
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
sp<IFilter> hidlFilter = filterClient->getHalFilter();
|
||||
if (hidlFilter == NULL) {
|
||||
return Result::INVALID_ARGUMENT;
|
||||
}
|
||||
return mDvr->detachFilter(hidlFilter);
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::start() {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
return mDvr->start();
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::stop() {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
return mDvr->stop();
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::flush() {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
return mDvr->flush();
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
Result DvrClient::close() {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
Result res = mDvr->close();
|
||||
if (res == Result::SUCCESS) {
|
||||
mDvr = NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
/////////////// IDvrCallback ///////////////////////
|
||||
|
||||
HidlDvrCallback::HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback)
|
||||
: mDvrClientCallback(dvrClientCallback) {}
|
||||
|
||||
Return<void> HidlDvrCallback::onRecordStatus(const RecordStatus status) {
|
||||
if (mDvrClientCallback != NULL) {
|
||||
mDvrClientCallback->onRecordStatus(status);
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> HidlDvrCallback::onPlaybackStatus(const PlaybackStatus status) {
|
||||
if (mDvrClientCallback != NULL) {
|
||||
mDvrClientCallback->onPlaybackStatus(status);
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
/////////////// DvrClient Helper Methods ///////////////////////
|
||||
|
||||
Result DvrClient::getQueueDesc(MQDesc& dvrMQDesc) {
|
||||
// pending aidl interface
|
||||
|
||||
if (mDvr != NULL) {
|
||||
Result res = Result::UNKNOWN_ERROR;
|
||||
mDvr->getQueueDesc([&](Result r, const MQDesc& desc) {
|
||||
dvrMQDesc = desc;
|
||||
res = r;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
} // namespace android
|
||||
162
media/jni/tuner/DvrClient.h
Normal file
162
media/jni/tuner/DvrClient.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_MEDIA_TV_DVR_CLIENT_H_
|
||||
#define _ANDROID_MEDIA_TV_DVR_CLIENT_H_
|
||||
|
||||
//#include <aidl/android/media/tv/tuner/ITunerDvr.h>
|
||||
#include <android/hardware/tv/tuner/1.0/IDvr.h>
|
||||
#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
|
||||
#include <android/hardware/tv/tuner/1.1/types.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
|
||||
#include "DvrClientCallback.h"
|
||||
#include "FilterClient.h"
|
||||
|
||||
//using ::aidl::android::media::tv::tuner::ITunerDvr;
|
||||
|
||||
using ::android::hardware::EventFlag;
|
||||
using ::android::hardware::MQDescriptorSync;
|
||||
using ::android::hardware::MessageQueue;
|
||||
using ::android::hardware::tv::tuner::V1_0::DvrSettings;
|
||||
using ::android::hardware::tv::tuner::V1_0::IDvr;
|
||||
using ::android::hardware::tv::tuner::V1_0::IDvrCallback;
|
||||
|
||||
using namespace std;
|
||||
|
||||
using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
using MQDesc = MQDescriptorSync<uint8_t>;
|
||||
|
||||
namespace android {
|
||||
|
||||
// TODO: pending aidl interface
|
||||
/*class TunerDvrCallback : public BnTunerDvrCallback {
|
||||
|
||||
public:
|
||||
TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback);
|
||||
|
||||
Status onRecordStatus(int status);
|
||||
Status onPlaybackStatus(int status);
|
||||
|
||||
private:
|
||||
sp<DvrClientCallback> mDvrClientCallback;
|
||||
};*/
|
||||
|
||||
struct HidlDvrCallback : public IDvrCallback {
|
||||
|
||||
public:
|
||||
HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback);
|
||||
virtual Return<void> onRecordStatus(const RecordStatus status);
|
||||
virtual Return<void> onPlaybackStatus(const PlaybackStatus status);
|
||||
|
||||
private:
|
||||
sp<DvrClientCallback> mDvrClientCallback;
|
||||
};
|
||||
|
||||
struct DvrClient : public RefBase {
|
||||
|
||||
public:
|
||||
DvrClient();
|
||||
~DvrClient();
|
||||
|
||||
// TODO: remove after migration to Tuner Service is done.
|
||||
void setHidlDvr(sp<IDvr> dvr);
|
||||
|
||||
/**
|
||||
* Set the DVR file descriptor.
|
||||
*/
|
||||
void setFd(int fd);
|
||||
|
||||
/**
|
||||
* Read data from file with given size. Return the actual read size.
|
||||
*/
|
||||
long readFromFile(long size);
|
||||
|
||||
/**
|
||||
* Read data from the given buffer with given size. Return the actual read size.
|
||||
*/
|
||||
long readFromBuffer(uint8_t* buffer, long size);
|
||||
|
||||
/**
|
||||
* Write data to file with given size. Return the actual write size.
|
||||
*/
|
||||
long writeToFile(long size);
|
||||
|
||||
/**
|
||||
* Write data to the given buffer with given size. Return the actual write size.
|
||||
*/
|
||||
long writeToBuffer(uint8_t* buffer, long size);
|
||||
|
||||
/**
|
||||
* Configure the DVR.
|
||||
*/
|
||||
Result configure(DvrSettings settings);
|
||||
|
||||
/**
|
||||
* Attach one filter to DVR interface for recording.
|
||||
*/
|
||||
Result attachFilter(sp<FilterClient> filterClient);
|
||||
|
||||
/**
|
||||
* Detach one filter from the DVR's recording.
|
||||
*/
|
||||
Result detachFilter(sp<FilterClient> filterClient);
|
||||
|
||||
/**
|
||||
* Start DVR.
|
||||
*/
|
||||
Result start();
|
||||
|
||||
/**
|
||||
* Stop DVR.
|
||||
*/
|
||||
Result stop();
|
||||
|
||||
/**
|
||||
* Flush DVR data.
|
||||
*/
|
||||
Result flush();
|
||||
|
||||
/**
|
||||
* close the DVR instance to release resource for DVR.
|
||||
*/
|
||||
Result close();
|
||||
|
||||
private:
|
||||
Result getQueueDesc(MQDesc& dvrMQDesc);
|
||||
|
||||
/**
|
||||
* An AIDL Tuner Dvr Singleton assigned at the first time the Tuner Client
|
||||
* opens a dvr. Default null when dvr is not opened.
|
||||
*/
|
||||
// TODO: pending on aidl interface
|
||||
//shared_ptr<ITunerDvr> mTunerDvr;
|
||||
|
||||
/**
|
||||
* A Dvr HAL interface that is ready before migrating to the TunerDvr.
|
||||
* This is a temprary interface before Tuner Framework migrates to use TunerService.
|
||||
* Default null when the HAL service does not exist.
|
||||
*/
|
||||
sp<IDvr> mDvr;
|
||||
|
||||
unique_ptr<MQ> mDvrMQ;
|
||||
EventFlag* mDvrMQEventFlag;
|
||||
string mFilePath;
|
||||
int mFd;
|
||||
};
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_MEDIA_TV_DVR_CLIENT_H_
|
||||
33
media/jni/tuner/DvrClientCallback.h
Normal file
33
media/jni/tuner/DvrClientCallback.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
|
||||
#define _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
|
||||
|
||||
using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
|
||||
using ::android::hardware::tv::tuner::V1_0::RecordStatus;
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace android {
|
||||
|
||||
struct DvrClientCallback : public RefBase {
|
||||
virtual void onRecordStatus(const RecordStatus status);
|
||||
virtual void onPlaybackStatus(const PlaybackStatus status);
|
||||
};
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
|
||||
@@ -40,6 +40,8 @@ TunerClient::TunerClient() {
|
||||
// Connect with Tuner Service.
|
||||
::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
|
||||
mTunerService = ITunerService::fromBinder(binder);
|
||||
// TODO: Remove after JNI migration is done.
|
||||
mTunerService = NULL;
|
||||
if (mTunerService == NULL) {
|
||||
ALOGE("Failed to get tuner service");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user