Tuner JNI: time filter

Test: make; acloud create;
Change-Id: I6bd53f6831e021d14b8d5762850a083acdbcf26a
This commit is contained in:
shubang
2020-02-05 16:27:06 -08:00
parent 954aa0efea
commit f657da2d54
4 changed files with 207 additions and 17 deletions

View File

@@ -16,6 +16,7 @@
package android.media.tv.tuner;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.tv.tuner.V1_0.Constants;
@@ -142,5 +143,33 @@ public final class TunerUtils {
"Invalid filter types. Main type=" + mainType + ", subtype=" + subtype);
}
/**
* Gets an throwable instance for the corresponding result.
*/
@Nullable
public static void throwExceptionForResult(
@TunerConstants.Result int r, @Nullable String msg) {
if (msg == null) {
msg = "";
}
switch (r) {
case TunerConstants.RESULT_INVALID_ARGUMENT:
throw new IllegalArgumentException(msg);
case TunerConstants.RESULT_INVALID_STATE:
throw new IllegalStateException(msg);
case TunerConstants.RESULT_NOT_INITIALIZED:
throw new IllegalStateException("Invalid state: not initialized. " + msg);
case TunerConstants.RESULT_OUT_OF_MEMORY:
throw new OutOfMemoryError(msg);
case TunerConstants.RESULT_UNAVAILABLE:
throw new IllegalStateException("Invalid state: resource unavailable. " + msg);
case TunerConstants.RESULT_UNKNOWN_ERROR:
throw new RuntimeException("Unknown error" + msg);
default:
break;
}
throw new RuntimeException("Unexpected result " + r + ". " + msg);
}
private TunerUtils() {}
}

View File

@@ -17,7 +17,9 @@
package android.media.tv.tuner.filter;
import android.annotation.SystemApi;
import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerConstants.Result;
import android.media.tv.tuner.TunerUtils;
/**
* A timer filter is used to filter data based on timestamps.
@@ -51,6 +53,8 @@ public class TimeFilter implements AutoCloseable {
private native Long nativeGetSourceTime();
private native int nativeClose();
private long mNativeContext;
private boolean mEnable = false;
// Called by JNI code
@@ -139,6 +143,9 @@ public class TimeFilter implements AutoCloseable {
*/
@Override
public void close() {
nativeClose();
int res = nativeClose();
if (res != TunerConstants.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "Failed to close time filter.");
}
}
}

View File

