Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c08a08e3 authored by Kensuke Miyagi's avatar Kensuke Miyagi
Browse files

Enable Frontend callback for sharee.

Bug: 209873032
Test: cts.TunerTest#testShareFrontendFromTuner

Change-Id: Iffd4cb5070e65fb298006d9813ce1a5b5c069a5b
parent a89a52d6
Loading
Loading
Loading
Loading
+45 −16
Original line number Diff line number Diff line
@@ -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,20 +546,22 @@ public class Tuner implements AutoCloseable {
        }
    }

    private void releaseAll() {
    private void releaseFrontend() {
        mFrontendLock.lock();
        try {
            if (mFrontendHandle != null) {
                synchronized (mIsSharedFrontend) {
                    if (!mIsSharedFrontend) {
                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");
                    }
                    mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
                }
                    mIsSharedFrontend = false;
                }
                FrameworkStatsLog
                        .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
@@ -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(() -> {
+97 −22
Original line number Diff line number Diff line
@@ -947,34 +947,72 @@ 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));
    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 {
        ALOGE("FrontendClientCallbackImpl::onEvent:"
            ALOGW("FrontendClientCallbackImpl::onEvent:"
                    "Frontend object has been freed. Ignoring callback.");
        }
    }
}

void FrontendClientCallbackImpl::onScanMessage(
        FrontendScanMessageType type, const FrontendScanMessage& message) {
    ALOGV("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
    jobject frontend(env->NewLocalRef(mObject));

    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:"
                "Frontend object has been freed. Ignoring callback.");
        return;
                    "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>()) {
@@ -1153,11 +1191,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 ///////////////////////
@@ -1176,6 +1217,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();
@@ -1188,6 +1233,7 @@ JTuner::~JTuner() {
    env->DeleteWeakGlobalRef(mObject);
    env->DeleteGlobalRef(mClass);
    mFeClient = nullptr;
    mFeClientCb = nullptr;
    mDemuxClient = nullptr;
    mClass = nullptr;
    mObject = nullptr;
@@ -1243,9 +1289,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"),
@@ -1265,6 +1310,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");
@@ -3184,6 +3241,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);
@@ -4346,6 +4417,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 },
+14 −2
Original line number Diff line number Diff line
@@ -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;