Merge "Enable Frontend callback for sharee."

This commit is contained in:
TreeHugger Robot
2021-12-13 17:59:55 +00:00
committed by Android (Google) Code Review
3 changed files with 156 additions and 40 deletions

View File

@@ -285,7 +285,7 @@ public class Tuner implements AutoCloseable {
@Nullable
private FrontendInfo mFrontendInfo;
private Integer mFrontendHandle;
private Boolean mIsSharedFrontend = false;
private Tuner mFeOwnerTuner = null;
private int mFrontendType = FrontendSettings.TYPE_UNDEFINED;
private int mUserId;
private Lnb mLnb;
@@ -442,11 +442,10 @@ public class Tuner implements AutoCloseable {
mFrontendLock.lock();
try {
mTunerResourceManager.shareFrontend(mClientId, tuner.mClientId);
synchronized (mIsSharedFrontend) {
mFrontendHandle = tuner.mFrontendHandle;
mFrontend = tuner.mFrontend;
mIsSharedFrontend = true;
}
mFeOwnerTuner = tuner;
mFeOwnerTuner.registerFrontendCallbackListener(this);
mFrontendHandle = mFeOwnerTuner.mFrontendHandle;
mFrontend = mFeOwnerTuner.mFrontend;
nativeShareFrontend(mFrontend.mId);
} finally {
releaseTRMSLock();
@@ -512,6 +511,27 @@ public class Tuner implements AutoCloseable {
private long mNativeContext; // used by native jMediaTuner
/**
* Registers a tuner as a listener for frontend callbacks.
*/
private void registerFrontendCallbackListener(Tuner tuner) {
nativeRegisterFeCbListener(tuner.getNativeContext());
}
/**
* Unregisters a tuner as a listener for frontend callbacks.
*/
private void unregisterFrontendCallbackListener(Tuner tuner) {
nativeUnregisterFeCbListener(tuner.getNativeContext());
}
/**
* Returns the pointer to the associated JTuner.
*/
long getNativeContext() {
return mNativeContext;
}
/**
* Releases the Tuner instance.
*/
@@ -526,19 +546,21 @@ public class Tuner implements AutoCloseable {
}
}
private void releaseAll() {
private void releaseFrontend() {
mFrontendLock.lock();
try {
if (mFrontendHandle != null) {
synchronized (mIsSharedFrontend) {
if (!mIsSharedFrontend) {
int res = nativeCloseFrontend(mFrontendHandle);
if (res != Tuner.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "failed to close frontend");
}
mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
if (mFeOwnerTuner != null) {
// unregister self from the Frontend callback
mFeOwnerTuner.unregisterFrontendCallbackListener(this);
mFeOwnerTuner = null;
} else {
// close resource as owner
int res = nativeCloseFrontend(mFrontendHandle);
if (res != Tuner.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "failed to close frontend");
}
mIsSharedFrontend = false;
mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
}
FrameworkStatsLog
.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
@@ -549,9 +571,14 @@ public class Tuner implements AutoCloseable {
} finally {
mFrontendLock.unlock();
}
}
private void releaseAll() {
releaseFrontend();
mLnbLock.lock();
try {
// mLnb will be non-null only for owner tuner
if (mLnb != null) {
mLnb.close();
}
@@ -641,6 +668,8 @@ public class Tuner implements AutoCloseable {
*/
private native Frontend nativeOpenFrontendByHandle(int handle);
private native int nativeShareFrontend(int id);
private native void nativeRegisterFeCbListener(long nativeContext);
private native void nativeUnregisterFeCbListener(long nativeContext);
@Result
private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune();
@@ -1276,7 +1305,7 @@ public class Tuner implements AutoCloseable {
}
private void onFrontendEvent(int eventType) {
Log.d(TAG, "Got event from tuning. Event type: " + eventType);
Log.d(TAG, "Got event from tuning. Event type: " + eventType + " for " + this);
synchronized (mOnTuneEventLock) {
if (mOnTuneEventExecutor != null && mOnTuneEventListener != null) {
mOnTuneEventExecutor.execute(() -> {

View File

@@ -951,20 +951,45 @@ FilterClientCallbackImpl::~FilterClientCallbackImpl() {
}
/////////////// FrontendClientCallbackImpl ///////////////////////
FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
FrontendClientCallbackImpl::FrontendClientCallbackImpl(JTuner* jtuner, jweak listener) {
ALOGV("FrontendClientCallbackImpl() with listener:%p", listener);
addCallbackListener(jtuner, listener);
}
void FrontendClientCallbackImpl::addCallbackListener(JTuner* jtuner, jweak listener) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jweak listenerRef = env->NewWeakGlobalRef(listener);
ALOGV("addCallbackListener() with listener:%p and ref:%p @%p", listener, listenerRef, this);
std::scoped_lock<std::mutex> lock(mMutex);
mListenersMap[jtuner] = listenerRef;
}
void FrontendClientCallbackImpl::removeCallbackListener(JTuner* listener) {
ALOGV("removeCallbackListener for listener:%p", listener);
JNIEnv *env = AndroidRuntime::getJNIEnv();
std::scoped_lock<std::mutex> lock(mMutex);
if (mListenersMap.find(listener) != mListenersMap.end() && mListenersMap[listener]) {
env->DeleteWeakGlobalRef(mListenersMap[listener]);
mListenersMap.erase(listener);
}
}
void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
ALOGV("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject frontend(env->NewLocalRef(mObject));
if (!env->IsSameObject(frontend, nullptr)) {
env->CallVoidMethod(
frontend,
gFields.onFrontendEventID,
(jint)frontendEventType);
} else {
ALOGE("FrontendClientCallbackImpl::onEvent:"
"Frontend object has been freed. Ignoring callback.");
std::scoped_lock<std::mutex> lock(mMutex);
for (const auto& mapEntry : mListenersMap) {
ALOGV("JTuner:%p, jweak:%p", mapEntry.first, mapEntry.second);
jobject frontend(env->NewLocalRef(mapEntry.second));
if (!env->IsSameObject(frontend, nullptr)) {
env->CallVoidMethod(
frontend,
gFields.onFrontendEventID,
(jint)frontendEventType);
} else {
ALOGW("FrontendClientCallbackImpl::onEvent:"
"Frontend object has been freed. Ignoring callback.");
}
}
}
@@ -973,12 +998,25 @@ void FrontendClientCallbackImpl::onScanMessage(
ALOGV("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
jobject frontend(env->NewLocalRef(mObject));
if (env->IsSameObject(frontend, nullptr)) {
ALOGE("FrontendClientCallbackImpl::onScanMessage:"
"Frontend object has been freed. Ignoring callback.");
return;
std::scoped_lock<std::mutex> lock(mMutex);
for (const auto& mapEntry : mListenersMap) {
jobject frontend(env->NewLocalRef(mapEntry.second));
if (env->IsSameObject(frontend, nullptr)) {
ALOGE("FrontendClientCallbackImpl::onScanMessage:"
"Tuner object has been freed. Ignoring callback.");
continue;
}
executeOnScanMessage(env, clazz, frontend, type, message);
}
}
void FrontendClientCallbackImpl::executeOnScanMessage(
JNIEnv *env, const jclass& clazz, const jobject& frontend,
FrontendScanMessageType type,
const FrontendScanMessage& message) {
ALOGV("FrontendClientCallbackImpl::executeOnScanMessage, type=%d", type);
switch(type) {
case FrontendScanMessageType::LOCKED: {
if (message.get<FrontendScanMessage::Tag::isLocked>()) {
@@ -1157,11 +1195,14 @@ void FrontendClientCallbackImpl::onScanMessage(
}
FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (mObject != nullptr) {
env->DeleteWeakGlobalRef(mObject);
mObject = nullptr;
JNIEnv *env = android::AndroidRuntime::getJNIEnv();
ALOGV("~FrontendClientCallbackImpl()");
std::scoped_lock<std::mutex> lock(mMutex);
for (const auto& mapEntry : mListenersMap) {
ALOGV("deleteRef :%p at @ %p", mapEntry.second, this);
env->DeleteWeakGlobalRef(mapEntry.second);
}
mListenersMap.clear();
}
/////////////// Tuner ///////////////////////
@@ -1180,6 +1221,10 @@ JTuner::JTuner(JNIEnv *env, jobject thiz) : mClass(nullptr) {
mSharedFeId = (int)Constant::INVALID_FRONTEND_ID;
}
jweak JTuner::getObject() {
return mObject;
}
JTuner::~JTuner() {
if (mFeClient != nullptr) {
mFeClient->close();
@@ -1192,6 +1237,7 @@ JTuner::~JTuner() {
env->DeleteWeakGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
mFeClient = nullptr;
mFeClientCb = nullptr;
mDemuxClient = nullptr;
mClass = nullptr;
mObject = nullptr;
@@ -1247,9 +1293,8 @@ jobject JTuner::openFrontendByHandle(int feHandle) {
return nullptr;
}
sp<FrontendClientCallbackImpl> feClientCb =
new FrontendClientCallbackImpl(env->NewWeakGlobalRef(mObject));
mFeClient->setCallback(feClientCb);
mFeClientCb = new FrontendClientCallbackImpl(this, mObject);
mFeClient->setCallback(mFeClientCb);
// TODO: add more fields to frontend
return env->NewObject(
env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
@@ -1269,6 +1314,18 @@ int JTuner::shareFrontend(int feId) {
return (int)Result::SUCCESS;
}
void JTuner::registerFeCbListener(JTuner* jtuner) {
if (mFeClientCb != nullptr && jtuner != nullptr) {
mFeClientCb->addCallbackListener(jtuner, jtuner->getObject());
}
}
void JTuner::unregisterFeCbListener(JTuner* jtuner) {
if (mFeClientCb != nullptr && jtuner != nullptr) {
mFeClientCb->removeCallbackListener(jtuner);
}
}
jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
@@ -3188,6 +3245,20 @@ static int android_media_tv_Tuner_share_frontend(
return tuner->shareFrontend(id);
}
static void android_media_tv_Tuner_register_fe_cb_listener(
JNIEnv *env, jobject thiz, jlong shareeJTuner) {
sp<JTuner> tuner = getTuner(env, thiz);
JTuner *jtuner = (JTuner *)shareeJTuner;
tuner->registerFeCbListener(jtuner);
}
static void android_media_tv_Tuner_unregister_fe_cb_listener(
JNIEnv *env, jobject thiz, jlong shareeJTuner) {
sp<JTuner> tuner = getTuner(env, thiz);
JTuner *jtuner = (JTuner *)shareeJTuner;
tuner->unregisterFeCbListener(jtuner);
}
static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
sp<JTuner> tuner = getTuner(env, thiz);
FrontendSettings setting = getFrontendSettings(env, type, settings);
@@ -4361,6 +4432,10 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_open_frontend_by_handle },
{ "nativeShareFrontend", "(I)I",
(void *)android_media_tv_Tuner_share_frontend },
{ "nativeRegisterFeCbListener", "(J)V",
(void*)android_media_tv_Tuner_register_fe_cb_listener },
{ "nativeUnregisterFeCbListener", "(J)V",
(void*)android_media_tv_Tuner_unregister_fe_cb_listener },
{ "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },

View File

@@ -149,14 +149,21 @@ private:
void getRestartEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
};
struct JTuner;
struct FrontendClientCallbackImpl : public FrontendClientCallback {
FrontendClientCallbackImpl(jweak tunerObj);
FrontendClientCallbackImpl(JTuner*, jweak);
~FrontendClientCallbackImpl();
virtual void onEvent(FrontendEventType frontendEventType);
virtual void onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
jweak mObject;
void executeOnScanMessage(JNIEnv *env, const jclass& clazz, const jobject& frontend,
FrontendScanMessageType type,
const FrontendScanMessage& message);
void addCallbackListener(JTuner*, jweak obj);
void removeCallbackListener(JTuner* jtuner);
std::unordered_map<JTuner*, jweak> mListenersMap;
std::mutex mMutex;
};
struct JTuner : public RefBase {
@@ -171,6 +178,8 @@ struct JTuner : public RefBase {
jobject getFrontendIds();
jobject openFrontendByHandle(int feHandle);
int shareFrontend(int feId);
void registerFeCbListener(JTuner* jtuner);
void unregisterFeCbListener(JTuner* jtuner);
jint closeFrontendById(int id);
jobject getFrontendInfo(int id);
int tune(const FrontendSettings& settings);
@@ -192,6 +201,8 @@ struct JTuner : public RefBase {
jint closeFrontend();
jint closeDemux();
jweak getObject();
protected:
virtual ~JTuner();
@@ -200,6 +211,7 @@ private:
jweak mObject;
static sp<TunerClient> mTunerClient;
sp<FrontendClient> mFeClient;
sp<FrontendClientCallbackImpl> mFeClientCb;
int mFeId;
int mSharedFeId;
sp<LnbClient> mLnbClient;