Snap for 9608188 from 9d31b5ced11684e6b89a70461e2cd67cb12c1a36 to udc-d1-release

Change-Id: I73673e1b3a0a15062e06b3a437997e52b6227259
diff --git a/Android.bp b/Android.bp
index 8bc8aad..93f283d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -109,7 +109,7 @@
 
 soong_config_string_variable {
     name: "rcp_bus",
-    values: ["spi", "uart"],
+    values: ["spi", "uart", "hal"],
 }
 
 ot_config_cc_defaults {
@@ -122,10 +122,9 @@
             spi: {
                 cflags: ["-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_SPI"]
             },
-            uart: {
+            hal: {
                 cflags: [
-                    "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART",
-                    "-DOPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE=1",
+                    "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_VENDOR",
                 ]
             },
             conditions_default: {
@@ -146,6 +145,7 @@
     local_include_dirs: [
         "include",
         "src",
+        "src/android/thread_network_hal",
         "src/cli",
         "src/core",
         "src/ncp",
@@ -173,6 +173,8 @@
     ],
 
     srcs: [
+        "src/android/thread_network_hal/hal_interface.cpp",
+        "src/android/thread_network_hal/vendor_interface.cpp",
         "src/core/api/backbone_router_api.cpp",
         "src/core/api/backbone_router_ftd_api.cpp",
         "src/core/api/border_agent_api.cpp",
@@ -556,6 +558,7 @@
         "src/cli",
         "src/core",
         "src/ncp",
+        "src/lib/hdlc",
         "third_party",
         "third_party/mbedtls",
         "third_party/mbedtls/repo/include",
@@ -586,6 +589,7 @@
 
 cc_library_static {
     name: "openthread-simulation",
+    vendor: true,
 
     defaults: [
         "ot_rcp_cflags_defaults",
@@ -606,13 +610,10 @@
         "examples/platforms/simulation/system.c",
         "examples/platforms/simulation/trel.c",
         "examples/platforms/simulation/uart.c",
-
         "examples/platforms/utils/link_metrics.cpp",
         "examples/platforms/utils/mac_frame.cpp",
         "examples/platforms/utils/soft_source_match_table.c",
-
         "src/lib/platform/exit_code.c",
-
         "third_party/mbedtls/repo/library/aes.c",
         "third_party/mbedtls/repo/library/asn1parse.c",
         "third_party/mbedtls/repo/library/asn1write.c",
@@ -643,6 +644,7 @@
 
 cc_library_static {
     name: "openthread-radio",
+    vendor: true,
 
     defaults: [
         "ot_rcp_cflags_defaults",
@@ -650,6 +652,9 @@
     ],
 
     generated_headers: ["ot_version_header"],
+    shared_libs: [
+        "libcutils",
+    ],
 
     srcs: [
         "src/core/api/diags_api.cpp",
@@ -688,23 +693,71 @@
 
 cc_library_static {
     name: "openthread-hdlc",
+    vendor: true,
     defaults: [
         "ot_rcp_cflags_defaults",
         "ot_simulation_cflags_defaults",
     ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
     srcs: [
         "src/lib/hdlc/hdlc.cpp",
     ],
 }
 
 cc_library_static {
+    name: "openthread-url",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/url",
+    ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    srcs: [
+        "src/lib/url/url.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-platform",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/platform",
+    ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    srcs: [
+        "src/lib/platform/exit_code.c",
+    ],
+}
+
+
+cc_library_static {
     name: "openthread-spinel-rcp",
+    vendor: true,
 
     defaults: [
         "ot_rcp_cflags_defaults",
         "ot_simulation_cflags_defaults",
     ],
 
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+
     srcs: [
         "src/lib/spinel/spinel.c",
         "src/lib/spinel/spinel_buffer.cpp",
@@ -715,6 +768,7 @@
 
 cc_library_static {
     name: "openthread-rcp",
+    vendor: true,
 
     defaults: [
         "ot_rcp_cflags_defaults",
@@ -733,7 +787,7 @@
 
 cc_binary {
     name: "ot-rcp",
-
+    vendor: true,
     defaults: [
         "ot_rcp_cflags_defaults",
         "ot_simulation_cflags_defaults",
@@ -760,3 +814,56 @@
     ],
 }
 
+cc_library_static {
+    name: "openthread-posix",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/platform",
+        "src/posix/platform",
+        "src/posix/platform/include",
+    ],
+    export_include_dirs: [
+        "include",
+        "src/core",
+        "src/posix/platform",
+        "src/posix/platform/include",
+    ],
+
+    cflags: [
+        "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART",
+        "-DOPENTHREAD_OSIX_CONFIG_RCP_PTY_ENABLE=1",
+    ],
+
+    cppflags: [
+        "-Wno-non-virtual-dtor",
+    ],
+
+    srcs: [
+        "src/posix/platform/alarm.cpp",
+        "src/posix/platform/mainloop.cpp",
+        "src/posix/platform/hdlc_interface.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-common",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+    ],
+
+    export_include_dirs: [
+        "include",
+        "src/core",
+    ],
+
+    srcs: [
+        "src/core/common/error.cpp",
+        "src/core/api/error_api.cpp",
+    ],
+}
diff --git a/src/android/thread_network_hal/hal_interface.cpp b/src/android/thread_network_hal/hal_interface.cpp
new file mode 100644
index 0000000..25d6292
--- /dev/null
+++ b/src/android/thread_network_hal/hal_interface.cpp
@@ -0,0 +1,290 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the copyright holder nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *   This file includes the implementation for the IPC Binder interface to radio Co-Processor (RCP).
+ */
+
+#include "hal_interface.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <linux/gpio.h>
+#include <linux/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <sys/select.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+namespace ot {
+namespace Posix {
+using ::aidl::android::hardware::threadnetwork::IThreadChip;
+using ::aidl::android::hardware::threadnetwork::IThreadChipCallback;
+using ::ndk::ScopedAStatus;
+
+using ot::Spinel::SpinelInterface;
+
+HalInterface::HalInterface(SpinelInterface::ReceiveFrameCallback aCallback,
+                           void *                                aCallbackContext,
+                           SpinelInterface::RxFrameBuffer &      aFrameBuffer)
+    : mRxFrameCallback(aCallback)
+    , mRxFrameContext(aCallbackContext)
+    , mRxFrameBuffer(aFrameBuffer)
+    , mThreadChip(nullptr)
+    , mThreadChipCallback(nullptr)
+    , mDeathRecipient(AIBinder_DeathRecipient_new(BinderDeathCallback))
+    , mBinderFd(-1)
+{
+    OT_ASSERT(mRxFrameCallback != nullptr);
+}
+
+otError HalInterface::Init(const Url::Url &aRadioUrl)
+{
+    static const std::string            kServicePrefix = std::string() + IThreadChip::descriptor + "/chip";
+    uint32_t                            id             = 0;
+    const char *                        value;
+    binder_status_t                     binderStatus;
+    ScopedAStatus                       ndkStatus;
+    std::shared_ptr<ThreadChipCallback> callback;
+    std::string                         serviceName;
+
+    binderStatus = ABinderProcess_setupPolling(&mBinderFd);
+    VerifyOrDie(binderStatus == ::STATUS_OK, OT_EXIT_FAILURE);
+    VerifyOrDie(mBinderFd >= 0, OT_EXIT_FAILURE);
+
+    if ((value = aRadioUrl.GetValue("id")) != nullptr)
+    {
+        id = static_cast<uint32_t>(atoi(value));
+    }
+
+    serviceName = kServicePrefix + std::to_string(id);
+    otLogInfoPlat("[HAL] Wait for getting the service %s ...", serviceName.c_str());
+    mThreadChip = IThreadChip::fromBinder(::ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+    VerifyOrDie(mThreadChip != nullptr, OT_EXIT_FAILURE);
+
+    callback = ndk::SharedRefBase::make<ThreadChipCallback>(this);
+    VerifyOrDie(callback->asBinder().get() != nullptr, OT_EXIT_FAILURE);
+
+    mThreadChipCallback = IThreadChipCallback::fromBinder(callback->asBinder());
+    VerifyOrDie(mThreadChipCallback != nullptr, OT_EXIT_FAILURE);
+
+    VerifyOrDie(AIBinder_linkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this) == STATUS_OK,
+                OT_EXIT_FAILURE);
+
+    ndkStatus = mThreadChip->open(mThreadChipCallback);
+    if (!ndkStatus.isOk())
+    {
+        otLogCritPlat("[HAL] Open the HAL interface failed: %s", ndkStatus.getMessage());
+        DieNow(OT_EXIT_FAILURE);
+    }
+
+    otLogInfoPlat("[HAL] Successfully got the service %s", serviceName.c_str());
+
+    return OT_ERROR_NONE;
+}
+
+void HalInterface::BinderDeathCallback(void *aContext)
+{
+    OT_UNUSED_VARIABLE(aContext);
+
+    otLogInfoPlat("[HAL] Thread network HAL is dead, exit!");
+    DieNow(OT_EXIT_FAILURE);
+}
+
+HalInterface::~HalInterface(void)
+{
+    Deinit();
+}
+
+void HalInterface::Deinit(void)
+{
+    if (mThreadChip != nullptr)
+    {
+        mThreadChip->close();
+        AIBinder_unlinkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this);
+        mThreadChip         = nullptr;
+        mThreadChipCallback = nullptr;
+    }
+
+    if (mBinderFd >= 0)
+    {
+        close(mBinderFd);
+    }
+}
+
+uint32_t HalInterface::GetBusSpeed(void) const
+{
+    static const uint32_t kBusSpeed = 1000000;
+    return kBusSpeed;
+}
+
+void HalInterface::OnRcpReset(void)
+{
+    mThreadChip->reset();
+}
+
+void HalInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
+{
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+    OT_UNUSED_VARIABLE(aTimeout);
+
+    if (mBinderFd >= 0)
+    {
+        FD_SET(mBinderFd, &aReadFdSet);
+        aMaxFd = std::max(aMaxFd, mBinderFd);
+    }
+}
+
+void HalInterface::Process(const RadioProcessContext &aContext)
+{
+    if ((mBinderFd >= 0) && FD_ISSET(mBinderFd, aContext.mReadFdSet))
+    {
+        ABinderProcess_handlePolledCommands();
+    }
+}
+
+otError HalInterface::WaitForFrame(uint64_t aTimeoutUs)
+{
+    otError        error = OT_ERROR_NONE;
+    struct timeval timeout;
+    fd_set         readFdSet;
+    int            ret;
+
+    VerifyOrExit(mBinderFd >= 0, error = OT_ERROR_FAILED);
+
+    timeout.tv_sec  = static_cast<time_t>(aTimeoutUs / US_PER_S);
+    timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % US_PER_S);
+
+    FD_ZERO(&readFdSet);
+    FD_SET(mBinderFd, &readFdSet);
+
+    ret = select(mBinderFd + 1, &readFdSet, nullptr, nullptr, &timeout);
+
+    if ((ret > 0) && FD_ISSET(mBinderFd, &readFdSet))
+    {
+        ABinderProcess_handlePolledCommands();
+    }
+    else if (ret == 0)
+    {
+        ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
+    }
+    else if (errno != EINTR)
+    {
+        DieNow(OT_EXIT_ERROR_ERRNO);
+    }
+
+exit:
+
+    if (error != OT_ERROR_NONE)
+    {
+        otLogWarnPlat("[HAL] Wait for frame failed: %s", otThreadErrorToString(error));
+    }
+
+    return error;
+}
+
+otError HalInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength)
+{
+    otError       error = OT_ERROR_NONE;
+    ScopedAStatus status;
+
+    VerifyOrExit((aFrame != nullptr) && (aLength <= kMaxFrameSize), error = OT_ERROR_INVALID_ARGS);
+    status = mThreadChip->sendSpinelFrame(std::vector<uint8_t>(aFrame, aFrame + aLength));
+    VerifyOrExit(!status.isOk(), error = OT_ERROR_NONE);
+    error = StatusToError(status);
+    otLogWarnPlat("[HAL] Send frame to HAL interface failed: %s", otThreadErrorToString(error));
+
+exit:
+    return error;
+}
+
+void HalInterface::ReceiveFrameCallback(const std::vector<uint8_t> &aFrame)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFrame.size() > 0, error = OT_ERROR_FAILED);
+
+    for (uint32_t i = 0; i < aFrame.size(); i++)
+    {
+        if ((error = mRxFrameBuffer.WriteByte(aFrame[i])) != OT_ERROR_NONE)
+        {
+            otLogNotePlat("[HAL] Drop the received spinel frame: %s", otThreadErrorToString(error));
+            mRxFrameBuffer.DiscardFrame();
+            ExitNow();
+        }
+    }
+
+    mRxFrameCallback(mRxFrameContext);
+
+exit:
+    return;
+}
+
+otError HalInterface::StatusToError(ScopedAStatus &aStatus)
+{
+    otError error = OT_ERROR_FAILED;
+
+    VerifyOrExit(!aStatus.isOk(), error = OT_ERROR_NONE);
+
+    if (aStatus.getExceptionCode() == EX_ILLEGAL_STATE)
+    {
+        error = OT_ERROR_INVALID_STATE;
+    }
+    else if (aStatus.getExceptionCode() == EX_ILLEGAL_ARGUMENT)
+    {
+        error = OT_ERROR_INVALID_ARGS;
+    }
+    else if (aStatus.getExceptionCode() == EX_SERVICE_SPECIFIC)
+    {
+        switch (aStatus.getServiceSpecificError())
+        {
+        case IThreadChip::ERROR_FAILED:
+            error = OT_ERROR_FAILED;
+            break;
+        case IThreadChip::ERROR_BUSY:
+            error = OT_ERROR_BUSY;
+            break;
+        case IThreadChip::ERROR_NO_BUFS:
+            error = OT_ERROR_NO_BUFS;
+            break;
+        default:
+            error = OT_ERROR_FAILED;
+            break;
+        }
+    }
+
+exit:
+    return error;
+}
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
diff --git a/src/android/thread_network_hal/hal_interface.hpp b/src/android/thread_network_hal/hal_interface.hpp
new file mode 100644
index 0000000..da19390
--- /dev/null
+++ b/src/android/thread_network_hal/hal_interface.hpp
@@ -0,0 +1,210 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the copyright holder nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *   This file includes definitions for the IPC binder interface to radio (RCP).
+ */
+
+#ifndef ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
+#define ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
+
+#include "openthread-posix-config.h"
+
+#include "platform-posix.h"
+#include "lib/spinel/spinel_interface.hpp"
+
+#include <openthread/openthread-system.h>
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <aidl/android/hardware/threadnetwork/BnThreadChipCallback.h>
+#include <aidl/android/hardware/threadnetwork/IThreadChip.h>
+#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
+
+namespace ot {
+namespace Posix {
+
+/**
+ * This class defines an IPC Binder interface to the Radio Co-processor (RCP).
+ *
+ */
+class HalInterface
+{
+public:
+    /**
+     * This constructor initializes the object.
+     *
+     * @param[in] aCallback         A reference to a `Callback` object.
+     * @param[in] aCallbackContext  The context pointer passed to the callback.
+     * @param[in] aFrameBuffer      A reference to a `RxFrameBuffer` object.
+     *
+     */
+    HalInterface(Spinel::SpinelInterface::ReceiveFrameCallback aCallback,
+                 void                                         *aCallbackContext,
+                 Spinel::SpinelInterface::RxFrameBuffer       &aFrameBuffer);
+
+    /**
+     * This destructor deinitializes the object.
+     *
+     */
+    ~HalInterface(void);
+
+    /**
+     * This method initializes the interface to the Radio Co-processor (RCP).
+     *
+     * @note This method should be called before reading and sending spinel frames to the interface.
+     *
+     * @param[in]  aRadioUrl          Arguments parsed from radio url.
+     *
+     * @retval OT_ERROR_NONE          The interface is initialized successfully.
+     * @retval OT_ERROR_ALREADY       The interface is already initialized.
+     * @retval OT_ERROR_INVALID_ARGS  The UART device or executable cannot be found or failed to open/run.
+     *
+     */
+    otError Init(const Url::Url &aRadioUrl);
+
+    /**
+     * This method deinitializes the interface to the RCP.
+     *
+     */
+    void Deinit(void);
+
+    /**
+     * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
+     *
+     * @param[in] aFrame     A pointer to buffer containing the spinel frame to send.
+     * @param[in] aLength    The length (number of bytes) in the frame.
+     *
+     * @retval OT_ERROR_NONE     Successfully encoded and sent the spinel frame.
+     * @retval OT_ERROR_BUSY     Failed due to another operation is on going.
+     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to encode the frame.
+     * @retval OT_ERROR_FAILED   Failed to call the HAL to send the frame.
+     *
+     */
+    otError SendFrame(const uint8_t *aFrame, uint16_t aLength);
+
+    /**
+     * This method waits for receiving part or all of spinel frame within specified interval.
+     *
+     * @param[in]  aTimeout  The timeout value in microseconds.
+     *
+     * @retval OT_ERROR_NONE             Part or all of spinel frame is received.
+     * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout.
+     *
+     */
+    otError WaitForFrame(uint64_t aTimeoutUs);
+
+    /**
+     * This method updates the file descriptor sets with file descriptors used by the radio driver.
+     *
+     * @param[inout]  aReadFdSet   A reference to the read file descriptors.
+     * @param[inout]  aWriteFdSet  A reference to the write file descriptors.
+     * @param[inout]  aMaxFd       A reference to the max file descriptor.
+     * @param[inout]  aTimeout     A reference to the timeout.
+     *
+     */
+    void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
+
+    /**
+     * This method performs radio driver processing.
+     *
+     * @param[in]   aContext        The context containing fd_sets.
+     *
+     */
+    void Process(const RadioProcessContext &aContext);
+
+    /**
+     * This method returns the bus speed between the host and the radio.
+     *
+     * @returns   Bus speed in bits/second.
+     *
+     */
+    uint32_t GetBusSpeed(void) const;
+
+    /**
+     * This method is called when RCP failure detected and resets internal states of the interface.
+     *
+     */
+    void OnRcpReset(void);
+
+    /**
+     * This method is called when RCP is reset to recreate the connection with it.
+     * Intentionally empty.
+     *
+     */
+    otError ResetConnection(void) { return OT_ERROR_NONE; }
+
+private:
+    void        ReceiveFrameCallback(const std::vector<uint8_t> &aFrame);
+    static void BinderDeathCallback(void *aContext);
+    otError     StatusToError(::ndk::ScopedAStatus &aStatus);
+
+    class ThreadChipCallback : public ::aidl::android::hardware::threadnetwork::BnThreadChipCallback
+    {
+    public:
+        ThreadChipCallback(HalInterface *aInterface)
+            : mInterface(aInterface)
+        {
+        }
+
+        ::ndk::ScopedAStatus onReceiveSpinelFrame(const std::vector<uint8_t> &in_aFrame)
+        {
+            mInterface->ReceiveFrameCallback(in_aFrame);
+            return ndk::ScopedAStatus::ok();
+        }
+
+    private:
+        HalInterface *mInterface;
+    };
+
+    enum
+    {
+        kMaxFrameSize = Spinel::SpinelInterface::kMaxFrameSize,
+    };
+
+    Spinel::SpinelInterface::ReceiveFrameCallback mRxFrameCallback;
+    void                                         *mRxFrameContext;
+    Spinel::SpinelInterface::RxFrameBuffer       &mRxFrameBuffer;
+
+    std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChip>         mThreadChip;
+    std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChipCallback> mThreadChipCallback;
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+    int                                  mBinderFd;
+
+    // Non-copyable, intentionally not implemented.
+    HalInterface(const HalInterface &);
+    HalInterface &operator=(const HalInterface &);
+};
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+#endif // ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
diff --git a/src/android/thread_network_hal/vendor_interface.cpp b/src/android/thread_network_hal/vendor_interface.cpp
new file mode 100644
index 0000000..fb8c66f
--- /dev/null
+++ b/src/android/thread_network_hal/vendor_interface.cpp
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the copyright holder nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *   This file includes the implementation for the vendor defined radio spinel interface
+ *   to radio Co-Processor (RCP).
+ */
+
+#include "vendor_interface.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <linux/gpio.h>
+#include <linux/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <sys/select.h>
+
+#include <memory>
+
+#include "hal_interface.hpp"
+
+namespace ot {
+namespace Posix {
+using ot::Spinel::SpinelInterface;
+
+HalInterface *sHalInterface = nullptr;
+
+VendorInterface::VendorInterface(SpinelInterface::ReceiveFrameCallback aCallback,
+                                 void                                 *aCallbackContext,
+                                 SpinelInterface::RxFrameBuffer       &aFrameBuffer)
+{
+    sHalInterface = new HalInterface(aCallback, aCallbackContext, aFrameBuffer);
+    assert(sHalInterface != nullptr);
+}
+
+otError VendorInterface::Init(const Url::Url &aRadioUrl)
+{
+    return sHalInterface->Init(aRadioUrl);
+}
+
+VendorInterface::~VendorInterface(void)
+{
+    sHalInterface->Deinit();
+    delete sHalInterface;
+    sHalInterface = nullptr;
+}
+
+void VendorInterface::Deinit(void)
+{
+    sHalInterface->Deinit();
+}
+
+uint32_t VendorInterface::GetBusSpeed(void) const
+{
+    return sHalInterface->GetBusSpeed();
+}
+
+void VendorInterface::OnRcpReset(void)
+{
+    sHalInterface->OnRcpReset();
+}
+
+void VendorInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
+{
+    sHalInterface->UpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd, aTimeout);
+}
+
+void VendorInterface::Process(const RadioProcessContext &aContext)
+{
+    sHalInterface->Process(aContext);
+}
+
+otError VendorInterface::WaitForFrame(uint64_t aTimeoutUs)
+{
+    return sHalInterface->WaitForFrame(aTimeoutUs);
+}
+
+otError VendorInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength)
+{
+    return sHalInterface->SendFrame(aFrame, aLength);
+}
+
+otError VendorInterface::ResetConnection(void)
+{
+    return sHalInterface->ResetConnection();
+}
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
diff --git a/src/posix/platform/mainloop.hpp b/src/posix/platform/mainloop.hpp
index d4f6ac8..4f0fa7c 100644
--- a/src/posix/platform/mainloop.hpp
+++ b/src/posix/platform/mainloop.hpp
@@ -65,6 +65,12 @@
      */
     virtual void Process(const otSysMainloopContext &aContext) = 0;
 
+    /**
+     * This method marks desturctor virtual method.
+     *
+     */
+    virtual ~Source() = default;
+
 private:
     Source *mNext = nullptr;
 };