Loading threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl +3 −4 Original line number Diff line number Diff line Loading @@ -36,10 +36,9 @@ package android.hardware.threadnetwork; interface IThreadChip { void open(in android.hardware.threadnetwork.IThreadChipCallback callback); void close(); void reset(); void hardwareReset(); void sendSpinelFrame(in byte[] frame); const int ERROR_FAILED = 1; const int ERROR_INVALID_ARGS = 2; const int ERROR_NO_BUFS = 3; const int ERROR_BUSY = 4; const int ERROR_NO_BUFS = 2; const int ERROR_BUSY = 3; } threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl +10 −11 Original line number Diff line number Diff line Loading @@ -29,20 +29,15 @@ interface IThreadChip { */ const int ERROR_FAILED = 1; /** * The invalid arguments. */ const int ERROR_INVALID_ARGS = 2; /** * Insufficient buffers available to send frames. */ const int ERROR_NO_BUFS = 3; const int ERROR_NO_BUFS = 2; /** * Service is busy and could not service the operation. */ const int ERROR_BUSY = 4; const int ERROR_BUSY = 3; /** * This method initializes the Thread HAL instance. If open completes Loading @@ -51,9 +46,10 @@ interface IThreadChip { * * @param callback A IThreadChipCallback callback instance. * * @throws EX_ILLEGAL_ARGUMENT if the callback handle is invalid (for example, it is null). * * @throws ServiceSpecificException with one of the following values: * - ERROR_FAILED The interface cannot be opened due to an internal error. * - ERROR_INVALID_ARGS The callback handle is invalid (for example, it is null). * - ERROR_BUSY This interface is in use. */ void open(in IThreadChipCallback callback); Loading @@ -64,11 +60,14 @@ interface IThreadChip { void close(); /** * This method resets the Thread HAL internal state. The callback registered by * `open()` won’t be reset and the resource allocated by `open()` won’t be free. * This method hardware resets the Thread radio chip via the physical reset pin. * The callback registered by `open()` won’t be reset and the resource allocated * by `open()` won’t be free. * * @throws EX_UNSUPPORTED_OPERATION if the Thread radio chip doesn't support the hardware reset. * */ void reset(); void hardwareReset(); /** * This method sends a spinel frame to the Thread HAL. Loading threadnetwork/aidl/default/thread_chip.cpp +88 −59 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include "thread_chip.hpp" #include <android-base/logging.h> #include <android/binder_auto_utils.h> #include <android/binder_ibinder.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <utils/Log.h> Loading Loading @@ -46,20 +48,36 @@ ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this, mRxFrameBuffer); } else { ALOGE("The protocol \"%s\" is not supported!", protocol); exit(1); ALOGE("The protocol \"%s\" is not supported", protocol); exit(EXIT_FAILURE); } CHECK_NE(mSpinelInterface, nullptr); mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(ThreadChip::onBinderDiedJump)); AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump); } ThreadChip::~ThreadChip() { AIBinder_DeathRecipient_delete(mDeathRecipient.get()); } void ThreadChip::onBinderDiedJump(void* context) { reinterpret_cast<ThreadChip*>(context)->onBinderDied(); } void ThreadChip::clientDeathCallback(void* context) { reinterpret_cast<ThreadChip*>(context)->clientDeathCallback(); void ThreadChip::onBinderDied(void) { ALOGW("Thread Network HAL client is dead"); } void ThreadChip::clientDeathCallback(void) { ALOGW("Thread Network HAL client is dead."); close(); void ThreadChip::onBinderUnlinkedJump(void* context) { reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked(); } void ThreadChip::onBinderUnlinked(void) { ALOGW("ThreadChip binder is unlinked"); deinitChip(); } void ThreadChip::handleReceivedFrameJump(void* context) { Loading @@ -76,62 +94,70 @@ void ThreadChip::handleReceivedFrame(void) { } ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) { ndk::ScopedAStatus status; AIBinder* binder; VerifyOrExit(mCallback == nullptr, status = errorStatus(ERROR_BUSY, "Interface is already opened")); VerifyOrExit(in_callback != nullptr, status = errorStatus(ERROR_INVALID_ARGS, "The callback is NULL")); binder = in_callback->asBinder().get(); VerifyOrExit(binder != nullptr, status = errorStatus(ERROR_FAILED, "Failed to get the callback binder")); mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback); VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK, status = errorStatus(ERROR_FAILED, "Failed to link the binder to death")); VerifyOrExit(mSpinelInterface->Init(mUrl) == OT_ERROR_NONE, status = errorStatus(ERROR_FAILED, "Failed to initialize the interface")); ndk::ScopedAStatus status = initChip(in_callback); if (status.isOk()) { AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this); ALOGI("Open IThreadChip successfully"); } else { ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str()); } return status; } ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr<IThreadChipCallback>& in_callback) { if (in_callback == nullptr) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } else if (mCallback == nullptr) { if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) { return errorStatus(ERROR_FAILED, "Failed to initialize the interface"); } mCallback = in_callback; ot::Posix::Mainloop::Manager::Get().Add(*this); status = ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok(); } else { return errorStatus(ERROR_BUSY, "Interface has been opened"); } } exit: if (!status.isOk()) { if (mBinderDeathRecipient != nullptr) { AIBinder_DeathRecipient_delete(mBinderDeathRecipient); mBinderDeathRecipient = nullptr; ndk::ScopedAStatus ThreadChip::close() { ndk::ScopedAStatus status; std::shared_ptr<IThreadChipCallback> callback = mCallback; status = deinitChip(); if (status.isOk()) { if (callback != nullptr) { AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this); } ALOGW("Open failed, error: %s", status.getDescription().c_str()); ALOGI("Close IThreadChip successfully"); } else { ALOGI("open()"); ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str()); } return status; } ndk::ScopedAStatus ThreadChip::close() { VerifyOrExit(mCallback != nullptr); mCallback = nullptr; ndk::ScopedAStatus ThreadChip::deinitChip() { if (mCallback != nullptr) { mSpinelInterface->Deinit(); ot::Posix::Mainloop::Manager::Get().Remove(*this); AIBinder_DeathRecipient_delete(mBinderDeathRecipient); mBinderDeathRecipient = nullptr; exit: ALOGI("close()"); mCallback = nullptr; return ndk::ScopedAStatus::ok(); } return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) { ndk::ScopedAStatus status; otError error; VerifyOrExit(mCallback != nullptr, status = errorStatus(ERROR_FAILED, "The interface is not open")); if (mCallback == nullptr) { status = errorStatus(ERROR_FAILED, "The interface is not open"); } else { error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()), in_frame.size()); if (error == OT_ERROR_NONE) { Loading @@ -143,8 +169,8 @@ ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_fr } else { status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame"); } } exit: if (!status.isOk()) { ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str()); } Loading @@ -152,8 +178,11 @@ exit: return status; } ndk::ScopedAStatus ThreadChip::reset() { mSpinelInterface->HardwareReset(); ndk::ScopedAStatus ThreadChip::hardwareReset() { if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } ALOGI("reset()"); return ndk::ScopedAStatus::ok(); } Loading threadnetwork/aidl/default/thread_chip.hpp +10 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "lib/spinel/spinel_interface.hpp" #include "mainloop.hpp" #include <android/binder_auto_utils.h> #include <android/binder_ibinder.h> #include <utils/Mutex.h> Loading @@ -33,26 +34,31 @@ namespace threadnetwork { class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source { public: ThreadChip(char* url); ~ThreadChip(); ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override; ndk::ScopedAStatus close() override; ndk::ScopedAStatus sendSpinelFrame(const std::vector<uint8_t>& in_frame) override; ndk::ScopedAStatus reset() override; ndk::ScopedAStatus hardwareReset() override; void Update(otSysMainloopContext& context) override; void Process(const otSysMainloopContext& context) override; private: static void clientDeathCallback(void* context); void clientDeathCallback(void); static void onBinderDiedJump(void* context); void onBinderDied(void); static void onBinderUnlinkedJump(void* context); void onBinderUnlinked(void); static void handleReceivedFrameJump(void* context); void handleReceivedFrame(void); ndk::ScopedAStatus errorStatus(int32_t error, const char* message); ndk::ScopedAStatus initChip(const std::shared_ptr<IThreadChipCallback>& in_callback); ndk::ScopedAStatus deinitChip(); ot::Url::Url mUrl; std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface; ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer; std::shared_ptr<IThreadChipCallback> mCallback; AIBinder_DeathRecipient* mBinderDeathRecipient; ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; }; } // namespace threadnetwork Loading threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ TEST_P(ThreadNetworkAidl, Reset) { ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {}); EXPECT_TRUE(thread_chip->open(callback).isOk()); EXPECT_TRUE(thread_chip->reset().isOk()); EXPECT_TRUE(thread_chip->hardwareReset().isOk()); } TEST_P(ThreadNetworkAidl, SendSpinelFrame) { Loading Loading
threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl +3 −4 Original line number Diff line number Diff line Loading @@ -36,10 +36,9 @@ package android.hardware.threadnetwork; interface IThreadChip { void open(in android.hardware.threadnetwork.IThreadChipCallback callback); void close(); void reset(); void hardwareReset(); void sendSpinelFrame(in byte[] frame); const int ERROR_FAILED = 1; const int ERROR_INVALID_ARGS = 2; const int ERROR_NO_BUFS = 3; const int ERROR_BUSY = 4; const int ERROR_NO_BUFS = 2; const int ERROR_BUSY = 3; }
threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl +10 −11 Original line number Diff line number Diff line Loading @@ -29,20 +29,15 @@ interface IThreadChip { */ const int ERROR_FAILED = 1; /** * The invalid arguments. */ const int ERROR_INVALID_ARGS = 2; /** * Insufficient buffers available to send frames. */ const int ERROR_NO_BUFS = 3; const int ERROR_NO_BUFS = 2; /** * Service is busy and could not service the operation. */ const int ERROR_BUSY = 4; const int ERROR_BUSY = 3; /** * This method initializes the Thread HAL instance. If open completes Loading @@ -51,9 +46,10 @@ interface IThreadChip { * * @param callback A IThreadChipCallback callback instance. * * @throws EX_ILLEGAL_ARGUMENT if the callback handle is invalid (for example, it is null). * * @throws ServiceSpecificException with one of the following values: * - ERROR_FAILED The interface cannot be opened due to an internal error. * - ERROR_INVALID_ARGS The callback handle is invalid (for example, it is null). * - ERROR_BUSY This interface is in use. */ void open(in IThreadChipCallback callback); Loading @@ -64,11 +60,14 @@ interface IThreadChip { void close(); /** * This method resets the Thread HAL internal state. The callback registered by * `open()` won’t be reset and the resource allocated by `open()` won’t be free. * This method hardware resets the Thread radio chip via the physical reset pin. * The callback registered by `open()` won’t be reset and the resource allocated * by `open()` won’t be free. * * @throws EX_UNSUPPORTED_OPERATION if the Thread radio chip doesn't support the hardware reset. * */ void reset(); void hardwareReset(); /** * This method sends a spinel frame to the Thread HAL. Loading
threadnetwork/aidl/default/thread_chip.cpp +88 −59 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include "thread_chip.hpp" #include <android-base/logging.h> #include <android/binder_auto_utils.h> #include <android/binder_ibinder.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <utils/Log.h> Loading Loading @@ -46,20 +48,36 @@ ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this, mRxFrameBuffer); } else { ALOGE("The protocol \"%s\" is not supported!", protocol); exit(1); ALOGE("The protocol \"%s\" is not supported", protocol); exit(EXIT_FAILURE); } CHECK_NE(mSpinelInterface, nullptr); mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(ThreadChip::onBinderDiedJump)); AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump); } ThreadChip::~ThreadChip() { AIBinder_DeathRecipient_delete(mDeathRecipient.get()); } void ThreadChip::onBinderDiedJump(void* context) { reinterpret_cast<ThreadChip*>(context)->onBinderDied(); } void ThreadChip::clientDeathCallback(void* context) { reinterpret_cast<ThreadChip*>(context)->clientDeathCallback(); void ThreadChip::onBinderDied(void) { ALOGW("Thread Network HAL client is dead"); } void ThreadChip::clientDeathCallback(void) { ALOGW("Thread Network HAL client is dead."); close(); void ThreadChip::onBinderUnlinkedJump(void* context) { reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked(); } void ThreadChip::onBinderUnlinked(void) { ALOGW("ThreadChip binder is unlinked"); deinitChip(); } void ThreadChip::handleReceivedFrameJump(void* context) { Loading @@ -76,62 +94,70 @@ void ThreadChip::handleReceivedFrame(void) { } ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) { ndk::ScopedAStatus status; AIBinder* binder; VerifyOrExit(mCallback == nullptr, status = errorStatus(ERROR_BUSY, "Interface is already opened")); VerifyOrExit(in_callback != nullptr, status = errorStatus(ERROR_INVALID_ARGS, "The callback is NULL")); binder = in_callback->asBinder().get(); VerifyOrExit(binder != nullptr, status = errorStatus(ERROR_FAILED, "Failed to get the callback binder")); mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback); VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK, status = errorStatus(ERROR_FAILED, "Failed to link the binder to death")); VerifyOrExit(mSpinelInterface->Init(mUrl) == OT_ERROR_NONE, status = errorStatus(ERROR_FAILED, "Failed to initialize the interface")); ndk::ScopedAStatus status = initChip(in_callback); if (status.isOk()) { AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this); ALOGI("Open IThreadChip successfully"); } else { ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str()); } return status; } ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr<IThreadChipCallback>& in_callback) { if (in_callback == nullptr) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } else if (mCallback == nullptr) { if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) { return errorStatus(ERROR_FAILED, "Failed to initialize the interface"); } mCallback = in_callback; ot::Posix::Mainloop::Manager::Get().Add(*this); status = ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok(); } else { return errorStatus(ERROR_BUSY, "Interface has been opened"); } } exit: if (!status.isOk()) { if (mBinderDeathRecipient != nullptr) { AIBinder_DeathRecipient_delete(mBinderDeathRecipient); mBinderDeathRecipient = nullptr; ndk::ScopedAStatus ThreadChip::close() { ndk::ScopedAStatus status; std::shared_ptr<IThreadChipCallback> callback = mCallback; status = deinitChip(); if (status.isOk()) { if (callback != nullptr) { AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this); } ALOGW("Open failed, error: %s", status.getDescription().c_str()); ALOGI("Close IThreadChip successfully"); } else { ALOGI("open()"); ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str()); } return status; } ndk::ScopedAStatus ThreadChip::close() { VerifyOrExit(mCallback != nullptr); mCallback = nullptr; ndk::ScopedAStatus ThreadChip::deinitChip() { if (mCallback != nullptr) { mSpinelInterface->Deinit(); ot::Posix::Mainloop::Manager::Get().Remove(*this); AIBinder_DeathRecipient_delete(mBinderDeathRecipient); mBinderDeathRecipient = nullptr; exit: ALOGI("close()"); mCallback = nullptr; return ndk::ScopedAStatus::ok(); } return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) { ndk::ScopedAStatus status; otError error; VerifyOrExit(mCallback != nullptr, status = errorStatus(ERROR_FAILED, "The interface is not open")); if (mCallback == nullptr) { status = errorStatus(ERROR_FAILED, "The interface is not open"); } else { error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()), in_frame.size()); if (error == OT_ERROR_NONE) { Loading @@ -143,8 +169,8 @@ ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_fr } else { status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame"); } } exit: if (!status.isOk()) { ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str()); } Loading @@ -152,8 +178,11 @@ exit: return status; } ndk::ScopedAStatus ThreadChip::reset() { mSpinelInterface->HardwareReset(); ndk::ScopedAStatus ThreadChip::hardwareReset() { if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } ALOGI("reset()"); return ndk::ScopedAStatus::ok(); } Loading
threadnetwork/aidl/default/thread_chip.hpp +10 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "lib/spinel/spinel_interface.hpp" #include "mainloop.hpp" #include <android/binder_auto_utils.h> #include <android/binder_ibinder.h> #include <utils/Mutex.h> Loading @@ -33,26 +34,31 @@ namespace threadnetwork { class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source { public: ThreadChip(char* url); ~ThreadChip(); ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override; ndk::ScopedAStatus close() override; ndk::ScopedAStatus sendSpinelFrame(const std::vector<uint8_t>& in_frame) override; ndk::ScopedAStatus reset() override; ndk::ScopedAStatus hardwareReset() override; void Update(otSysMainloopContext& context) override; void Process(const otSysMainloopContext& context) override; private: static void clientDeathCallback(void* context); void clientDeathCallback(void); static void onBinderDiedJump(void* context); void onBinderDied(void); static void onBinderUnlinkedJump(void* context); void onBinderUnlinked(void); static void handleReceivedFrameJump(void* context); void handleReceivedFrame(void); ndk::ScopedAStatus errorStatus(int32_t error, const char* message); ndk::ScopedAStatus initChip(const std::shared_ptr<IThreadChipCallback>& in_callback); ndk::ScopedAStatus deinitChip(); ot::Url::Url mUrl; std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface; ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer; std::shared_ptr<IThreadChipCallback> mCallback; AIBinder_DeathRecipient* mBinderDeathRecipient; ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; }; } // namespace threadnetwork Loading
threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ TEST_P(ThreadNetworkAidl, Reset) { ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {}); EXPECT_TRUE(thread_chip->open(callback).isOk()); EXPECT_TRUE(thread_chip->reset().isOk()); EXPECT_TRUE(thread_chip->hardwareReset().isOk()); } TEST_P(ThreadNetworkAidl, SendSpinelFrame) { Loading