From a6165dcccf0096f8363b4b64b0f5332267eea330 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Thu, 6 Jul 2023 18:09:22 +0800 Subject: [PATCH] change the Thread Network HAL api from 'reset' to 'hardwareReset' This CL changes the API from 'reset' to 'hardwareReset' to make the the definition of the API clearer. This CL also optimizes the Thread Network HAL default implementation. Bug: 289867661 Test: Run Thread stack on cuttlefish. Change-Id: Id742453d9d7a0d369ac8f16905efdacfcfba1dbc --- .../hardware/threadnetwork/IThreadChip.aidl | 7 +- .../hardware/threadnetwork/IThreadChip.aidl | 21 ++- threadnetwork/aidl/default/thread_chip.cpp | 145 +++++++++++------- threadnetwork/aidl/default/thread_chip.hpp | 14 +- .../vts/VtsHalThreadNetworkTargetTest.cpp | 2 +- 5 files changed, 111 insertions(+), 78 deletions(-) diff --git a/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl index e4d4cbe788..607ceb398d 100644 --- a/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl +++ b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl @@ -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; } diff --git a/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl index eebaa46983..e695623286 100644 --- a/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl +++ b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl @@ -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 @@ -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); @@ -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. diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp index 94d1e93cbe..3d38cb841b 100644 --- a/threadnetwork/aidl/default/thread_chip.cpp +++ b/threadnetwork/aidl/default/thread_chip.cpp @@ -17,6 +17,8 @@ #include "thread_chip.hpp" #include +#include +#include #include #include #include @@ -46,20 +48,36 @@ ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) mSpinelInterface = std::make_shared(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); } -void ThreadChip::clientDeathCallback(void* context) { - reinterpret_cast(context)->clientDeathCallback(); +ThreadChip::~ThreadChip() { + AIBinder_DeathRecipient_delete(mDeathRecipient.get()); } -void ThreadChip::clientDeathCallback(void) { - ALOGW("Thread Network HAL client is dead."); - close(); +void ThreadChip::onBinderDiedJump(void* context) { + reinterpret_cast(context)->onBinderDied(); +} + +void ThreadChip::onBinderDied(void) { + ALOGW("Thread Network HAL client is dead"); +} + +void ThreadChip::onBinderUnlinkedJump(void* context) { + reinterpret_cast(context)->onBinderUnlinked(); +} + +void ThreadChip::onBinderUnlinked(void) { + ALOGW("ThreadChip binder is unlinked"); + deinitChip(); } void ThreadChip::handleReceivedFrameJump(void* context) { @@ -76,75 +94,83 @@ void ThreadChip::handleReceivedFrame(void) { } ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr& in_callback) { - ndk::ScopedAStatus status; - AIBinder* binder; + ndk::ScopedAStatus status = initChip(in_callback); - 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")); - - mCallback = in_callback; - ot::Posix::Mainloop::Manager::Get().Add(*this); - status = ndk::ScopedAStatus::ok(); - -exit: - if (!status.isOk()) { - if (mBinderDeathRecipient != nullptr) { - AIBinder_DeathRecipient_delete(mBinderDeathRecipient); - mBinderDeathRecipient = nullptr; - } - ALOGW("Open failed, error: %s", status.getDescription().c_str()); + if (status.isOk()) { + AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this); + ALOGI("Open IThreadChip successfully"); } else { - ALOGI("open()"); + ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str()); } return status; } +ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr& 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); + return ndk::ScopedAStatus::ok(); + } else { + return errorStatus(ERROR_BUSY, "Interface has been opened"); + } +} + ndk::ScopedAStatus ThreadChip::close() { - VerifyOrExit(mCallback != nullptr); - mCallback = nullptr; - mSpinelInterface->Deinit(); + ndk::ScopedAStatus status; + std::shared_ptr callback = mCallback; - ot::Posix::Mainloop::Manager::Get().Remove(*this); + status = deinitChip(); + if (status.isOk()) { + if (callback != nullptr) { + AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this); + } - AIBinder_DeathRecipient_delete(mBinderDeathRecipient); - mBinderDeathRecipient = nullptr; + ALOGI("Close IThreadChip successfully"); + } else { + ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str()); + } -exit: - ALOGI("close()"); - return ndk::ScopedAStatus::ok(); + return status; +} + +ndk::ScopedAStatus ThreadChip::deinitChip() { + if (mCallback != nullptr) { + mSpinelInterface->Deinit(); + ot::Posix::Mainloop::Manager::Get().Remove(*this); + mCallback = nullptr; + return ndk::ScopedAStatus::ok(); + } + + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector& in_frame) { ndk::ScopedAStatus status; otError error; - VerifyOrExit(mCallback != nullptr, - status = errorStatus(ERROR_FAILED, "The interface is not open")); - - error = mSpinelInterface->SendFrame(reinterpret_cast(in_frame.data()), - in_frame.size()); - if (error == OT_ERROR_NONE) { - status = ndk::ScopedAStatus::ok(); - } else if (error == OT_ERROR_NO_BUFS) { - status = errorStatus(ERROR_NO_BUFS, "Insufficient buffer space to send"); - } else if (error == OT_ERROR_BUSY) { - status = errorStatus(ERROR_BUSY, "The interface is busy"); + if (mCallback == nullptr) { + status = errorStatus(ERROR_FAILED, "The interface is not open"); } else { - status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame"); + error = mSpinelInterface->SendFrame(reinterpret_cast(in_frame.data()), + in_frame.size()); + if (error == OT_ERROR_NONE) { + status = ndk::ScopedAStatus::ok(); + } else if (error == OT_ERROR_NO_BUFS) { + status = errorStatus(ERROR_NO_BUFS, "Insufficient buffer space to send"); + } else if (error == OT_ERROR_BUSY) { + status = errorStatus(ERROR_BUSY, "The interface is busy"); + } 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()); } @@ -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(); } diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp index 294190a658..1ab6d544d1 100644 --- a/threadnetwork/aidl/default/thread_chip.hpp +++ b/threadnetwork/aidl/default/thread_chip.hpp @@ -22,6 +22,7 @@ #include "lib/spinel/spinel_interface.hpp" #include "mainloop.hpp" +#include #include #include @@ -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& in_callback) override; ndk::ScopedAStatus close() override; ndk::ScopedAStatus sendSpinelFrame(const std::vector& 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& in_callback); + ndk::ScopedAStatus deinitChip(); ot::Url::Url mUrl; std::shared_ptr mSpinelInterface; ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer; std::shared_ptr mCallback; - AIBinder_DeathRecipient* mBinderDeathRecipient; + ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; }; } // namespace threadnetwork diff --git a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp index 04c6deaf2a..5925b54b6a 100644 --- a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp +++ b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp @@ -91,7 +91,7 @@ TEST_P(ThreadNetworkAidl, Reset) { ndk::SharedRefBase::make([](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) {