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

Commit 4a0eddf4 authored by shubang's avatar shubang
Browse files

DVR API: class, methods, JNI

Test: make; alcoud;
Change-Id: Iddcffef436dc520c969a3dc4f854e3d4c902c2b8
parent 4056b743
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ public final class Tuner implements AutoCloseable {

    private native Descrambler nativeOpenDescrambler();

    private native Dvr nativeOpenDvr(int type, int bufferSize);

    /**
     * Frontend Callback.
@@ -118,6 +119,20 @@ public final class Tuner implements AutoCloseable {
        void onFilterStatus(int status);
    }

    /**
     * DVR Callback.
     */
    public interface DvrCallback {
        /**
         * Invoked when record status changed.
         */
        void onRecordStatus(int status);
        /**
         * Invoked when playback status changed.
         */
        void onPlaybackStatus(int status);
    }

    @Nullable
    private EventHandler createEventHandler() {
        Looper looper;
@@ -321,4 +336,39 @@ public final class Tuner implements AutoCloseable {
        Descrambler descrambler = nativeOpenDescrambler();
        return descrambler;
    }

    // TODO: consider splitting Dvr to Playback and Recording
    protected class Dvr {
        private long mNativeContext;
        private DvrCallback mCallback;

        private native boolean nativeAttachFilter(Filter filter);
        private native boolean nativeDetachFilter(Filter filter);
        private native boolean nativeStartDvr();
        private native boolean nativeStopDvr();
        private native boolean nativeFlushDvr();

        private Dvr() {}

        public boolean attachFilter(Filter filter) {
            return nativeAttachFilter(filter);
        }
        public boolean detachFilter(Filter filter) {
            return nativeDetachFilter(filter);
        }
        public boolean start() {
            return nativeStartDvr();
        }
        public boolean stop() {
            return nativeStopDvr();
        }
        public boolean flush() {
            return nativeFlushDvr();
        }
    }

    private Dvr openDvr(int type, int bufferSize) {
        Dvr dvr = nativeOpenDvr(type, bufferSize);
        return dvr;
    }
}
+131 −0
Original line number Diff line number Diff line
@@ -38,8 +38,10 @@ struct fields_t {
    jfieldID tunerContext;
    jfieldID filterContext;
    jfieldID descramblerContext;
    jfieldID dvrContext;
    jmethodID frontendInitID;
    jmethodID filterInitID;
    jmethodID dvrInitID;
    jmethodID onFrontendEventID;
    jmethodID onFilterStatusID;
    jmethodID lnbInitID;
@@ -67,6 +69,23 @@ Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessa
    return Void();
}

/////////////// DvrCallback ///////////////////////
Return<void> DvrCallback::onRecordStatus(RecordStatus /*status*/) {
    ALOGD("DvrCallback::onRecordStatus");
    return Void();
}

Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus /*status*/) {
    ALOGD("DvrCallback::onPlaybackStatus");
    return Void();
}

void DvrCallback::setDvr(const jobject dvr) {
    ALOGD("FilterCallback::setDvr");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    mDvr = env->NewWeakGlobalRef(dvr);
}

/////////////// FilterCallback ///////////////////////
//TODO: implement filter callback
Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /*filterEvent*/) {
@@ -327,6 +346,39 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
    return filterObj;
}

jobject JTuner::openDvr(DvrType type, int bufferSize) {
    ALOGD("JTuner::openDvr");
    if (mDemux == NULL) {
        if (!openDemux()) {
            return NULL;
        }
    }
    sp<IDvr> dvrSp;
    sp<DvrCallback> callback = new DvrCallback();
    mDemux->openDvr(type, bufferSize, callback,
            [&](Result, const sp<IDvr>& dvr) {
                dvrSp = dvr;
            });

    if (dvrSp == NULL) {
        return NULL;
    }

    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject dvrObj =
            env->NewObject(
                    env->FindClass("android/media/tv/tuner/Tuner$Dvr"),
                    gFields.dvrInitID,
                    mObject);

    dvrSp->incStrong(dvrObj);
    env->SetLongField(dvrObj, gFields.dvrContext, (jlong)dvrSp.get());

    callback->setDvr(dvrObj);

    return dvrObj;
}

}  // namespace android

////////////////////////////////////////////////////////////////////////////////
@@ -369,6 +421,10 @@ static sp<IFilter> getFilter(JNIEnv *env, jobject filter) {
    return (IFilter *)env->GetLongField(filter, gFields.filterContext);
}

static sp<IDvr> getDvr(JNIEnv *env, jobject dvr) {
    return (IDvr *)env->GetLongField(dvr, gFields.dvrContext);
}

