diff options
| -rw-r--r-- | media/java/android/media/tv/tuner/Tuner.java | 78 | ||||
| -rw-r--r-- | media/jni/android_media_tv_Tuner.cpp | 49 | ||||
| -rw-r--r-- | media/jni/android_media_tv_Tuner.h | 18 |
3 files changed, 132 insertions, 13 deletions
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index d1c171a2d7df..4ed8f423d6c9 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -16,6 +16,11 @@ package android.media.tv.tuner; +import android.annotation.Nullable; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + import java.util.List; /** @@ -34,8 +39,9 @@ public final class Tuner implements AutoCloseable { nativeInit(); } - private FrontendCallback mFrontendCallback; private List<Integer> mFrontendIds; + private Frontend mFrontend; + private EventHandler mHandler; public Tuner() { nativeSetup(); @@ -80,11 +86,66 @@ public final class Tuner implements AutoCloseable { void onEvent(int frontendEventType); } - protected static class Frontend { - int mId; + @Nullable + private EventHandler createEventHandler() { + Looper looper; + if ((looper = Looper.myLooper()) != null) { + return new EventHandler(looper); + } else if ((looper = Looper.getMainLooper()) != null) { + return new EventHandler(looper); + } + return null; + } + + private class EventHandler extends Handler { + private EventHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ON_FRONTEND_EVENT: + if (mFrontend != null && mFrontend.mCallback != null) { + mFrontend.mCallback.onEvent(msg.arg1); + } + break; + default: + // fall through + } + } + } + + protected class Frontend { + private int mId; + private FrontendCallback mCallback; + private Frontend(int id) { mId = id; } + + public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) { + mCallback = callback; + + if (mCallback == null) { + return; + } + + if (handler == null) { + // use default looper if handler is null + if (mHandler == null) { + mHandler = createEventHandler(); + } + return; + } + + Looper looper = handler.getLooper(); + if (mHandler != null && mHandler.getLooper() == looper) { + // the same looper. reuse mHandler + return; + } + mHandler = new EventHandler(looper); + } } private List<Integer> getFrontendIds() { @@ -94,12 +155,19 @@ public final class Tuner implements AutoCloseable { private Frontend openFrontendById(int id) { if (mFrontendIds == null) { - getFrontendIds(); + mFrontendIds = getFrontendIds(); } if (!mFrontendIds.contains(id)) { return null; } - return nativeOpenFrontendById(id); + mFrontend = nativeOpenFrontendById(id); + return mFrontend; + } + + private void onFrontendEvent(int eventType) { + if (mHandler != null) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_FRONTEND_EVENT, eventType, 0)); + } } protected class Filter { diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 9e96b74dd471..f8150972a413 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -36,6 +36,7 @@ struct fields_t { jfieldID context; jmethodID frontendInitID; jmethodID filterInitID; + jmethodID onFrontendEventID; }; static fields_t gFields; @@ -52,7 +53,32 @@ Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus /*status*/) return Void(); } +/////////////// FrontendCallback /////////////////////// + +FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {} + +Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) { + ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType); + JNIEnv *env = AndroidRuntime::getJNIEnv(); + env->CallVoidMethod( + mObject, + gFields.onFrontendEventID, + (jint)frontendEventType); + return Void(); +} +Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) { + ALOGD("FrontendCallback::onDiseqcMessage"); + return Void(); +} + +Return<void> FrontendCallback::onScanMessage( + FrontendScanMessageType type, const FrontendScanMessage& /*message*/) { + ALOGD("FrontendCallback::onScanMessage, type=%d", type); + return Void(); +} + /////////////// Tuner /////////////////////// + sp<ITuner> JTuner::mTuner; JTuner::JTuner(JNIEnv *env, jobject thiz) @@ -89,11 +115,10 @@ sp<ITuner> JTuner::getTunerService() { jobject JTuner::getFrontendIds() { ALOGD("JTuner::getFrontendIds()"); - hidl_vec<FrontendId> feIds; mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) { - feIds = frontendIds; + mFeIds = frontendIds; }); - if (feIds.size() == 0) { + if (mFeIds.size() == 0) { ALOGW("Frontend isn't available"); return NULL; } @@ -106,21 +131,25 @@ jobject JTuner::getFrontendIds() { jclass integerClazz = env->FindClass("java/lang/Integer"); jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V"); - for (int i=0; i < feIds.size(); i++) { - jobject idObj = env->NewObject(integerClazz, intInit, feIds[i]); + for (int i=0; i < mFeIds.size(); i++) { + jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]); env->CallBooleanMethod(obj, arrayListAdd, idObj); } return obj; } jobject JTuner::openFrontendById(int id) { + sp<IFrontend> fe; mTuner->openFrontendById(id, [&](Result, const sp<IFrontend>& frontend) { - mFe = frontend; + fe = frontend; }); - if (mFe == nullptr) { + if (fe == nullptr) { ALOGE("Failed to open frontend"); return NULL; } + mFe = fe; + sp<FrontendCallback> feCb = new FrontendCallback(mObject, id); + fe->setCallback(feCb); jint jId = (jint) id; JNIEnv *env = AndroidRuntime::getJNIEnv(); @@ -128,6 +157,7 @@ jobject JTuner::openFrontendById(int id) { return env->NewObject( env->FindClass("android/media/tv/tuner/Tuner$Frontend"), gFields.frontendInitID, + mObject, (jint) jId); } @@ -210,8 +240,11 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) { gFields.context = env->GetFieldID(clazz, "mNativeContext", "J"); CHECK(gFields.context != NULL); + gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V"); + jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend"); - gFields.frontendInitID = env->GetMethodID(frontendClazz, "<init>", "(I)V"); + gFields.frontendInitID = + env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V"); jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter"); gFields.filterInitID = diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index b23b39492ac0..7a889c3534da 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -24,14 +24,19 @@ #include "jni.h" using ::android::hardware::Return; +using ::android::hardware::hidl_vec; 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::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::IFilter; using ::android::hardware::tv::tuner::V1_0::IFilterCallback; using ::android::hardware::tv::tuner::V1_0::IFrontend; +using ::android::hardware::tv::tuner::V1_0::IFrontendCallback; using ::android::hardware::tv::tuner::V1_0::ITuner; namespace android { @@ -41,6 +46,18 @@ struct FilterCallback : public IFilterCallback { virtual Return<void> onFilterStatus(const DemuxFilterStatus status); }; +struct FrontendCallback : public IFrontendCallback { + FrontendCallback(jweak tunerObj, FrontendId id); + + virtual Return<void> onEvent(FrontendEventType frontendEventType); + virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage); + virtual Return<void> onScanMessage( + FrontendScanMessageType type, const FrontendScanMessage& message); + + jweak mObject; + FrontendId mId; +}; + struct JTuner : public RefBase { JTuner(JNIEnv *env, jobject thiz); sp<ITuner> getTunerService(); @@ -55,6 +72,7 @@ private: jclass mClass; jweak mObject; static sp<ITuner> mTuner; + hidl_vec<FrontendId> mFeIds; sp<IFrontend> mFe; sp<IDemux> mDemux; int mDemuxId; |