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

Commit 03079387 authored by Amy Zhang's avatar Amy Zhang
Browse files

Check if the weak reference of java object is alive before using it

This CL get the global strong reference from the weak reference before
calling methods on a weak java object reference in Tuner JNI.

The method call would use the strong ref instead of the weak ref after
making sure it's non-null because weak ref is not garanteed non-null
even after the null check

see https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#weak_global_references
for more details

Test: atest android.media.tv.tuner.cts
Bug: 176190716
Change-Id: I81215c18cda413c5ddee0e46480ce3783dfe4be9
parent 7658b9e2
Loading
Loading
Loading
Loading
+128 −49
Original line number Original line Diff line number Diff line
@@ -217,23 +217,36 @@ namespace android {
void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
    ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
    ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject lnb(env->NewLocalRef(mLnbObj));
    if (!env->IsSameObject(lnb, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mLnbObj,
                lnb,
                gFields.onLnbEventID,
                gFields.onLnbEventID,
                (jint)lnbEventType);
                (jint)lnbEventType);
    } else {
        ALOGE("LnbClientCallbackImpl::onEvent:"
                "Lnb object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mLnbObj);
    }
}
}


void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
    ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
    ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject lnb(env->NewLocalRef(mLnbObj));
    if (!env->IsSameObject(lnb, nullptr)) {
        jbyteArray array = env->NewByteArray(diseqcMessage.size());
        jbyteArray array = env->NewByteArray(diseqcMessage.size());
        env->SetByteArrayRegion(
        env->SetByteArrayRegion(
                array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
                array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));

        env->CallVoidMethod(
        env->CallVoidMethod(
            mLnbObj,
                lnb,
                gFields.onLnbDiseqcMessageID,
                gFields.onLnbDiseqcMessageID,
                array);
                array);
    } else {
        ALOGE("LnbClientCallbackImpl::onDiseqcMessage:"
                "Lnb object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mLnbObj);
    }
}
}


void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
@@ -254,19 +267,33 @@ LnbClientCallbackImpl::~LnbClientCallbackImpl() {
void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
    ALOGD("DvrClientCallbackImpl::onRecordStatus");
    ALOGD("DvrClientCallbackImpl::onRecordStatus");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject dvr(env->NewLocalRef(mDvrObj));
    if (!env->IsSameObject(dvr, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mDvrObj,
                dvr,
                gFields.onDvrRecordStatusID,
                gFields.onDvrRecordStatusID,
                (jint) status);
                (jint) status);
    } else {
        ALOGE("DvrClientCallbackImpl::onRecordStatus:"
                "Dvr object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mDvrObj);
    }
}
}


void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
    ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
    ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject dvr(env->NewLocalRef(mDvrObj));
    if (!env->IsSameObject(dvr, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mDvrObj,
                dvr,
                gFields.onDvrPlaybackStatusID,
                gFields.onDvrPlaybackStatusID,
                (jint) status);
                (jint) status);
    } else {
        ALOGE("DvrClientCallbackImpl::onPlaybackStatus:"
                "Dvr object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mDvrObj);
    }
}
}


void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
@@ -810,10 +837,17 @@ void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterE
            }
            }
        }
        }
    }
    }
    jobject filter(env->NewLocalRef(mFilterObj));
    if (!env->IsSameObject(filter, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mFilterObj,
                filter,
                gFields.onFilterEventID,
                gFields.onFilterEventID,
                array);
                array);
    } else {
        ALOGE("FilterClientCallbackImpl::onFilterEvent_1_1:"
                "Filter object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mFilterObj);
    }
}
}


void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
@@ -828,10 +862,17 @@ void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent
void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
    ALOGD("FilterClientCallbackImpl::onFilterStatus");
    ALOGD("FilterClientCallbackImpl::onFilterStatus");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject filter(env->NewLocalRef(mFilterObj));
    if (!env->IsSameObject(filter, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mFilterObj,
                filter,
                gFields.onFilterStatusID,
                gFields.onFilterStatusID,
                (jint)status);
                (jint)status);
    } else {
        ALOGE("FilterClientCallbackImpl::onFilterStatus:"
                "Filter object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mFilterObj);
    }
}
}


void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
@@ -841,6 +882,15 @@ void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filte
    mFilterClient = filterClient;
    mFilterClient = filterClient;
}
}


