mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge "change the Thread Network HAL api from 'reset' to 'hardwareReset'" into main am: 086e138474 am: 715b1abf5b am: 39d9ddb327
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2649860 Change-Id: I32482790baea4aa13c993f1201d98572e58cc222 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
void ThreadChip::clientDeathCallback(void* context) {
|
||||
reinterpret_cast<ThreadChip*>(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<ThreadChip*>(context)->onBinderDied();
|
||||
}
|
||||
|
||||
void ThreadChip::onBinderDied(void) {
|
||||
ALOGW("Thread Network HAL client is dead");
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -76,75 +94,83 @@ void ThreadChip::handleReceivedFrame(void) {
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& 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<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);
|
||||
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<IThreadChipCallback> 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<uint8_t>& in_frame) {
|
||||
ndk::ScopedAStatus status;
|
||||
otError error;
|
||||
|
||||
VerifyOrExit(mCallback != nullptr,
|
||||
status = errorStatus(ERROR_FAILED, "The interface is not open"));
|
||||
|
||||
error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(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<const uint8_t*>(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();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user