diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 7620a79624243..3a5041732e1ba 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -712,6 +712,8 @@ public final class Tuner implements AutoCloseable { private native void nativeSetFileDescriptor(FileDescriptor fd); private native int nativeRead(int size); private native int nativeRead(byte[] bytes, int offset, int size); + private native int nativeWrite(int size); + private native int nativeWrite(byte[] bytes, int offset, int size); private Dvr() {} @@ -809,6 +811,20 @@ public final class Tuner implements AutoCloseable { } return nativeRead(bytes, offset, size); } + + /** + * Writes recording data to file. + */ + public int write(int size) { + return nativeWrite(size); + } + + /** + * Writes recording data to buffer. + */ + public int write(@NonNull byte[] bytes, int offset, int size) { + return nativeWrite(bytes, offset, size); + } } private Dvr openDvr(int type, int bufferSize) { diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index cfc56999add8c..1d327b2e9fb9e 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -118,6 +118,10 @@ sp Dvr::getIDvr() { return mDvrSp; } +DvrMQ& Dvr::getDvrMQ() { + return *mDvrMQ; +} + /////////////// FilterCallback /////////////////////// //TODO: implement filter callback Return FilterCallback::onFilterEvent(const DemuxFilterEvent& /*filterEvent*/) { @@ -1004,13 +1008,66 @@ static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) return ret; } -static int android_media_tv_Tuner_read_dvr_to_array( +static int android_media_tv_Tuner_read_dvr_from_array( JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */, jint /* size */) { //TODO: impl return 0; } +static int android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jint size) { + sp dvrSp = getDvr(env, dvr); + if (dvrSp == NULL) { + ALOGW("Failed to write dvr: dvr not found"); + return 0; + } + + if (dvrSp->mDvrMQ == NULL) { + ALOGW("Failed to write dvr: dvr not configured"); + return 0; + } + + DvrMQ& dvrMq = dvrSp->getDvrMQ(); + + int available = dvrMq.availableToRead(); + int toRead = std::min(size, available); + + int ret = 0; + DvrMQ::MemTransaction tx; + if (dvrMq.beginRead(toRead, &tx)) { + auto first = tx.getFirstRegion(); + auto data = first.getAddress(); + int length = first.getLength(); + int firstToRead = std::min(length, toRead); + ret = write(dvrSp->mFd, data, firstToRead); + if (ret < firstToRead) { + ALOGW("[DVR] MQ to file: %d bytes read, but %d bytes written", firstToRead, ret); + } else if (firstToRead < toRead) { + ALOGD("[DVR] read second region: %d bytes read, %d 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: %d bytes to be read, %d bytes written", toRead, ret); + if (!dvrMq.commitRead(ret)) { + ALOGE("[DVR] Error: failed to commit read!"); + } + + } else { + ALOGE("dvrMq.beginRead failed"); + } + + return ret; +} + +static int android_media_tv_Tuner_write_dvr_to_array( + JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */, + jint /* size */) { + //TODO: impl + return 0; +} static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init }, @@ -1077,7 +1134,9 @@ static const JNINativeMethod gDvrMethods[] = { { "nativeSetFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void *)android_media_tv_Tuner_dvr_set_fd }, { "nativeRead", "(I)I", (void *)android_media_tv_Tuner_read_dvr }, - { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_to_array }, + { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_from_array }, + { "nativeWrite", "(I)I", (void *)android_media_tv_Tuner_write_dvr }, + { "nativeWrite", "([BII)I", (void *)android_media_tv_Tuner_write_dvr_to_array }, }; static const JNINativeMethod gLnbMethods[] = { diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index d6956783d6c30..5c012bbebb9d3 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -85,6 +85,7 @@ struct Dvr : public RefBase { Dvr(sp sp, jweak obj); ~Dvr(); int close(); + DvrMQ& getDvrMQ(); sp getIDvr(); sp mDvrSp; jweak mDvrObj;