Merge "DVR API: class, methods, JNI"

This commit is contained in:
Shubang Lu
2019-11-14 21:00:55 +00:00
committed by Android (Google) Code Review
3 changed files with 196 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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();