Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bed5323f authored by Zhanglong Xia's avatar Zhanglong Xia Committed by Kangping Dong
Browse files

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.
(cherry picked from https://android-review.googlesource.com/q/commit:a6165dcccf0096f8363b4b64b0f5332267eea330)
Merged-In: Id742453d9d7a0d369ac8f16905efdacfcfba1dbc
Change-Id: Id742453d9d7a0d369ac8f16905efdacfcfba1dbc
parent 3bbcbcdc
Loading
Loading
Loading
Loading
+3 −4
Original line number Original line Diff line number Diff line
@@ -36,10 +36,9 @@ package android.hardware.threadnetwork;
interface IThreadChip {
interface IThreadChip {
  void open(in android.hardware.threadnetwork.IThreadChipCallback callback);
  void open(in android.hardware.threadnetwork.IThreadChipCallback callback);
  void close();
  void close();
  void reset();
  void hardwareReset();
  void sendSpinelFrame(in byte[] frame);
  void sendSpinelFrame(in byte[] frame);
  const int ERROR_FAILED = 1;
  const int ERROR_FAILED = 1;
  const int ERROR_INVALID_ARGS = 2;
  const int ERROR_NO_BUFS = 2;
  const int ERROR_NO_BUFS = 3;
  const int ERROR_BUSY = 3;
  const int ERROR_BUSY = 4;
}
}
+10 −11
Original line number Original line Diff line number Diff line
@@ -29,20 +29,15 @@ interface IThreadChip {
     */
     */
    const int ERROR_FAILED = 1;
    const int ERROR_FAILED = 1;


    /**
     * The invalid arguments.
     */
    const int ERROR_INVALID_ARGS = 2;

    /**
    /**
     * Insufficient buffers available to send frames.
     * 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.
     * 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
     * This method initializes the Thread HAL instance. If open completes
@@ -51,9 +46,10 @@ interface IThreadChip {
     *
     *
     * @param callback  A IThreadChipCallback callback instance.
     * @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:
     * @throws ServiceSpecificException with one of the following values:
     *     - ERROR_FAILED        The interface cannot be opened due to an internal error.
     *     - 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.
     *     - ERROR_BUSY          This interface is in use.
     */
     */
    void open(in IThreadChipCallback callback);
    void open(in IThreadChipCallback callback);
@@ -64,11 +60,14 @@ interface IThreadChip {
    void close();
    void close();


    /**
    /**
     * This method resets the Thread HAL internal state. The callback registered by
     * This method hardware resets the Thread radio chip via the physical reset pin.
     * `open()` won’t be reset and the resource allocated by `open()` won’t be free.
     * 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.
     * This method sends a spinel frame to the Thread HAL.
+88 −59
Original line number Original line Diff line number Diff line
@@ -17,6 +17,8 @@
#include "thread_chip.hpp"
#include "thread_chip.hpp"


#include <android-base/logging.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/binder_process.h>
#include <utils/Log.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,
        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
                                                                      mRxFrameBuffer);
                                                                      mRxFrameBuffer);
    } else {
    } else {
        ALOGE("The protocol \"%s\" is not supported!", protocol);
        ALOGE("The protocol \"%s\" is not supported", protocol);
        exit(1);
        exit(EXIT_FAILURE);
    }
    }


    CHECK_NE(mSpinelInterface, nullptr);
    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) {
void ThreadChip::onBinderDied(void) {
    reinterpret_cast<ThreadChip*>(context)->clientDeathCallback();
    ALOGW("Thread Network HAL client is dead");
}
}


void ThreadChip::clientDeathCallback(void) {
void ThreadChip::onBinderUnlinkedJump(void* context) {
    ALOGW("Thread Network HAL client is dead.");
    reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked();
    close();
}

void ThreadChip::onBinderUnlinked(void) {
    ALOGW("ThreadChip binder is unlinked");
    deinitChip();
}
}


void ThreadChip::handleReceivedFrameJump(void* context) {
void ThreadChip::handleReceivedFrameJump(void* context) {
@@ -76,62 +94,70 @@ void ThreadChip::handleReceivedFrame(void) {
}
}


ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) {
ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) {
    ndk::ScopedAStatus status;
    ndk::ScopedAStatus status = initChip(in_callback);
    AIBinder* binder;


    if (status.isOk()) {
    VerifyOrExit(mCallback == nullptr,
        AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this);
                 status = errorStatus(ERROR_BUSY, "Interface is already opened"));
        ALOGI("Open IThreadChip successfully");
    VerifyOrExit(in_callback != nullptr,
    } else {
                 status = errorStatus(ERROR_INVALID_ARGS, "The callback is NULL"));
        ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str());
    binder = in_callback->asBinder().get();
    }
    VerifyOrExit(binder != nullptr,

                 status = errorStatus(ERROR_FAILED, "Failed to get the callback binder"));
    return status;
    mBinderDeathRecipient = AIBinder_DeathRecipient_new(clientDeathCallback);
}
    VerifyOrExit(AIBinder_linkToDeath(binder, mBinderDeathRecipient, this) == STATUS_OK,

                 status = errorStatus(ERROR_FAILED, "Failed to link the binder to death"));
ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr<IThreadChipCallback>& in_callback) {
    VerifyOrExit(mSpinelInterface->Init(mUrl) == OT_ERROR_NONE,
    if (in_callback == nullptr) {
                 status = errorStatus(ERROR_FAILED, "Failed to initialize the interface"));
        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;
        mCallback = in_callback;
        ot::Posix::Mainloop::Manager::Get().Add(*this);
        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:
ndk::ScopedAStatus ThreadChip::close() {
    if (!status.isOk()) {
    ndk::ScopedAStatus status;
        if (mBinderDeathRecipient != nullptr) {
    std::shared_ptr<IThreadChipCallback> callback = mCallback;
            AIBinder_DeathRecipient_delete(mBinderDeathRecipient);

            mBinderDeathRecipient = nullptr;
    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 {
    } else {
        ALOGI("open()");
        ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str());
    }
    }


    return status;
    return status;
}
}


ndk::ScopedAStatus ThreadChip::close() {
ndk::ScopedAStatus ThreadChip::deinitChip() {
    VerifyOrExit(mCallback != nullptr);
    if (mCallback != nullptr) {
    mCallback = nullptr;
        mSpinelInterface->Deinit();
        mSpinelInterface->Deinit();

        ot::Posix::Mainloop::Manager::Get().Remove(*this);
        ot::Posix::Mainloop::Manager::Get().Remove(*this);

        mCallback = nullptr;
    AIBinder_DeathRecipient_delete(mBinderDeathRecipient);
    mBinderDeathRecipient = nullptr;

exit:
    ALOGI("close()");
        return ndk::ScopedAStatus::ok();
        return ndk::ScopedAStatus::ok();
    }
    }


    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}

ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) {
ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) {
    ndk::ScopedAStatus status;
    ndk::ScopedAStatus status;
    otError error;
    otError error;


    VerifyOrExit(mCallback != nullptr,
    if (mCallback == nullptr) {
                 status = errorStatus(ERROR_FAILED, "The interface is not open"));
        status = errorStatus(ERROR_FAILED, "The interface is not open");

    } else {
        error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
        error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
                                            in_frame.size());
                                            in_frame.size());
        if (error == OT_ERROR_NONE) {
        if (error == OT_ERROR_NONE) {
@@ -143,8 +169,8 @@ ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_fr
        } else {
        } else {
            status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame");
            status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame");
        }
        }
    }


exit:
    if (!status.isOk()) {
    if (!status.isOk()) {
        ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str());
        ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str());
    }
    }
@@ -152,8 +178,11 @@ exit:
    return status;
    return status;
}
}


ndk::ScopedAStatus ThreadChip::reset() {
ndk::ScopedAStatus ThreadChip::hardwareReset() {
    mSpinelInterface->HardwareReset();
    if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) {
        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
    }

    ALOGI("reset()");
    ALOGI("reset()");
    return ndk::ScopedAStatus::ok();
    return ndk::ScopedAStatus::ok();
}
}
+10 −4
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include "lib/spinel/spinel_interface.hpp"
#include "lib/spinel/spinel_interface.hpp"
#include "mainloop.hpp"
#include "mainloop.hpp"


#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
#include <android/binder_ibinder.h>
#include <utils/Mutex.h>
#include <utils/Mutex.h>


@@ -33,26 +34,31 @@ namespace threadnetwork {
class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
  public:
  public:
    ThreadChip(char* url);
    ThreadChip(char* url);
    ~ThreadChip();


    ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
    ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
    ndk::ScopedAStatus close() override;
    ndk::ScopedAStatus close() override;
    ndk::ScopedAStatus sendSpinelFrame(const std::vector<uint8_t>& in_frame) 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 Update(otSysMainloopContext& context) override;
    void Process(const otSysMainloopContext& context) override;
    void Process(const otSysMainloopContext& context) override;


  private:
  private:
    static void clientDeathCallback(void* context);
    static void onBinderDiedJump(void* context);
    void clientDeathCallback(void);
    void onBinderDied(void);
    static void onBinderUnlinkedJump(void* context);
    void onBinderUnlinked(void);
    static void handleReceivedFrameJump(void* context);
    static void handleReceivedFrameJump(void* context);
    void handleReceivedFrame(void);
    void handleReceivedFrame(void);
    ndk::ScopedAStatus errorStatus(int32_t error, const char* message);
    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;
    ot::Url::Url mUrl;
    std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface;
    std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface;
    ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
    ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
    std::shared_ptr<IThreadChipCallback> mCallback;
    std::shared_ptr<IThreadChipCallback> mCallback;
    AIBinder_DeathRecipient* mBinderDeathRecipient;
    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
};
};


}  // namespace threadnetwork
}  // namespace threadnetwork
+1 −1
Original line number Original line Diff line number Diff line
@@ -91,7 +91,7 @@ TEST_P(ThreadNetworkAidl, Reset) {
            ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
            ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});


    EXPECT_TRUE(thread_chip->open(callback).isOk());
    EXPECT_TRUE(thread_chip->open(callback).isOk());
    EXPECT_TRUE(thread_chip->reset().isOk());
    EXPECT_TRUE(thread_chip->hardwareReset().isOk());
}
}


TEST_P(ThreadNetworkAidl, SendSpinelFrame) {
TEST_P(ThreadNetworkAidl, SendSpinelFrame) {