Loading libs/vr/libdvr/dvr_hardware_composer_client.cpp +36 −9 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,9 @@ #include <binder/IServiceManager.h> #include <binder/IServiceManager.h> #include <private/android/AHardwareBufferHelpers.h> #include <private/android/AHardwareBufferHelpers.h> #include <functional> #include <memory> #include <memory> #include <mutex> struct DvrHwcFrame { struct DvrHwcFrame { android::dvr::ComposerView::Frame frame; android::dvr::ComposerView::Frame frame; Loading @@ -16,10 +18,15 @@ namespace { class HwcCallback : public android::dvr::BnVrComposerCallback { class HwcCallback : public android::dvr::BnVrComposerCallback { public: public: explicit HwcCallback(DvrHwcOnFrameCallback callback, using CallbackFunction = std::function<int(DvrHwcFrame*)>; void* client_state); explicit HwcCallback(const CallbackFunction& callback); ~HwcCallback() override; ~HwcCallback() override; // Reset the callback. This needs to be done early to avoid use after free // accesses from binder thread callbacks. void Shutdown(); std::unique_ptr<DvrHwcFrame> DequeueFrame(); std::unique_ptr<DvrHwcFrame> DequeueFrame(); private: private: Loading @@ -28,26 +35,41 @@ class HwcCallback : public android::dvr::BnVrComposerCallback { const android::dvr::ParcelableComposerFrame& frame, const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) override; android::dvr::ParcelableUniqueFd* fence) override; DvrHwcOnFrameCallback callback_; // Protects the |callback_| from uses from multiple threads. During shutdown void* client_state_; // there may be in-flight frame update events. In those cases the callback // access needs to be protected otherwise binder threads may access an invalid // callback. std::mutex mutex_; CallbackFunction callback_; HwcCallback(const HwcCallback&) = delete; HwcCallback(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; }; }; HwcCallback::HwcCallback(DvrHwcOnFrameCallback callback, void* client_state) HwcCallback::HwcCallback(const CallbackFunction& callback) : callback_(callback), client_state_(client_state) {} : callback_(callback) {} HwcCallback::~HwcCallback() {} HwcCallback::~HwcCallback() {} void HwcCallback::Shutdown() { std::lock_guard<std::mutex> guard(mutex_); callback_ = nullptr; } android::binder::Status HwcCallback::onNewFrame( android::binder::Status HwcCallback::onNewFrame( const android::dvr::ParcelableComposerFrame& frame, const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) { android::dvr::ParcelableUniqueFd* fence) { std::lock_guard<std::mutex> guard(mutex_); if (!callback_) { fence->set_fence(android::base::unique_fd()); return android::binder::Status::ok(); } std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame()); std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame()); dvr_frame->frame = frame.frame(); dvr_frame->frame = frame.frame(); fence->set_fence(android::base::unique_fd(callback_(client_state_, fence->set_fence(android::base::unique_fd(callback_(dvr_frame.release()))); dvr_frame.release()))); return android::binder::Status::ok(); return android::binder::Status::ok(); } } Loading @@ -67,7 +89,8 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) { if (!client->composer.get()) if (!client->composer.get()) return nullptr; return nullptr; client->callback = new HwcCallback(callback, data); client->callback = new HwcCallback(std::bind(callback, data, std::placeholders::_1)); android::binder::Status status = client->composer->registerObserver( android::binder::Status status = client->composer->registerObserver( client->callback); client->callback); if (!status.isOk()) if (!status.isOk()) Loading @@ -77,6 +100,10 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) { } } void dvrHwcClientDestroy(DvrHwcClient* client) { void dvrHwcClientDestroy(DvrHwcClient* client) { // NOTE: Deleting DvrHwcClient* isn't enough since DvrHwcClient::callback is a // shared pointer that could be referenced from a binder thread. But the // client callback isn't valid past this calls so that needs to be reset. client->callback->Shutdown(); delete client; delete client; } } Loading Loading
libs/vr/libdvr/dvr_hardware_composer_client.cpp +36 −9 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,9 @@ #include <binder/IServiceManager.h> #include <binder/IServiceManager.h> #include <private/android/AHardwareBufferHelpers.h> #include <private/android/AHardwareBufferHelpers.h> #include <functional> #include <memory> #include <memory> #include <mutex> struct DvrHwcFrame { struct DvrHwcFrame { android::dvr::ComposerView::Frame frame; android::dvr::ComposerView::Frame frame; Loading @@ -16,10 +18,15 @@ namespace { class HwcCallback : public android::dvr::BnVrComposerCallback { class HwcCallback : public android::dvr::BnVrComposerCallback { public: public: explicit HwcCallback(DvrHwcOnFrameCallback callback, using CallbackFunction = std::function<int(DvrHwcFrame*)>; void* client_state); explicit HwcCallback(const CallbackFunction& callback); ~HwcCallback() override; ~HwcCallback() override; // Reset the callback. This needs to be done early to avoid use after free // accesses from binder thread callbacks. void Shutdown(); std::unique_ptr<DvrHwcFrame> DequeueFrame(); std::unique_ptr<DvrHwcFrame> DequeueFrame(); private: private: Loading @@ -28,26 +35,41 @@ class HwcCallback : public android::dvr::BnVrComposerCallback { const android::dvr::ParcelableComposerFrame& frame, const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) override; android::dvr::ParcelableUniqueFd* fence) override; DvrHwcOnFrameCallback callback_; // Protects the |callback_| from uses from multiple threads. During shutdown void* client_state_; // there may be in-flight frame update events. In those cases the callback // access needs to be protected otherwise binder threads may access an invalid // callback. std::mutex mutex_; CallbackFunction callback_; HwcCallback(const HwcCallback&) = delete; HwcCallback(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; }; }; HwcCallback::HwcCallback(DvrHwcOnFrameCallback callback, void* client_state) HwcCallback::HwcCallback(const CallbackFunction& callback) : callback_(callback), client_state_(client_state) {} : callback_(callback) {} HwcCallback::~HwcCallback() {} HwcCallback::~HwcCallback() {} void HwcCallback::Shutdown() { std::lock_guard<std::mutex> guard(mutex_); callback_ = nullptr; } android::binder::Status HwcCallback::onNewFrame( android::binder::Status HwcCallback::onNewFrame( const android::dvr::ParcelableComposerFrame& frame, const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) { android::dvr::ParcelableUniqueFd* fence) { std::lock_guard<std::mutex> guard(mutex_); if (!callback_) { fence->set_fence(android::base::unique_fd()); return android::binder::Status::ok(); } std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame()); std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame()); dvr_frame->frame = frame.frame(); dvr_frame->frame = frame.frame(); fence->set_fence(android::base::unique_fd(callback_(client_state_, fence->set_fence(android::base::unique_fd(callback_(dvr_frame.release()))); dvr_frame.release()))); return android::binder::Status::ok(); return android::binder::Status::ok(); } } Loading @@ -67,7 +89,8 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) { if (!client->composer.get()) if (!client->composer.get()) return nullptr; return nullptr; client->callback = new HwcCallback(callback, data); client->callback = new HwcCallback(std::bind(callback, data, std::placeholders::_1)); android::binder::Status status = client->composer->registerObserver( android::binder::Status status = client->composer->registerObserver( client->callback); client->callback); if (!status.isOk()) if (!status.isOk()) Loading @@ -77,6 +100,10 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) { } } void dvrHwcClientDestroy(DvrHwcClient* client) { void dvrHwcClientDestroy(DvrHwcClient* client) { // NOTE: Deleting DvrHwcClient* isn't enough since DvrHwcClient::callback is a // shared pointer that could be referenced from a binder thread. But the // client callback isn't valid past this calls so that needs to be reset. client->callback->Shutdown(); delete client; delete client; } } Loading