Handle frontend callbacks
Test: make; acloud;
Change-Id: I0b238c01311a77eac161bae210f9459fef34a424
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index d1c171a..4ed8f42 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 @@
nativeInit();
}
- private FrontendCallback mFrontendCallback;
private List<Integer> mFrontendIds;
+ private Frontend mFrontend;
+ private EventHandler mHandler;
public Tuner() {
nativeSetup();
@@ -80,11 +86,66 @@
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 @@
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 9e96b74..f815097 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -36,6 +36,7 @@
jfieldID context;
jmethodID frontendInitID;
jmethodID filterInitID;
+ jmethodID onFrontendEventID;
};
static fields_t gFields;
@@ -52,7 +53,32 @@
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 @@
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 @@
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 @@
return env->NewObject(
env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
gFields.frontendInitID,
+ mObject,
(jint) jId);
}
@@ -210,8 +240,11 @@
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 b23b394..7a889c3 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 @@
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 @@
jclass mClass;
jweak mObject;
static sp<ITuner> mTuner;
+ hidl_vec<FrontendId> mFeIds;
sp<IFrontend> mFe;
sp<IDemux> mDemux;
int mDemuxId;