FilterClientCallbackImpl::~FilterClientCallbackImpl() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    if (mFilterObj != NULL) {
        env->DeleteWeakGlobalRef(mFilterObj);
        mFilterObj = NULL;
    }
    mFilterClient = NULL;
}

/////////////// FrontendClientCallbackImpl ///////////////////////
/////////////// FrontendClientCallbackImpl ///////////////////////


FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
@@ -848,10 +898,17 @@ FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject
void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
    ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
    ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jobject frontend(env->NewLocalRef(mObject));
    if (!env->IsSameObject(frontend, nullptr)) {
        env->CallVoidMethod(
        env->CallVoidMethod(
            mObject,
                frontend,
                gFields.onFrontendEventID,
                gFields.onFrontendEventID,
                (jint)frontendEventType);
                (jint)frontendEventType);
    } else {
        ALOGE("FrontendClientCallbackImpl::onEvent:"
                "Frontend object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mObject);
    }
}
}


void FrontendClientCallbackImpl::onScanMessage(
void FrontendClientCallbackImpl::onScanMessage(
@@ -859,11 +916,18 @@ void FrontendClientCallbackImpl::onScanMessage(
    ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
    ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
    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.");
        env->DeleteWeakGlobalRef(mObject);
        return;
    }
    switch(type) {
    switch(type) {
        case FrontendScanMessageType::LOCKED: {
        case FrontendScanMessageType::LOCKED: {
            if (message.isLocked()) {
            if (message.isLocked()) {
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onLocked", "()V"));
                        env->GetMethodID(clazz, "onLocked", "()V"));
            }
            }
            break;
            break;
@@ -871,14 +935,14 @@ void FrontendClientCallbackImpl::onScanMessage(
        case FrontendScanMessageType::END: {
        case FrontendScanMessageType::END: {
            if (message.isEnd()) {
            if (message.isEnd()) {
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onScanStopped", "()V"));
                        env->GetMethodID(clazz, "onScanStopped", "()V"));
            }
            }
            break;
            break;
        }
        }
        case FrontendScanMessageType::PROGRESS_PERCENT: {
        case FrontendScanMessageType::PROGRESS_PERCENT: {
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onProgress", "(I)V"),
                    env->GetMethodID(clazz, "onProgress", "(I)V"),
                    (jint) message.progressPercent());
                    (jint) message.progressPercent());
            break;
            break;
@@ -889,7 +953,7 @@ void FrontendClientCallbackImpl::onScanMessage(
            env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
            env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));


            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
                    env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
                    freqs);
                    freqs);
            break;
            break;
@@ -900,21 +964,21 @@ void FrontendClientCallbackImpl::onScanMessage(
            env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
            env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));


            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
                    env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
                    symbolRates);
                    symbolRates);
            break;
            break;
        }
        }
        case FrontendScanMessageType::HIERARCHY: {
        case FrontendScanMessageType::HIERARCHY: {
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onHierarchy", "(I)V"),
                    env->GetMethodID(clazz, "onHierarchy", "(I)V"),
                    (jint) message.hierarchy());
                    (jint) message.hierarchy());
            break;
            break;
        }
        }
        case FrontendScanMessageType::ANALOG_TYPE: {
        case FrontendScanMessageType::ANALOG_TYPE: {
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onSignalType", "(I)V"),
                    env->GetMethodID(clazz, "onSignalType", "(I)V"),
                    (jint) message.analogType());
                    (jint) message.analogType());
            break;
            break;
@@ -926,7 +990,7 @@ void FrontendClientCallbackImpl::onScanMessage(
            env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
            env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);


            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onPlpIds", "([I)V"),
                    env->GetMethodID(clazz, "onPlpIds", "([I)V"),
                    plpIds);
                    plpIds);
            break;
            break;
@@ -938,7 +1002,7 @@ void FrontendClientCallbackImpl::onScanMessage(
            env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
            env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);


            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onGroupIds", "([I)V"),
                    env->GetMethodID(clazz, "onGroupIds", "([I)V"),
                    groupIds);
                    groupIds);
            break;
            break;
@@ -950,7 +1014,7 @@ void FrontendClientCallbackImpl::onScanMessage(
            env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
            env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);


            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
                    env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
                    streamIds);
                    streamIds);
            break;
            break;
