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

Commit 74faf2a5 authored by Ray Chin's avatar Ray Chin
Browse files

Fix FilterClientCallbackImpl crash caused by race condition

Bug: 315422402
Test: Run on reference design device Ohm.
Change-Id: I79062b338049b36189223814fdf30e90b34e85ab
parent 311d8371
Loading
Loading
Loading
Loading
+42 −22
Original line number Diff line number Diff line
@@ -693,6 +693,8 @@ void FilterClientCallbackImpl::getMediaEvent(const jobjectArray& arr, const int
                                           mpuSequenceNumber, isPesPrivateData, sc,
                                           audioDescriptor.get(), presentationsJObj.get()));

    // Protect mFilterClient from being set to null.
    android::Mutex::Autolock autoLock(mLock);
    uint64_t avSharedMemSize = mFilterClient->getAvSharedHandleInfo().size;
    if (mediaEvent.avMemory.fds.size() > 0 || mediaEvent.avDataId != 0 ||
        (dataLength > 0 && (dataLength + offset) < avSharedMemSize)) {
@@ -939,38 +941,52 @@ void FilterClientCallbackImpl::onFilterEvent(const vector<DemuxFilterEvent> &eve
            }
        }
    }
    ScopedLocalRef filter(env, env->NewLocalRef(mFilterObj));
    if (!env->IsSameObject(filter.get(), nullptr)) {

    ScopedLocalRef<jobject> filter(env);
    {
        android::Mutex::Autolock autoLock(mLock);
        if (env->IsSameObject(mFilterObj, nullptr)) {
            ALOGE("FilterClientCallbackImpl::onFilterEvent:"
                  "Filter object has been freed. Ignoring callback.");
            return;
        } else {
            filter.reset(env->NewLocalRef(mFilterObj));
        }
    }

    jmethodID methodID = gFields.onFilterEventID;
    if (mSharedFilter) {
        methodID = gFields.onSharedFilterEventID;
    }
    env->CallVoidMethod(filter.get(), methodID, array.get());
    } else {
        ALOGE("FilterClientCallbackImpl::onFilterEvent:"
              "Filter object has been freed. Ignoring callback.");
    }
}

void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
    ALOGV("FilterClientCallbackImpl::onFilterStatus");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    ScopedLocalRef filter(env, env->NewLocalRef(mFilterObj));
    if (!env->IsSameObject(filter.get(), nullptr)) {
    ScopedLocalRef<jobject> filter(env);
    {
        android::Mutex::Autolock autoLock(mLock);
        if (env->IsSameObject(filter.get(), nullptr)) {
            ALOGE("FilterClientCallbackImpl::onFilterStatus:"
                  "Filter object has been freed. Ignoring callback.");
            return;
        } else {
            filter.reset(env->NewLocalRef(mFilterObj));
        }
    }

    jmethodID methodID = gFields.onFilterStatusID;
    if (mSharedFilter) {
        methodID = gFields.onSharedFilterStatusID;
    }
    env->CallVoidMethod(filter.get(), methodID, (jint)static_cast<uint8_t>(status));
    } else {
        ALOGE("FilterClientCallbackImpl::onFilterStatus:"
              "Filter object has been freed. Ignoring callback.");
    }
}

void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
    ALOGV("FilterClientCallbackImpl::setFilter");
    // Java Object
    android::Mutex::Autolock autoLock(mLock);
    mFilterObj = filterObj;
    mFilterClient = filterClient;
    mSharedFilter = false;
@@ -979,6 +995,7 @@ void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filte
void FilterClientCallbackImpl::setSharedFilter(jweak filterObj, sp<FilterClient> filterClient) {
    ALOGV("FilterClientCallbackImpl::setFilter");
    // Java Object
    android::Mutex::Autolock autoLock(mLock);
    mFilterObj = filterObj;
    mFilterClient = filterClient;
    mSharedFilter = true;
@@ -1047,11 +1064,14 @@ FilterClientCallbackImpl::FilterClientCallbackImpl() {

FilterClientCallbackImpl::~FilterClientCallbackImpl() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    {
        android::Mutex::Autolock autoLock(mLock);
        if (mFilterObj != nullptr) {
            env->DeleteWeakGlobalRef(mFilterObj);
            mFilterObj = nullptr;
        }
        mFilterClient = nullptr;
    }
    env->DeleteGlobalRef(mEventClass);
    env->DeleteGlobalRef(mSectionEventClass);
    env->DeleteGlobalRef(mMediaEventClass);
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ struct FilterClientCallbackImpl : public FilterClientCallback {
private:
    jweak mFilterObj;
    sp<FilterClient> mFilterClient;
    android::Mutex mLock;
    jclass mEventClass;
    jclass mSectionEventClass;
    jclass mMediaEventClass;