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

Commit 90413535 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enable Frontend callback for sharee."

parents 80a49a08 c08a08e3
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
@@ -951,34 +951,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>()) {
@@ -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 },
+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;