@@ -961,21 +1025,21 @@ void FrontendClientCallbackImpl::onScanMessage(
            if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
            if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
                standard = (jint) std.sStd();
                standard = (jint) std.sStd();
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
                        env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
                        standard);
                        standard);
            } else if (std.getDiscriminator() ==
            } else if (std.getDiscriminator() ==
                    FrontendScanMessage::Standard::hidl_discriminator::tStd) {
                    FrontendScanMessage::Standard::hidl_discriminator::tStd) {
                standard = (jint) std.tStd();
                standard = (jint) std.tStd();
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
                        env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
                        standard);
                        standard);
            } else if (std.getDiscriminator() ==
            } else if (std.getDiscriminator() ==
                    FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
                    FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
                standard = (jint) std.sifStd();
                standard = (jint) std.sifStd();
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
                        env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
                        standard);
                        standard);
            }
            }
@@ -996,7 +1060,7 @@ void FrontendClientCallbackImpl::onScanMessage(
                env->SetObjectArrayElement(array, i, obj);
                env->SetObjectArrayElement(array, i, obj);
            }
            }
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onAtsc3PlpInfos",
                    env->GetMethodID(clazz, "onAtsc3PlpInfos",
                            "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
                            "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
                    array);
                    array);
@@ -1010,6 +1074,13 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
    ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
    ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
    jobject frontend(env->NewLocalRef(mObject));
    if (env->IsSameObject(frontend, nullptr)) {
        ALOGE("FrontendClientCallbackImpl::onScanMessageExt1_1:"
                "Frontend object has been freed. Ignoring callback.");
        env->DeleteWeakGlobalRef(mObject);
        return;
    }
    switch(type) {
    switch(type) {
        case FrontendScanMessageTypeExt1_1::MODULATION: {
        case FrontendScanMessageTypeExt1_1::MODULATION: {
            jint modulation = -1;
            jint modulation = -1;
@@ -1056,7 +1127,7 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
            }
            }
            if (modulation > 0) {
            if (modulation > 0) {
                env->CallVoidMethod(
                env->CallVoidMethod(
                        mObject,
                        frontend,
                        env->GetMethodID(clazz, "onModulationReported", "(I)V"),
                        env->GetMethodID(clazz, "onModulationReported", "(I)V"),
                        modulation);
                        modulation);
            }
            }
@@ -1065,7 +1136,7 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
        case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
        case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
            bool isHighPriority = message.isHighPriority();
            bool isHighPriority = message.isHighPriority();
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onPriorityReported", "(B)V"),
                    env->GetMethodID(clazz, "onPriorityReported", "(B)V"),
                    isHighPriority);
                    isHighPriority);
            break;
            break;
@@ -1073,7 +1144,7 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
        case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
        case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
            jint dvbcAnnex = (jint) message.annex();
            jint dvbcAnnex = (jint) message.annex();
            env->CallVoidMethod(
            env->CallVoidMethod(
                    mObject,
                    frontend,
                    env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"),
                    env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"),
                    dvbcAnnex);
                    dvbcAnnex);
            break;
            break;
@@ -1083,6 +1154,14 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
    }
    }
}
}


FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    if (mObject != NULL) {
        env->DeleteWeakGlobalRef(mObject);
        mObject = NULL;
    }
}

/////////////// Tuner ///////////////////////
/////////////// Tuner ///////////////////////


sp<TunerClient> JTuner::mTunerClient;
sp<TunerClient> JTuner::mTunerClient;
+2 −1
Original line number Original line Diff line number Diff line
@@ -118,6 +118,7 @@ struct MediaEvent : public RefBase {
};
};


struct FilterClientCallbackImpl : public FilterClientCallback {
struct FilterClientCallbackImpl : public FilterClientCallback {
    ~FilterClientCallbackImpl();
    virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
    virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
            const DemuxFilterEventExt& filterEventExt);
            const DemuxFilterEventExt& filterEventExt);
    virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
    virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
@@ -155,7 +156,7 @@ private:


struct FrontendClientCallbackImpl : public FrontendClientCallback {
struct FrontendClientCallbackImpl : public FrontendClientCallback {
    FrontendClientCallbackImpl(jweak tunerObj);
    FrontendClientCallbackImpl(jweak tunerObj);

    ~FrontendClientCallbackImpl();
    virtual void onEvent(FrontendEventType frontendEventType);
    virtual void onEvent(FrontendEventType frontendEventType);
    virtual void onScanMessage(
    virtual void onScanMessage(
            FrontendScanMessageType type, const FrontendScanMessage& message);
            FrontendScanMessageType type, const FrontendScanMessage& message);