diff --git a/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl b/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl new file mode 100644 index 0000000..3d47462 --- /dev/null +++ b/src/main/aidl/com/omixlab/mosis/IMosisListener.aidl @@ -0,0 +1,7 @@ +package com.omixlab.mosis; + +// oneway = fire-and-forget (asynchronous) +oneway interface IMosisListener { + void onServiceInitialized(boolean success); + void onFrameAvailable(long hardwareBufferPtr); +} diff --git a/src/main/aidl/com/omixlab/mosis/IMosisService.aidl b/src/main/aidl/com/omixlab/mosis/IMosisService.aidl index ce10aa1..faed57b 100644 --- a/src/main/aidl/com/omixlab/mosis/IMosisService.aidl +++ b/src/main/aidl/com/omixlab/mosis/IMosisService.aidl @@ -1,6 +1,8 @@ package com.omixlab.mosis; +import com.omixlab.mosis.IMosisListener; + interface IMosisService { - boolean initOS(); + boolean initOS(IMosisListener listener); int getNumber(); } \ No newline at end of file diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt index e363666..66d87ae 100644 --- a/src/main/cpp/CMakeLists.txt +++ b/src/main/cpp/CMakeLists.txt @@ -10,6 +10,7 @@ set(BINDER_DIR "${ANDROID_SDK}/platforms/android-36/optional/libbinder_ndk_cpp") add_library(mosis-service SHARED mosis-service.cpp com/omixlab/mosis/IMosisService.cpp + com/omixlab/mosis/IMosisListener.cpp egl_context.cpp logger.cpp glad/src/egl.c @@ -21,6 +22,7 @@ target_link_libraries(mosis-service add_library(mosis-test SHARED com/omixlab/mosis/IMosisService.cpp + com/omixlab/mosis/IMosisListener.cpp mosis-test.cpp egl_context.cpp logger.cpp diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h new file mode 100644 index 0000000..60aa64f --- /dev/null +++ b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisListener.h @@ -0,0 +1,53 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Using: /Users/omar/Library/Android/sdk/build-tools/36.1.0/aidl --lang=ndk --min_sdk_version=36 -o src/main/cpp -h src/main/cpp -I src/main/aidl src/main/aidl/com/omixlab/mosis/IMosisListener.aidl + * + * DO NOT CHECK THIS FILE INTO A CODE TREE (e.g. git, etc..). + * ALWAYS GENERATE THIS FILE FROM UPDATED AIDL COMPILER + * AS A BUILD INTERMEDIATE ONLY. THIS IS NOT SOURCE CODE. + */ +#pragma once + +#include "aidl/com/omixlab/mosis/IMosisListener.h" + +#include +#include + +#ifndef __BIONIC__ +#ifndef __assert2 +#define __assert2(a,b,c,d) ((void)0) +#endif +#endif + +namespace aidl { +namespace com { +namespace omixlab { +namespace mosis { +class BnMosisListener : public ::ndk::BnCInterface { +public: + BnMosisListener(); + virtual ~BnMosisListener(); +protected: + ::ndk::SpAIBinder createBinder() override; +private: +}; +class IMosisListenerDelegator : public BnMosisListener { +public: + explicit IMosisListenerDelegator(const std::shared_ptr &impl) : _impl(impl) { + } + + ::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); + } +protected: +private: + std::shared_ptr _impl; +}; + +} // namespace mosis +} // namespace omixlab +} // namespace com +} // namespace aidl diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BnMosisService.h b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisService.h index 031b8f0..59ae1b6 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/BnMosisService.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/BnMosisService.h @@ -36,8 +36,8 @@ public: explicit IMosisServiceDelegator(const std::shared_ptr &impl) : _impl(impl) { } - ::ndk::ScopedAStatus initOS(bool* _aidl_return) override { - return _impl->initOS(_aidl_return); + ::ndk::ScopedAStatus initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& in_listener, bool* _aidl_return) override { + return _impl->initOS(in_listener, _aidl_return); } ::ndk::ScopedAStatus getNumber(int32_t* _aidl_return) override { return _impl->getNumber(_aidl_return); diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h new file mode 100644 index 0000000..48b5d91 --- /dev/null +++ b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisListener.h @@ -0,0 +1,30 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Using: /Users/omar/Library/Android/sdk/build-tools/36.1.0/aidl --lang=ndk --min_sdk_version=36 -o src/main/cpp -h src/main/cpp -I src/main/aidl src/main/aidl/com/omixlab/mosis/IMosisListener.aidl + * + * DO NOT CHECK THIS FILE INTO A CODE TREE (e.g. git, etc..). + * ALWAYS GENERATE THIS FILE FROM UPDATED AIDL COMPILER + * AS A BUILD INTERMEDIATE ONLY. THIS IS NOT SOURCE CODE. + */ +#pragma once + +#include "aidl/com/omixlab/mosis/IMosisListener.h" + +#include + +namespace aidl { +namespace com { +namespace omixlab { +namespace mosis { +class BpMosisListener : public ::ndk::BpCInterface { +public: + explicit BpMosisListener(const ::ndk::SpAIBinder& binder); + virtual ~BpMosisListener(); + + ::ndk::ScopedAStatus onServiceInitialized(bool in_success) override; + ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override; +}; +} // namespace mosis +} // namespace omixlab +} // namespace com +} // namespace aidl diff --git a/src/main/cpp/aidl/com/omixlab/mosis/BpMosisService.h b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisService.h index c472c5a..a87812d 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/BpMosisService.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/BpMosisService.h @@ -21,7 +21,7 @@ public: explicit BpMosisService(const ::ndk::SpAIBinder& binder); virtual ~BpMosisService(); - ::ndk::ScopedAStatus initOS(bool* _aidl_return) override; + ::ndk::ScopedAStatus initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& in_listener, bool* _aidl_return) override; ::ndk::ScopedAStatus getNumber(int32_t* _aidl_return) override; }; } // namespace mosis diff --git a/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h b/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h new file mode 100644 index 0000000..870b1b9 --- /dev/null +++ b/src/main/cpp/aidl/com/omixlab/mosis/IMosisListener.h @@ -0,0 +1,57 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Using: /Users/omar/Library/Android/sdk/build-tools/36.1.0/aidl --lang=ndk --min_sdk_version=36 -o src/main/cpp -h src/main/cpp -I src/main/aidl src/main/aidl/com/omixlab/mosis/IMosisListener.aidl + * + * DO NOT CHECK THIS FILE INTO A CODE TREE (e.g. git, etc..). + * ALWAYS GENERATE THIS FILE FROM UPDATED AIDL COMPILER + * AS A BUILD INTERMEDIATE ONLY. THIS IS NOT SOURCE CODE. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#ifdef BINDER_STABILITY_SUPPORT +#include +#endif // BINDER_STABILITY_SUPPORT + +namespace aidl { +namespace com { +namespace omixlab { +namespace mosis { +class IMosisListenerDelegator; + +class IMosisListener : public ::ndk::ICInterface { +public: + typedef IMosisListenerDelegator DefaultDelegator; + static const char* descriptor; + IMosisListener(); + virtual ~IMosisListener(); + + static constexpr uint32_t TRANSACTION_onServiceInitialized = FIRST_CALL_TRANSACTION + 0; + static constexpr uint32_t TRANSACTION_onFrameAvailable = FIRST_CALL_TRANSACTION + 1; + + static std::shared_ptr fromBinder(const ::ndk::SpAIBinder& binder); + static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr& instance); + static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr* instance); + 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; +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::SpAIBinder asBinder() override; + bool isRemote() override; +}; +} // namespace mosis +} // namespace omixlab +} // namespace com +} // namespace aidl diff --git a/src/main/cpp/aidl/com/omixlab/mosis/IMosisService.h b/src/main/cpp/aidl/com/omixlab/mosis/IMosisService.h index ec33f83..599bc6a 100644 --- a/src/main/cpp/aidl/com/omixlab/mosis/IMosisService.h +++ b/src/main/cpp/aidl/com/omixlab/mosis/IMosisService.h @@ -14,10 +14,14 @@ #include #include #include +#include #ifdef BINDER_STABILITY_SUPPORT #include #endif // BINDER_STABILITY_SUPPORT +namespace aidl::com::omixlab::mosis { +class IMosisListener; +} // namespace aidl::com::omixlab::mosis namespace aidl { namespace com { namespace omixlab { @@ -39,14 +43,14 @@ public: static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr* instance); static bool setDefaultImpl(const std::shared_ptr& impl); static const std::shared_ptr& getDefaultImpl(); - virtual ::ndk::ScopedAStatus initOS(bool* _aidl_return) = 0; + virtual ::ndk::ScopedAStatus initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& in_listener, bool* _aidl_return) = 0; virtual ::ndk::ScopedAStatus getNumber(int32_t* _aidl_return) = 0; private: static std::shared_ptr default_impl; }; class IMosisServiceDefault : public IMosisService { public: - ::ndk::ScopedAStatus initOS(bool* _aidl_return) override; + ::ndk::ScopedAStatus initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& in_listener, bool* _aidl_return) override; ::ndk::ScopedAStatus getNumber(int32_t* _aidl_return) 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 new file mode 100644 index 0000000..c582e59 --- /dev/null +++ b/src/main/cpp/com/omixlab/mosis/IMosisListener.cpp @@ -0,0 +1,201 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Using: /Users/omar/Library/Android/sdk/build-tools/36.1.0/aidl --lang=ndk --min_sdk_version=36 -o src/main/cpp -h src/main/cpp -I src/main/aidl src/main/aidl/com/omixlab/mosis/IMosisListener.aidl + * + * DO NOT CHECK THIS FILE INTO A CODE TREE (e.g. git, etc..). + * ALWAYS GENERATE THIS FILE FROM UPDATED AIDL COMPILER + * AS A BUILD INTERMEDIATE ONLY. THIS IS NOT SOURCE CODE. + */ +#include "aidl/com/omixlab/mosis/IMosisListener.h" + +#include +#include +#include +#include +#include +#include + +namespace aidl { +namespace com { +namespace omixlab { +namespace mosis { +static binder_status_t _aidl_com_omixlab_mosis_IMosisListener_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) { + (void)_aidl_in; + (void)_aidl_out; + binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION; + std::shared_ptr _aidl_impl = std::static_pointer_cast(::ndk::ICInterface::asInterface(_aidl_binder)); + switch (_aidl_code) { + case (FIRST_CALL_TRANSACTION + 0 /*onServiceInitialized*/): { + bool in_success; + + _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_success); + if (_aidl_ret_status != STATUS_OK) break; + + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->onServiceInitialized(in_success); + _aidl_ret_status = STATUS_OK; + break; + } + case (FIRST_CALL_TRANSACTION + 1 /*onFrameAvailable*/): { + int64_t in_hardwareBufferPtr; + + _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_hardwareBufferPtr); + if (_aidl_ret_status != STATUS_OK) break; + + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->onFrameAvailable(in_hardwareBufferPtr); + _aidl_ret_status = STATUS_OK; + break; + } + } + return _aidl_ret_status; +} + +static AIBinder_Class* _g_aidl_com_omixlab_mosis_IMosisListener_clazz = ::ndk::ICInterface::defineClass(IMosisListener::descriptor, _aidl_com_omixlab_mosis_IMosisListener_onTransact, nullptr, 0); + +BpMosisListener::BpMosisListener(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {} +BpMosisListener::~BpMosisListener() {} + +::ndk::ScopedAStatus BpMosisListener::onServiceInitialized(bool in_success) { + 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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_success); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AIBinder_transact( + asBinderReference().get(), + (FIRST_CALL_TRANSACTION + 0 /*onServiceInitialized*/), + _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()->onServiceInitialized(in_success); + 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(int64_t in_hardwareBufferPtr) { + 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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_hardwareBufferPtr); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AIBinder_transact( + asBinderReference().get(), + (FIRST_CALL_TRANSACTION + 1 /*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(in_hardwareBufferPtr); + 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; +} +// Source for BnMosisListener +BnMosisListener::BnMosisListener() {} +BnMosisListener::~BnMosisListener() {} +::ndk::SpAIBinder BnMosisListener::createBinder() { + AIBinder* binder = AIBinder_new(_g_aidl_com_omixlab_mosis_IMosisListener_clazz, static_cast(this)); + #ifdef BINDER_STABILITY_SUPPORT + AIBinder_markCompilationUnitStability(binder); + #endif // BINDER_STABILITY_SUPPORT + return ::ndk::SpAIBinder(binder); +} +// Source for IMosisListener +const char* IMosisListener::descriptor = "com.omixlab.mosis.IMosisListener"; +IMosisListener::IMosisListener() {} +IMosisListener::~IMosisListener() {} + + +std::shared_ptr IMosisListener::fromBinder(const ::ndk::SpAIBinder& binder) { + if (!AIBinder_associateClass(binder.get(), _g_aidl_com_omixlab_mosis_IMosisListener_clazz)) { + #if __ANDROID_API__ >= 31 + const AIBinder_Class* originalClass = AIBinder_getClass(binder.get()); + if (originalClass == nullptr) return nullptr; + if (0 == strcmp(AIBinder_Class_getDescriptor(originalClass), descriptor)) { + return ::ndk::SharedRefBase::make(binder); + } + #endif + return nullptr; + } + std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get()); + if (interface) { + return std::static_pointer_cast(interface); + } + return ::ndk::SharedRefBase::make(binder); +} + +binder_status_t IMosisListener::writeToParcel(AParcel* parcel, const std::shared_ptr& instance) { + return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr); +} +binder_status_t IMosisListener::readFromParcel(const AParcel* parcel, std::shared_ptr* instance) { + ::ndk::SpAIBinder binder; + binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR()); + if (status != STATUS_OK) return status; + *instance = IMosisListener::fromBinder(binder); + return STATUS_OK; +} +bool IMosisListener::setDefaultImpl(const std::shared_ptr& impl) { + // Only one user of this interface can use this function + // at a time. This is a heuristic to detect if two different + // users in the same process use this function. + assert(!IMosisListener::default_impl); + if (impl) { + IMosisListener::default_impl = impl; + return true; + } + return false; +} +const std::shared_ptr& IMosisListener::getDefaultImpl() { + return IMosisListener::default_impl; +} +std::shared_ptr IMosisListener::default_impl = nullptr; +::ndk::ScopedAStatus IMosisListenerDefault::onServiceInitialized(bool /*in_success*/) { + ::ndk::ScopedAStatus _aidl_status; + _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); + return _aidl_status; +} +::ndk::ScopedAStatus IMosisListenerDefault::onFrameAvailable(int64_t /*in_hardwareBufferPtr*/) { + ::ndk::ScopedAStatus _aidl_status; + _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); + return _aidl_status; +} +::ndk::SpAIBinder IMosisListenerDefault::asBinder() { + return ::ndk::SpAIBinder(); +} +bool IMosisListenerDefault::isRemote() { + return false; +} +} // namespace mosis +} // namespace omixlab +} // namespace com +} // namespace aidl diff --git a/src/main/cpp/com/omixlab/mosis/IMosisService.cpp b/src/main/cpp/com/omixlab/mosis/IMosisService.cpp index f91d70f..f989799 100644 --- a/src/main/cpp/com/omixlab/mosis/IMosisService.cpp +++ b/src/main/cpp/com/omixlab/mosis/IMosisService.cpp @@ -12,8 +12,11 @@ #include #include #include +#include #include +#include #include +#include namespace aidl { namespace com { @@ -26,9 +29,13 @@ static binder_status_t _aidl_com_omixlab_mosis_IMosisService_onTransact(AIBinder std::shared_ptr _aidl_impl = std::static_pointer_cast(::ndk::ICInterface::asInterface(_aidl_binder)); switch (_aidl_code) { case (FIRST_CALL_TRANSACTION + 0 /*initOS*/): { + std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener> in_listener; bool _aidl_return; - ::ndk::ScopedAStatus _aidl_status = _aidl_impl->initOS(&_aidl_return); + _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_listener); + if (_aidl_ret_status != STATUS_OK) break; + + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->initOS(in_listener, &_aidl_return); _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get()); if (_aidl_ret_status != STATUS_OK) break; @@ -62,7 +69,7 @@ static AIBinder_Class* _g_aidl_com_omixlab_mosis_IMosisService_clazz = ::ndk::IC BpMosisService::BpMosisService(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {} BpMosisService::~BpMosisService() {} -::ndk::ScopedAStatus BpMosisService::initOS(bool* _aidl_return) { +::ndk::ScopedAStatus BpMosisService::initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& in_listener, bool* _aidl_return) { binder_status_t _aidl_ret_status = STATUS_OK; ::ndk::ScopedAStatus _aidl_status; ::ndk::ScopedAParcel _aidl_in; @@ -71,6 +78,9 @@ BpMosisService::~BpMosisService() {} _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_listener); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + _aidl_ret_status = AIBinder_transact( asBinderReference().get(), (FIRST_CALL_TRANSACTION + 0 /*initOS*/), @@ -82,7 +92,7 @@ BpMosisService::~BpMosisService() {} #endif // BINDER_STABILITY_SUPPORT ); if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMosisService::getDefaultImpl()) { - _aidl_status = IMosisService::getDefaultImpl()->initOS(_aidl_return); + _aidl_status = IMosisService::getDefaultImpl()->initOS(in_listener, _aidl_return); goto _aidl_status_return; } if (_aidl_ret_status != STATUS_OK) goto _aidl_error; @@ -195,7 +205,7 @@ const std::shared_ptr& IMosisService::getDefaultImpl() { return IMosisService::default_impl; } std::shared_ptr IMosisService::default_impl = nullptr; -::ndk::ScopedAStatus IMosisServiceDefault::initOS(bool* /*_aidl_return*/) { +::ndk::ScopedAStatus IMosisServiceDefault::initOS(const std::shared_ptr<::aidl::com::omixlab::mosis::IMosisListener>& /*in_listener*/, bool* /*_aidl_return*/) { ::ndk::ScopedAStatus _aidl_status; _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); return _aidl_status; diff --git a/src/main/cpp/egl_context.cpp b/src/main/cpp/egl_context.cpp index 668d453..9779795 100644 --- a/src/main/cpp/egl_context.cpp +++ b/src/main/cpp/egl_context.cpp @@ -4,6 +4,14 @@ #include #include #include +#include + +static void debug_handler(GLenum source, GLenum type, + GLuint id, GLenum severity, GLsizei length, const GLchar* message, + const void* userParam) +{ + Logger::Log(std::format("GL Error: {}", std::string_view(message, length))); +} bool egl::Context::create(ANativeWindow* window) { @@ -74,6 +82,11 @@ bool egl::Context::create(ANativeWindow* window) Logger::Log("glad failed to load GLES2"); return false; } + if (glDebugMessageCallback) + { + glDebugMessageCallback(debug_handler, nullptr); + glEnable(GL_DEBUG_OUTPUT); + } return true; } diff --git a/src/main/cpp/mosis-service.cpp b/src/main/cpp/mosis-service.cpp index 41c438e..5928132 100644 --- a/src/main/cpp/mosis-service.cpp +++ b/src/main/cpp/mosis-service.cpp @@ -1,13 +1,153 @@ #include #include +#include #include +#include #include "egl_context.h" #include "logger.h" +#include +#include +#include using namespace aidl::com::omixlab::mosis; -class NativeService : public BnMosisService { +class Texture +{ + GLuint id; +public: + bool create(uint32_t width, uint32_t height) + { + glGenTextures(1, &id); + return true; + } +}; + +class RenderTarget +{ + AHardwareBuffer* hardwareBuffer = nullptr; + GLuint m_framebuffer = 0; + GLuint texture = 0; +public: + bool create(uint32_t width, uint32_t height) + { + glGenFramebuffers(1, &m_framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + return false; + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return true; + } + bool create_exported(uint32_t width, uint32_t height) + { + AHardwareBuffer_Desc desc = {}; + desc.width = width; + desc.height = height; + desc.layers = 1; + desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | + AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | + AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER; + + if (AHardwareBuffer_allocate(&desc, &hardwareBuffer) != 0) + { + Logger::Log("Failed to allocate hardware buffer"); + return false; + } + + EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer); + EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, + EGL_NATIVE_BUFFER_ANDROID, clientBuffer, nullptr); + + if (eglImage == EGL_NO_IMAGE_KHR) + { + AHardwareBuffer_release(hardwareBuffer); + 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); + + glGenFramebuffers(1, &m_framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + bool status = (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return status; + } + [[nodiscard]] long hardware_buffer() + { + return reinterpret_cast(hardwareBuffer); + } + void bind() + { + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); + } + void unbind() + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + void destroy() + { + glDeleteTextures(1, &texture); + glDeleteFramebuffers(1, &m_framebuffer); + } +}; + +class Kernel +{ std::unique_ptr m_egl_context; + std::unique_ptr m_render_target; + std::shared_ptr m_listener; + std::thread m_main_loop_thread; + void main_loop() + { + m_egl_context = std::make_unique(); + if (!m_egl_context->create()) + { + Logger::Log("failed to create EGL context"); + return; + } + m_render_target = std::make_unique(); + if (!m_render_target->create_exported(1024, 1024)) + { + Logger::Log("failed to create render target"); + return; + } + m_render_target->bind(); + m_listener->onServiceInitialized(true); + while (true) + { + m_listener->onFrameAvailable(m_render_target->hardware_buffer()); + m_egl_context->swap(); + } + } +public: + Kernel(const std::shared_ptr& listener) : m_listener(listener) + { + m_main_loop_thread = std::thread(&Kernel::main_loop, this); + } +}; + +class NativeService : public BnMosisService +{ + std::unique_ptr m_kernel; public: NativeService() = default; ndk::ScopedAStatus getNumber(int32_t *_aidl_return) override @@ -15,15 +155,12 @@ public: *_aidl_return = 100; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus initOS(bool *_aidl_return) override { - if (!m_egl_context) + ndk::ScopedAStatus initOS(const std::shared_ptr& listener, + bool *_aidl_return) override + { + if (!m_kernel) { - m_egl_context = std::make_unique(); - *_aidl_return = m_egl_context->create(); - } - else - { - Logger::Log("OS already initialized"); + m_kernel = std::make_unique(listener); *_aidl_return = true; } return ndk::ScopedAStatus::ok(); @@ -32,7 +169,8 @@ public: extern "C" JNIEXPORT jobject JNICALL -Java_com_omixlab_mosis_NativeService_getBinderNative(JNIEnv *env, jobject thiz) { +Java_com_omixlab_mosis_NativeService_getBinderNative(JNIEnv *env, jobject thiz) +{ static std::shared_ptr g_service = ndk::SharedRefBase::make(); return AIBinder_toJavaBinder(env, g_service->asBinder().get()); } diff --git a/src/main/cpp/mosis-test.cpp b/src/main/cpp/mosis-test.cpp index 8774f5e..fbdda54 100644 --- a/src/main/cpp/mosis-test.cpp +++ b/src/main/cpp/mosis-test.cpp @@ -58,7 +58,9 @@ std::unique_ptr g_renderer; extern "C" JNIEXPORT void JNICALL -Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz, jobject binder) { +Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz, + jobject binder) +{ AIBinder* pBinder = AIBinder_fromJavaBinder(env, binder); const ndk::SpAIBinder spBinder(pBinder); g_service = IMosisService::fromBinder(spBinder); @@ -67,7 +69,9 @@ Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz, extern "C" JNIEXPORT void JNICALL -Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, jobject surface) { +Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, + jobject surface) +{ Logger::Log("setSurface"); if (!g_renderer) { @@ -77,7 +81,8 @@ Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, jobjec } extern "C" JNIEXPORT void JNICALL -Java_com_omixlab_mosis_MainActivity_destroySurface(JNIEnv *env, jobject thiz) { +Java_com_omixlab_mosis_MainActivity_destroySurface(JNIEnv *env, jobject thiz) +{ Logger::Log("destroySurface"); if (g_renderer) { diff --git a/src/main/java/com/omixlab/mosis/MainActivity.kt b/src/main/java/com/omixlab/mosis/MainActivity.kt index e7e1712..4e11c3c 100644 --- a/src/main/java/com/omixlab/mosis/MainActivity.kt +++ b/src/main/java/com/omixlab/mosis/MainActivity.kt @@ -10,7 +10,6 @@ import android.view.Surface import android.view.SurfaceView import android.view.SurfaceHolder import androidx.activity.ComponentActivity -import androidx.activity.addCallback import androidx.activity.enableEdgeToEdge import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Arrangement @@ -66,10 +65,20 @@ 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() + val result = service.initOS(listener) Log.d("MosisTest", "InitOS returned: $result") buttonText.value = if (result) "OS Initialized" else "OS Not Initialized" } diff --git a/src/main/java/com/omixlab/mosis/NativeService.kt b/src/main/java/com/omixlab/mosis/NativeService.kt index 1667c1a..a0be45e 100644 --- a/src/main/java/com/omixlab/mosis/NativeService.kt +++ b/src/main/java/com/omixlab/mosis/NativeService.kt @@ -5,8 +5,6 @@ import android.app.NotificationChannel import android.app.NotificationManager import android.app.Service import android.content.Intent -import android.os.Build -import android.os.Debug import android.os.IBinder import androidx.core.app.NotificationCompat diff --git a/src/main/res/layout/activity_main.xml b/src/main/res/layout/activity_main.xml deleted file mode 100644 index 9affce0..0000000 --- a/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml deleted file mode 100644 index 73862c4..0000000 --- a/src/main/res/values/strings.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file