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

Commit a076a721 authored by Ray Essick's avatar Ray Essick Committed by Automerger Merge Worker
Browse files

Merge "Break cyclic binder dependency" am: 3d87c778

parents 14caedbe 3d87c778
Loading
Loading
Loading
Loading
+64 −2
Original line number Diff line number Diff line
@@ -16,9 +16,16 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "RemoteMediaExtractor"

#include <list>
#include <pthread.h>
#include <condition_variable>
#include <mutex>

#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <cutils/properties.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/MediaMetricsItem.h>
#include <media/stagefright/MediaSource.h>
@@ -90,10 +97,65 @@ RemoteMediaExtractor::RemoteMediaExtractor(
    }
}

static pthread_t myThread;
static std::list<sp<DataSource>> pending;
static std::mutex pending_mutex;
static std::condition_variable pending_added;

static void* closing_thread_func(void *arg) {
    while (true) {
        sp<DataSource> ds = nullptr;
        std::unique_lock _lk(pending_mutex);
        pending_added.wait(_lk, []{return !pending.empty();});
        ALOGV("worker thread wake up with %zu entries", pending.size());
        if (!pending.empty()) {
            ds = pending.front();
            (void) pending.pop_front();
        }
        _lk.unlock();       // unique_lock is not scoped
        if (ds != nullptr) {
            ds->close();
        }
    }

    ALOGE("[unexpected] worker thread quit");
    return arg;
}

// this can be '&ds' as long as the pending.push_back() bumps the
// reference counts to ensure the object lives long enough
static void start_close_thread(sp<DataSource> &ds) {

    // make sure we have our (single) worker thread
    static std::once_flag sCheckOnce;
    std::call_once(sCheckOnce, [&](){
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        pthread_create(&myThread, &attr, closing_thread_func, nullptr);
        pthread_attr_destroy(&attr);
    });

    {
        std::lock_guard _lm(pending_mutex);     // scoped, no explicit unlock
        pending.push_back(ds);
    }
    pending_added.notify_one();     // get the worker thread going
}

RemoteMediaExtractor::~RemoteMediaExtractor() {
    delete mExtractor;
    // TODO(287851984) hook for changing behavior this dynamically, drop after testing
    int8_t new_scheme = property_get_bool("debug.mediaextractor.delayedclose", 1);
    if (new_scheme != 0) {
        ALOGV("deferred close()");
        start_close_thread(mSource);
        mSource.clear();
    } else {
        ALOGV("immediate close()");
        mSource->close();
        mSource.clear();
    }
    mExtractorPlugin = nullptr;
    // log the current record, provided it has some information worth recording
    if (MEDIA_LOG) {