Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59076763 authored by Shubang Lu's avatar Shubang Lu Committed by Android (Google) Code Review
Browse files

Merge "Read data from file for DVR"

parents 6a3a7e9a ba21a7f8
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.io.FileDescriptor;
import java.util.List;

/**
@@ -765,6 +766,9 @@ public final class Tuner implements AutoCloseable {
        private native int nativeStopDvr();
        private native int nativeFlushDvr();
        private native int nativeClose();
        private native void nativeSetFileDescriptor(FileDescriptor fd);
        private native int nativeRead(int size);
        private native int nativeRead(byte[] bytes, int offset, int size);

        private Dvr() {}

@@ -837,6 +841,31 @@ public final class Tuner implements AutoCloseable {
        public int close() {
            return nativeClose();
        }

        /**
         * Sets file descriptor to read/write data.
         */
        public void setFileDescriptor(FileDescriptor fd) {
            nativeSetFileDescriptor(fd);
        }

        /**
         * Reads data from the file for DVR playback.
         */
        public int read(int size) {
            return nativeRead(size);
        }

        /**
         * Reads data from the buffer for DVR playback.
         */
        public int read(@NonNull byte[] bytes, int offset, int size) {
            if (size + offset > bytes.length) {
                throw new ArrayIndexOutOfBoundsException(
                        "Array length=" + bytes.length + ", offset=" + offset + ", size=" + size);
            }
            return nativeRead(bytes, offset, size);
        }
    }

    private Dvr openDvr(int type, int bufferSize) {
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ cc_library_shared {
        "libfmq",
        "libhidlbase",
        "liblog",
        "libnativehelper",
        "libutils",
    ],

+92 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/JNIHelp.h>

#pragma GCC diagnostic ignored "-Wunused-function"

@@ -92,7 +93,7 @@ Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus /*status*/) {
}

void DvrCallback::setDvr(const jobject dvr) {
    ALOGD("FilterCallback::setDvr");
    ALOGD("DvrCallback::setDvr");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    mDvr = env->NewWeakGlobalRef(dvr);
}
@@ -101,6 +102,18 @@ void DvrCallback::setDvr(const jobject dvr) {

Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj) {}

Dvr::~Dvr() {
    EventFlag::deleteEventFlag(&mDvrMQEventFlag);
}

int Dvr::close() {
    Result r = mDvrSp->close();
    if (r == Result::SUCCESS) {
        EventFlag::deleteEventFlag(&mDvrMQEventFlag);
    }
    return (int)r;
}

sp<IDvr> Dvr::getIDvr() {
    return mDvrSp;
}
@@ -880,12 +893,28 @@ static int android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobjec
}

static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
    sp<Dvr> dvrSp = getDvr(env, dvr);
    sp<IDvr> iDvrSp = dvrSp->getIDvr();
    if (dvrSp == NULL) {
        ALOGD("Failed to configure dvr: dvr not found");
        return (int)Result::INVALID_STATE;
    }
    Result result = dvrSp->configure(getDvrSettings(env, settings));
    Result result = iDvrSp->configure(getDvrSettings(env, settings));
    MQDescriptorSync<uint8_t> dvrMQDesc;
    if (result == Result::SUCCESS) {
        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<DvrMQ>(dvrMQDesc, true);
            EventFlag::createEventFlag(
                    dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
        }
    }
    return (int)result;
}

@@ -943,6 +972,62 @@ static int android_media_tv_Tuner_close_lnb(JNIEnv*, jobject) {
    return 0;
}

static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
    sp<Dvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to set FD for dvr: dvr not found");
    }
    dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd);
    ALOGD("set fd = %d", dvrSp->mFd);
}

static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) {
    sp<Dvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to read dvr: dvr not found");
    }

    int available = dvrSp->mDvrMQ->availableToWrite();
    int write = std::min(size, available);

    DvrMQ::MemTransaction tx;
    int ret = 0;
    if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
        auto first = tx.getFirstRegion();
        auto data = first.getAddress();
        int length = first.getLength();
        int firstToWrite = std::min(length, write);
        ret = read(dvrSp->mFd, data, firstToWrite);
        if (ret < firstToWrite) {
            ALOGW("[DVR] file to MQ, first region: %d bytes to write, but %d bytes written",
                    firstToWrite, ret);
        } else if (firstToWrite < write) {
            ALOGD("[DVR] write second region: %d bytes written, %d 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: %d bytes need to be written, %d bytes written", write, ret);
        if (!dvrSp->mDvrMQ->commitWrite(ret)) {
            ALOGE("[DVR] Error: failed to commit write!");
        }

    } else {
        ALOGE("dvrMq.beginWrite failed");
    }
    return ret;
}

static int android_media_tv_Tuner_read_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 },
    { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -1010,6 +1095,10 @@ static const JNINativeMethod gDvrMethods[] = {
    { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
    { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
    { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
    { "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 },
};

static const JNINativeMethod gLnbMethods[] = {
+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <fmq/MessageQueue.h>
#include <fstream>
#include <string>
#include <unordered_map>
#include <utils/RefBase.h>

@@ -58,6 +60,7 @@ using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;

using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;

namespace android {

@@ -80,9 +83,15 @@ private:

struct Dvr : public RefBase {
    Dvr(sp<IDvr> sp, jweak obj);
    ~Dvr();
    int close();
    sp<IDvr> getIDvr();
    sp<IDvr> mDvrSp;
    jweak mDvrObj;
    std::unique_ptr<DvrMQ> mDvrMQ;
    EventFlag* mDvrMQEventFlag;
    std::string mFilePath;
    int mFd;
};

struct FilterCallback : public IFilterCallback {