From e576011ebbe85e4db66f9d3c4912c6ade5f4a5ea Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 30 Dec 2025 13:49:01 +0100 Subject: [PATCH] fix hardware buffer aidl --- build.gradle.kts | 2 +- .../aidl/android/hardware/HardwareBuffer.aidl | 3 + .../com/omixlab/mosis/IMosisListener.aidl | 5 +- src/main/cpp/CMakeLists.txt | 4 +- .../aidl/com/omixlab/mosis/BnMosisListener.h | 7 +- .../aidl/com/omixlab/mosis/BpMosisListener.h | 3 +- .../aidl/com/omixlab/mosis/IMosisListener.h | 10 ++- .../cpp/com/omixlab/mosis/IMosisListener.cpp | 59 +++++++++++-- src/main/cpp/mosis-service.cpp | 11 ++- src/main/cpp/mosis-test.cpp | 82 ++++++++++++++++++- .../java/com/omixlab/mosis/MainActivity.kt | 19 +---- 11 files changed, 162 insertions(+), 43 deletions(-) create mode 100644 src/main/aidl/android/hardware/HardwareBuffer.aidl diff --git a/build.gradle.kts b/build.gradle.kts index 74eb3c9..306bf62 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ android { defaultConfig { applicationId = "com.omixlab.mosis" - minSdk = 33 + minSdk = 34 targetSdk = 36 versionCode = 1 versionName = "1.0" diff --git a/src/main/aidl/android/hardware/HardwareBuffer.aidl b/src/main/aidl/android/hardware/HardwareBuffer.aidl new file mode 100644 index 0000000..ae119e3 --- /dev/null +++ b/src/main/aidl/android/hardware/HardwareBuffer.aidl @@ -0,0 +1,3 @@ +package android.hardware; + +@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h"; diff --git a/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl b/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl index 3d47462..4387be4 100644 --- a/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl +++ b/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl @@ -1,7 +1,10 @@ package com.omixlab.mosis; +import android.hardware.HardwareBuffer; + // oneway = fire-and-forget (asynchronous) oneway interface IMosisListener { void onServiceInitialized(boolean success); - void onFrameAvailable(long hardwareBufferPtr); + void onBufferAvailable(in HardwareBuffer buffer); + void onFrameAvailable(); } diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt index 66d87ae..858e427 100644 --- a/src/main/cpp/CMakeLists.txt +++ b/src/main/cpp/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(mosis-service SHARED target_include_directories(mosis-service PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${BINDER_DIR} glad/include) target_link_libraries(mosis-service - android log binder_ndk EGL GLESv2) + android log binder_ndk EGL GLESv2 nativewindow) add_library(mosis-test SHARED com/omixlab/mosis/IMosisService.cpp @@ -32,4 +32,4 @@ add_library(mosis-test SHARED target_include_directories(mosis-test PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${BINDER_DIR} glad/include) target_link_libraries(mosis-test - android log binder_ndk EGL GLESv2) + android log binder_ndk EGL GLESv2 nativewindow) diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h index 60aa64f..5f29dc8 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h @@ -39,8 +39,11 @@ public: ::ndk::ScopedAStatus onServiceInitialized(bool in_success) override { return _impl->onServiceInitialized(in_success); } - ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override { - return _impl->onFrameAvailable(in_hardwareBufferPtr); + ::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override { + return _impl->onBufferAvailable(in_buffer); + } + ::ndk::ScopedAStatus onFrameAvailable() override { + return _impl->onFrameAvailable(); } protected: private: diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h index 48b5d91..7bbd23a 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h @@ -22,7 +22,8 @@ public: virtual ~BpMosisListener(); ::ndk::ScopedAStatus onServiceInitialized(bool in_success) override; - ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override; + ::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override; + ::ndk::ScopedAStatus onFrameAvailable() override; }; } // namespace mosis } // namespace omixlab diff --git a/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h index 870b1b9..99c655f 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef BINDER_STABILITY_SUPPORT #include #endif // BINDER_STABILITY_SUPPORT @@ -32,7 +33,8 @@ public: virtual ~IMosisListener(); static constexpr uint32_t TRANSACTION_onServiceInitialized = FIRST_CALL_TRANSACTION + 0; - static constexpr uint32_t TRANSACTION_onFrameAvailable = FIRST_CALL_TRANSACTION + 1; + static constexpr uint32_t TRANSACTION_onBufferAvailable = FIRST_CALL_TRANSACTION + 1; + static constexpr uint32_t TRANSACTION_onFrameAvailable = FIRST_CALL_TRANSACTION + 2; static std::shared_ptr fromBinder(const ::ndk::SpAIBinder& binder); static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr& instance); @@ -40,14 +42,16 @@ public: static bool setDefaultImpl(const std::shared_ptr& impl); static const std::shared_ptr& getDefaultImpl(); virtual ::ndk::ScopedAStatus onServiceInitialized(bool in_success) = 0; - virtual ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) = 0; + virtual ::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) = 0; + virtual ::ndk::ScopedAStatus onFrameAvailable() = 0; private: static std::shared_ptr default_impl; }; class IMosisListenerDefault : public IMosisListener { public: ::ndk::ScopedAStatus onServiceInitialized(bool in_success) override; - ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override; + ::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override; + ::ndk::ScopedAStatus onFrameAvailable() override; ::ndk::SpAIBinder asBinder() override; bool isRemote() override; }; diff --git a/src/main/cpp/com/omixlab/mosis/IMosisListener.cpp b/src/main/cpp/com/omixlab/mosis/IMosisListener.cpp index c582e59..a80662b 100644 --- a/src/main/cpp/com/omixlab/mosis/IMosisListener.cpp +++ b/src/main/cpp/com/omixlab/mosis/IMosisListener.cpp @@ -35,13 +35,19 @@ static binder_status_t _aidl_com_omixlab_mosis_IMosisListener_onTransact(AIBinde _aidl_ret_status = STATUS_OK; break; } - case (FIRST_CALL_TRANSACTION + 1 /*onFrameAvailable*/): { - int64_t in_hardwareBufferPtr; + case (FIRST_CALL_TRANSACTION + 1 /*onBufferAvailable*/): { + ::aidl::android::hardware::HardwareBuffer in_buffer; - _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_hardwareBufferPtr); + _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_buffer); if (_aidl_ret_status != STATUS_OK) break; - ::ndk::ScopedAStatus _aidl_status = _aidl_impl->onFrameAvailable(in_hardwareBufferPtr); + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->onBufferAvailable(in_buffer); + _aidl_ret_status = STATUS_OK; + break; + } + case (FIRST_CALL_TRANSACTION + 2 /*onFrameAvailable*/): { + + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->onFrameAvailable(); _aidl_ret_status = STATUS_OK; break; } @@ -87,7 +93,7 @@ BpMosisListener::~BpMosisListener() {} _aidl_status_return: return _aidl_status; } -::ndk::ScopedAStatus BpMosisListener::onFrameAvailable(int64_t in_hardwareBufferPtr) { +::ndk::ScopedAStatus BpMosisListener::onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) { binder_status_t _aidl_ret_status = STATUS_OK; ::ndk::ScopedAStatus _aidl_status; ::ndk::ScopedAParcel _aidl_in; @@ -96,12 +102,12 @@ BpMosisListener::~BpMosisListener() {} _aidl_ret_status = AIBinder_prepareTransaction(asBinderReference().get(), _aidl_in.getR()); if (_aidl_ret_status != STATUS_OK) goto _aidl_error; - _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_hardwareBufferPtr); + _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_buffer); if (_aidl_ret_status != STATUS_OK) goto _aidl_error; _aidl_ret_status = AIBinder_transact( asBinderReference().get(), - (FIRST_CALL_TRANSACTION + 1 /*onFrameAvailable*/), + (FIRST_CALL_TRANSACTION + 1 /*onBufferAvailable*/), _aidl_in.getR(), _aidl_out.getR(), FLAG_ONEWAY @@ -110,7 +116,37 @@ BpMosisListener::~BpMosisListener() {} #endif // BINDER_STABILITY_SUPPORT ); if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMosisListener::getDefaultImpl()) { - _aidl_status = IMosisListener::getDefaultImpl()->onFrameAvailable(in_hardwareBufferPtr); + _aidl_status = IMosisListener::getDefaultImpl()->onBufferAvailable(in_buffer); + goto _aidl_status_return; + } + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_error: + _aidl_status.set(AStatus_fromStatus(_aidl_ret_status)); + _aidl_status_return: + return _aidl_status; +} +::ndk::ScopedAStatus BpMosisListener::onFrameAvailable() { + binder_status_t _aidl_ret_status = STATUS_OK; + ::ndk::ScopedAStatus _aidl_status; + ::ndk::ScopedAParcel _aidl_in; + ::ndk::ScopedAParcel _aidl_out; + + _aidl_ret_status = AIBinder_prepareTransaction(asBinderReference().get(), _aidl_in.getR()); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AIBinder_transact( + asBinderReference().get(), + (FIRST_CALL_TRANSACTION + 2 /*onFrameAvailable*/), + _aidl_in.getR(), + _aidl_out.getR(), + FLAG_ONEWAY + #ifdef BINDER_STABILITY_SUPPORT + | static_cast(FLAG_PRIVATE_LOCAL) + #endif // BINDER_STABILITY_SUPPORT + ); + if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMosisListener::getDefaultImpl()) { + _aidl_status = IMosisListener::getDefaultImpl()->onFrameAvailable(); goto _aidl_status_return; } if (_aidl_ret_status != STATUS_OK) goto _aidl_error; @@ -184,7 +220,12 @@ std::shared_ptr IMosisListener::default_impl = nullptr; _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); return _aidl_status; } -::ndk::ScopedAStatus IMosisListenerDefault::onFrameAvailable(int64_t /*in_hardwareBufferPtr*/) { +::ndk::ScopedAStatus IMosisListenerDefault::onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& /*in_buffer*/) { + ::ndk::ScopedAStatus _aidl_status; + _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); + return _aidl_status; +} +::ndk::ScopedAStatus IMosisListenerDefault::onFrameAvailable() { ::ndk::ScopedAStatus _aidl_status; _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); return _aidl_status; diff --git a/src/main/cpp/mosis-service.cpp b/src/main/cpp/mosis-service.cpp index b64d54f..ee900ed 100644 --- a/src/main/cpp/mosis-service.cpp +++ b/src/main/cpp/mosis-service.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "egl_context.h" #include "logger.h" #include @@ -10,6 +11,7 @@ #include using namespace aidl::com::omixlab::mosis; +using namespace aidl::android::hardware; class Texture { @@ -91,9 +93,9 @@ public: return status; } - [[nodiscard]] long hardware_buffer() + [[nodiscard]] AHardwareBuffer* hardware_buffer() { - return reinterpret_cast(hardwareBuffer); + return hardwareBuffer; } void bind() { @@ -115,6 +117,7 @@ class Kernel std::unique_ptr m_egl_context; std::unique_ptr m_render_target; std::shared_ptr m_listener; + HardwareBuffer m_aidl_buffer; std::thread m_main_loop_thread; void main_loop() { @@ -132,13 +135,15 @@ class Kernel } m_render_target->bind(); m_listener->onServiceInitialized(true); + m_aidl_buffer.reset(m_render_target->hardware_buffer()); + m_listener->onBufferAvailable(m_aidl_buffer); while (true) { glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glFinish(); - m_listener->onFrameAvailable(m_render_target->hardware_buffer()); + m_listener->onFrameAvailable(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } diff --git a/src/main/cpp/mosis-test.cpp b/src/main/cpp/mosis-test.cpp index fbdda54..9bfc45f 100644 --- a/src/main/cpp/mosis-test.cpp +++ b/src/main/cpp/mosis-test.cpp @@ -1,18 +1,55 @@ #include #include #include +#include +#include #include #include "logger.h" #include "egl_context.h" #include +#include #include #include using namespace aidl::com::omixlab::mosis; +using namespace aidl::android::hardware; -class Renderer +class Shader +{ + +}; + +class ImportedTexture +{ + GLuint texture = 0; +public: + bool create(AHardwareBuffer* hardwareBuffer) + { + AHardwareBuffer_Desc desc{}; + AHardwareBuffer_describe(hardwareBuffer, &desc); + EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer); + EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, + EGL_NATIVE_BUFFER_ANDROID, clientBuffer, nullptr); + if (eglImage == EGL_NO_IMAGE_KHR) + { + Logger::Log("Failed to create EGL image"); + return false; + } + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); + eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + return true; + } +}; + +class Renderer : public BnMosisListener { std::unique_ptr m_egl_context; + std::unique_ptr m_texture; + AHardwareBuffer* m_hwbuffer = nullptr; std::thread m_render_loop; bool m_active = false; void render_loop(ANativeWindow* window) @@ -23,6 +60,14 @@ class Renderer m_active = true; while (m_active) { + if (m_hwbuffer && !m_texture) + { + m_texture = std::make_unique(); + if (!m_texture->create(m_hwbuffer)) + { + Logger::Log("Failed to create texture"); + } + } render_frame(); } } @@ -35,9 +80,14 @@ class Renderer { glClearColor(0.f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + if (m_texture) + { + + } m_egl_context->swap(); } public: + Renderer() = default; bool create(ANativeWindow* window) { m_render_loop = std::thread(&Renderer::render_loop, this, window); @@ -51,10 +101,25 @@ public: m_egl_context->destroy(); m_egl_context.reset(); } + ndk::ScopedAStatus onServiceInitialized(bool in_success) override + { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus onFrameAvailable() override + { + Logger::Log("onFrameAvailable"); + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus onBufferAvailable(const HardwareBuffer &in_buffer) override + { + m_hwbuffer = in_buffer.get(); + AHardwareBuffer_acquire(m_hwbuffer); + return ndk::ScopedAStatus::ok(); + } }; std::shared_ptr g_service; -std::unique_ptr g_renderer; +std::shared_ptr g_renderer; extern "C" JNIEXPORT void JNICALL @@ -67,6 +132,17 @@ Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz, Logger::Log("Service Connected"); } +extern "C" +JNIEXPORT void JNICALL +Java_com_omixlab_mosis_MainActivity_initOS(JNIEnv *env, jobject thiz) +{ + if (g_service && g_renderer) + { + bool result{}; + g_service->initOS(g_renderer, &result); + } +} + extern "C" JNIEXPORT void JNICALL Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, @@ -75,7 +151,7 @@ Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, Logger::Log("setSurface"); if (!g_renderer) { - g_renderer = std::make_unique(); + g_renderer = ndk::SharedRefBase::make(); g_renderer->create(ANativeWindow_fromSurface(env, surface)); } } diff --git a/src/main/java/com/omixlab/mosis/MainActivity.kt b/src/main/java/com/omixlab/mosis/MainActivity.kt index 4e11c3c..4f7613e 100644 --- a/src/main/java/com/omixlab/mosis/MainActivity.kt +++ b/src/main/java/com/omixlab/mosis/MainActivity.kt @@ -65,24 +65,6 @@ class MainActivity : ComponentActivity() { Log.d("MosisTest", "surfaceDestroyed") } } - val listener = object : IMosisListener.Stub() { - override fun onServiceInitialized(success: Boolean) { - Log.d("MosisTest", "onServiceInitialized: $success") - - } - - override fun onFrameAvailable(hardwareBufferPtr: Long) { - Log.d("MosisTest", "onFrameAvailable: $hardwareBufferPtr") - } - } - fun initOS() - { - remote_service?.let { service -> - val result = service.initOS(listener) - Log.d("MosisTest", "InitOS returned: $result") - buttonText.value = if (result) "OS Initialized" else "OS Not Initialized" - } - } fun startRemoteService() { val intent = Intent("com.omixlab.mosis.SERVICE") intent.setPackage("com.omixlab.mosis") @@ -129,4 +111,5 @@ class MainActivity : ComponentActivity() { external fun serviceConnected(binder: IBinder) external fun setSurface(surface: Surface) external fun destroySurface() + external fun initOS() } \ No newline at end of file