Merge "BluetoothAudio: Statically link HAL dependencies" into main
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 e4d4cbe..607ceb3 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 @@
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 eebaa46..e695623 100644
--- a/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
+++ b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
@@ -30,19 +30,14 @@
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 @@
*
* @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 @@
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/Android.bp b/threadnetwork/aidl/default/Android.bp
index 8b938d2..bcd5704 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -79,7 +79,6 @@
"fuzzer.cpp",
],
- required: ["ot-rcp"],
fuzz_config: {
cc: [
"zhanglongxia@google.com",
diff --git a/threadnetwork/aidl/default/fuzzer.cpp b/threadnetwork/aidl/default/fuzzer.cpp
index 512708d..fb6e548 100644
--- a/threadnetwork/aidl/default/fuzzer.cpp
+++ b/threadnetwork/aidl/default/fuzzer.cpp
@@ -22,7 +22,7 @@
using android::fuzzService;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- char url[] = "spinel+hdlc+forkpty:///vendor/bin/ot-rcp?forkpty-arg=2";
+ char url[] = "spinel+hdlc+null:///dev/null";
auto service = ndk::SharedRefBase::make<ThreadChip>(url);
fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index 94d1e93..3d38cb8 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -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 @@
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 @@
}
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 @@
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 294190a..1ab6d54 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 <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
#include <utils/Mutex.h>
@@ -33,26 +34,31 @@
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
diff --git a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
index 04c6dea..5925b54 100644
--- a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
+++ b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
@@ -91,7 +91,7 @@
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) {