static void android_media_tv_Tuner_native_init(JNIEnv *env) {
    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
    CHECK(clazz != NULL);
@@ -399,6 +455,10 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) {
    gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
    gFields.descramblerInitID =
            env->GetMethodID(descramblerClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");

    jclass dvrClazz = env->FindClass("android/media/tv/tuner/Tuner$Dvr");
    gFields.dvrContext = env->GetFieldID(dvrClazz, "mNativeContext", "J");
    gFields.dvrInitID = env->GetMethodID(dvrClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
}

static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
@@ -493,6 +553,58 @@ static bool android_media_tv_Tuner_remove_pid(
    return result == Result::SUCCESS;
}

static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint type, jint bufferSize) {
    sp<JTuner> tuner = getTuner(env, thiz);
    return tuner->openDvr(static_cast<DvrType>(type), bufferSize);
}

static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
    sp<IDvr> dvrSp = getDvr(env, dvr);
    sp<IFilter> filterSp = getFilter(env, filter);
    if (dvrSp == NULL || filterSp == NULL) {
        return false;
    }
    Result result = dvrSp->attachFilter(filterSp);
    return result == Result::SUCCESS;
}

static bool android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
    sp<IDvr> dvrSp = getDvr(env, dvr);
    sp<IFilter> filterSp = getFilter(env, filter);
    if (dvrSp == NULL || filterSp == NULL) {
        return false;
    }
    Result result = dvrSp->detachFilter(filterSp);
    return result == Result::SUCCESS;
}

static bool android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
    sp<IDvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to start dvr: dvr not found");
        return false;
    }
    return dvrSp->start() == Result::SUCCESS;
}

static bool android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
    sp<IDvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to stop dvr: dvr not found");
        return false;
    }
    return dvrSp->stop() == Result::SUCCESS;
}

static bool android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
    sp<IDvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to flush dvr: dvr not found");
        return false;
    }
    return dvrSp->flush() == Result::SUCCESS;
}

static const JNINativeMethod gTunerMethods[] = {
    { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
    { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -508,6 +620,8 @@ static const JNINativeMethod gTunerMethods[] = {
            (void *)android_media_tv_Tuner_open_lnb_by_id },
    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Tuner$Descrambler;",
            (void *)android_media_tv_Tuner_open_descrambler },
    { "nativeOpenDvr", "(II)Landroid/media/tv/tuner/Tuner$Dvr;",
            (void *)android_media_tv_Tuner_open_dvr },
};

static const JNINativeMethod gFilterMethods[] = {
@@ -523,6 +637,16 @@ static const JNINativeMethod gDescramblerMethods[] = {
            (void *)android_media_tv_Tuner_remove_pid },
};

static const JNINativeMethod gDvrMethods[] = {
    { "nativeAttachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)Z",
            (void *)android_media_tv_Tuner_attach_filter },
    { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)Z",
            (void *)android_media_tv_Tuner_detach_filter },
    { "nativeStartDvr", "()Z", (void *)android_media_tv_Tuner_start_dvr },
    { "nativeStopDvr", "()Z", (void *)android_media_tv_Tuner_stop_dvr },
    { "nativeFlushDvr", "()Z", (void *)android_media_tv_Tuner_flush_dvr },
};

static bool register_android_media_tv_Tuner(JNIEnv *env) {
    if (AndroidRuntime::registerNativeMethods(
            env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) {
@@ -543,6 +667,13 @@ static bool register_android_media_tv_Tuner(JNIEnv *env) {
        ALOGE("Failed to register descrambler native methods");
        return false;
    }
    if (AndroidRuntime::registerNativeMethods(
            env, "android/media/tv/tuner/Tuner$Dvr",
            gDvrMethods,
            NELEM(gDvrMethods)) != JNI_OK) {
        ALOGE("Failed to register dvr native methods");
        return false;
    }
    return true;
}

+15 −0
Original line number Diff line number Diff line
@@ -29,12 +29,15 @@ using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxPid;
using ::android::hardware::tv::tuner::V1_0::DvrType;
using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
using ::android::hardware::tv::tuner::V1_0::IDemux;
using ::android::hardware::tv::tuner::V1_0::IDescrambler;
using ::android::hardware::tv::tuner::V1_0::IDvr;
using ::android::hardware::tv::tuner::V1_0::IDvrCallback;
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::IFrontend;
@@ -44,6 +47,8 @@ using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::LnbEventType;
using ::android::hardware::tv::tuner::V1_0::LnbId;
using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;

namespace android {

@@ -55,6 +60,15 @@ struct LnbCallback : public ILnbCallback {
    LnbId mId;
};

struct DvrCallback : public IDvrCallback {
    virtual Return<void> onRecordStatus(RecordStatus status);
    virtual Return<void> onPlaybackStatus(PlaybackStatus status);

    void setDvr(const jobject dvr);
private:
    jweak mDvr;
};

struct FilterCallback : public IFilterCallback {
    virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
    virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
@@ -85,6 +99,7 @@ struct JTuner : public RefBase {
    jobject openLnbById(int id);
    jobject openFilter(DemuxFilterType type, int bufferSize);
    jobject openDescrambler();
    jobject openDvr(DvrType type, int bufferSize);

protected:
    bool openDemux();