@@ -117,10 +117,12 @@ using ::android::hardware::tv::tuner::V1_0::Result;
struct fields_t {
jfieldID tunerContext;
jfieldID filterContext;
jfieldID timeFilterContext;
jfieldID descramblerContext;
jfieldID dvrContext;
jmethodID frontendInitID;
jmethodID filterInitID;
jmethodID timeFilterInitID;
jmethodID dvrInitID;
jmethodID onFrontendEventID;
jmethodID onFilterStatusID;
@@ -236,6 +238,25 @@ sp<IFilter> Filter::getIFilter() {
return mFilterSp;
}
/////////////// TimeFilter ///////////////////////
TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
mTimeFilterObj = env->NewWeakGlobalRef(obj);
}
TimeFilter::~TimeFilter() {
ALOGD("~TimeFilter");
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mTimeFilterObj);
mTimeFilterObj = NULL;
}
sp<ITimeFilter> TimeFilter::getITimeFilter() {
return mTimeFilterSp;
}
/////////////// FrontendCallback ///////////////////////
FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
@@ -702,6 +723,36 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
return filterObj;
}
jobject JTuner::openTimeFilter() {
if (mDemux == NULL) {
if (!openDemux()) {
return NULL;
}
}
sp<ITimeFilter> iTimeFilterSp;
Result res;
mDemux->openTimeFilter(
[&](Result r, const sp<ITimeFilter>& filter) {
iTimeFilterSp = filter;
res = r;
});
if (res != Result::SUCCESS || iTimeFilterSp == NULL) {
return NULL;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject timeFilterObj =
env->NewObject(
env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
gFields.timeFilterInitID);
sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj);
timeFilterSp->incStrong(timeFilterObj);
env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get());
return timeFilterObj;
}
jobject JTuner::openDvr(DvrType type, int bufferSize) {
ALOGD("JTuner::openDvr");
if (mDemux == NULL) {
@@ -1281,6 +1332,10 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) {
gFields.onFilterStatusID =
env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter");
gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J");
gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V");
jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
gFields.descramblerInitID =
@@ -1376,18 +1431,35 @@ static jobject android_media_tv_Tuner_open_lnb_by_id(JNIEnv *env, jobject thiz,
static jobject android_media_tv_Tuner_open_filter(
JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
sp<JTuner> tuner = getTuner(env, thiz);
DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
DemuxFilterType filterType {
.mainType = static_cast<DemuxFilterMainType>(type),
.mainType = mainType,
};
// TODO: other sub types
filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
switch(mainType) {
case DemuxFilterMainType::TS:
filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
break;
case DemuxFilterMainType::MMTP:
filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
break;
case DemuxFilterMainType::IP:
filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
break;
case DemuxFilterMainType::TLV:
filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
break;
case DemuxFilterMainType::ALP:
filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
break;
}
return tuner->openFilter(filterType, bufferSize);
}
static jobject android_media_tv_Tuner_open_time_filter(JNIEnv, jobject) {
return NULL;
static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openTimeFilter();
}
static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) {
@@ -1848,26 +1920,98 @@ static int android_media_tv_Tuner_close_filter(JNIEnv*, jobject) {
return 0;
}
// TODO: implement TimeFilter functions
static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext);
}
static int android_media_tv_Tuner_time_filter_set_timestamp(
JNIEnv, jobject, jlong) {
return 0;
JNIEnv *env, jobject filter, jlong timestamp) {
sp<TimeFilter> filterSp = getTimeFilter(env, filter);
if (filterSp == NULL) {
ALOGD("Failed set timestamp: time filter not found");
return (int) Result::INVALID_STATE;
}
sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp));
return (int) r;
}
static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv, jobject) {
return 0;
static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
sp<TimeFilter> filterSp = getTimeFilter(env, filter);
if (filterSp == NULL) {
ALOGD("Failed clear timestamp: time filter not found");
return (int) Result::INVALID_STATE;
}
sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
Result r = iFilterSp->clearTimeStamp();
return (int) r;
}
static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv, jobject) {
return NULL;
static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
sp<TimeFilter> filterSp = getTimeFilter(env, filter);
if (filterSp == NULL) {
ALOGD("Failed get timestamp: time filter not found");
return NULL;
}
sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
Result res;
uint64_t timestamp;
iFilterSp->getTimeStamp(
[&](Result r, uint64_t t) {
res = r;
timestamp = t;
});
if (res != Result::SUCCESS) {
return NULL;
}
jclass longClazz = env->FindClass("java/lang/Long");
jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
return longObj;
}
static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv, jobject) {
return NULL;
static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
sp<TimeFilter> filterSp = getTimeFilter(env, filter);
if (filterSp == NULL) {
ALOGD("Failed get source time: time filter not found");
return NULL;
}
sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
Result res;
uint64_t timestamp;
iFilterSp->getSourceTime(
[&](Result r, uint64_t t) {
res = r;
timestamp = t;
});
if (res != Result::SUCCESS) {
return NULL;
}
jclass longClazz = env->FindClass("java/lang/Long");
jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
return longObj;
}
static int android_media_tv_Tuner_time_filter_close(JNIEnv, jobject) {
return 0;
static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
sp<TimeFilter> filterSp = getTimeFilter(env, filter);
if (filterSp == NULL) {
ALOGD("Failed close time filter: time filter not found");
return (int) Result::INVALID_STATE;
}
Result r = filterSp->getITimeFilter()->close();
if (r == Result::SUCCESS) {
filterSp->decStrong(filter);
env->SetLongField(filter, gFields.timeFilterContext, 0);
}
return (int) r;
}
static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {

View File

@@ -54,6 +54,7 @@ using ::android::hardware::tv::tuner::V1_0::IFrontend;
using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::ILnb;
using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::LnbEventType;
using ::android::hardware::tv::tuner::V1_0::LnbId;
@@ -128,6 +129,14 @@ struct Filter : public RefBase {
jweak mFilterObj;
};
struct TimeFilter : public RefBase {
TimeFilter(sp<ITimeFilter> sp, jweak obj);
~TimeFilter();
sp<ITimeFilter> getITimeFilter();
sp<ITimeFilter> mTimeFilterSp;
jweak mTimeFilterObj;
};
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
@@ -143,6 +152,7 @@ struct JTuner : public RefBase {
jobject getLnbIds();
jobject openLnbById(int id);
jobject openFilter(DemuxFilterType type, int bufferSize);
jobject openTimeFilter();
jobject openDescrambler();
jobject openDvr(DvrType type, int bufferSize);