add fuzz test and fix the Thread network HAL compile errors

Bug: 288825495
Test: Build and run fuzz test in cuttlefish

Change-Id: If14bd95657d6a71737a348ccbc6d1b05bbcc1f4c
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 9fbf93e..93beb92 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -834,12 +834,4 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.threadnetwork</name>
-        <version>1</version>
-        <interface>
-            <name>IThreadChip</name>
-            <regex-instance>chip[0-9]+</regex-instance>
-        </interface>
-    </hal>
 </compatibility-matrix>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index e23f2ae..60bb2ab 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -794,4 +794,12 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.threadnetwork</name>
+        <version>1</version>
+        <interface>
+            <name>IThreadChip</name>
+            <regex-instance>chip[0-9]+</regex-instance>
+        </interface>
+    </hal>
 </compatibility-matrix>
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
index 201306d..736e808 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -24,10 +24,6 @@
         "libutils",
     ],
 
-    cppflags: [
-        "-Wno-non-virtual-dtor",
-    ],
-
     static_libs: [
         "openthread-common",
         "openthread-hdlc",
@@ -48,9 +44,43 @@
     name: "android.hardware.threadnetwork-service.sim",
     defaults: ["threadnetwork_service_default"],
     init_rc: ["android.hardware.threadnetwork-service.sim.rc"],
+    required: ["ot-rcp"],
 }
 
 cc_binary {
     name: "android.hardware.threadnetwork-service",
     defaults: ["threadnetwork_service_default"],
 }
+
+cc_fuzz {
+    name: "android.hardware.threadnetwork-service.fuzzer",
+
+    defaults:["service_fuzzer_defaults"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+
+    static_libs: [
+        "android.hardware.threadnetwork-V1-ndk",
+        "libbase",
+        "liblog",
+        "openthread-common",
+        "openthread-hdlc",
+        "openthread-platform",
+        "openthread-posix",
+        "openthread-url",
+    ],
+
+    srcs: [
+        "thread_chip.cpp",
+        "utils.cpp",
+        "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
new file mode 100644
index 0000000..512708d
--- /dev/null
+++ b/threadnetwork/aidl/default/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "thread_chip.hpp"
+
+using aidl::android::hardware::threadnetwork::ThreadChip;
+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";
+    auto service = ndk::SharedRefBase::make<ThreadChip>(url);
+
+    fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
+
diff --git a/threadnetwork/aidl/default/main.cpp b/threadnetwork/aidl/default/main.cpp
index 9f2a789..8419041 100644
--- a/threadnetwork/aidl/default/main.cpp
+++ b/threadnetwork/aidl/default/main.cpp
@@ -14,14 +14,37 @@
  * limitations under the License.
  */
 
+#include <aidl/android/hardware/threadnetwork/IThreadChip.h>
 #include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
 
 #include "service.hpp"
-#include "utils.hpp"
+#include "thread_chip.hpp"
+
+using aidl::android::hardware::threadnetwork::IThreadChip;
+using aidl::android::hardware::threadnetwork::ThreadChip;
 
 int main(int argc, char* argv[]) {
     CHECK_GT(argc, 1);
-    aidl::android::hardware::threadnetwork::Service service(&argv[1], argc - 1);
+    std::vector<std::shared_ptr<ThreadChip>> threadChips;
+    aidl::android::hardware::threadnetwork::Service service;
+
+    for (int id = 0; id < argc - 1; id++) {
+        binder_status_t status;
+        const std::string serviceName(std::string() + IThreadChip::descriptor + "/chip" +
+                                      std::to_string(id));
+        auto threadChip = ndk::SharedRefBase::make<ThreadChip>(argv[id + 1]);
+
+        CHECK_NE(threadChip, nullptr);
+
+        status = AServiceManager_addService(threadChip->asBinder().get(), serviceName.c_str());
+        CHECK_EQ(status, STATUS_OK);
+
+        ALOGI("ServiceName: %s, Url: %s", serviceName.c_str(), argv[id + 1]);
+        threadChips.push_back(std::move(threadChip));
+    }
 
     ALOGI("Thread Network HAL is running");
 
diff --git a/threadnetwork/aidl/default/service.cpp b/threadnetwork/aidl/default/service.cpp
index 44bb99a..7f583f4 100644
--- a/threadnetwork/aidl/default/service.cpp
+++ b/threadnetwork/aidl/default/service.cpp
@@ -18,25 +18,14 @@
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
-
-#include "thread_chip.hpp"
-#include "utils.hpp"
+#include <utils/Log.h>
 
 namespace aidl {
 namespace android {
 namespace hardware {
 namespace threadnetwork {
 
-Service::Service(char* urls[], int numUrls) : mBinderFd(-1) {
-    CHECK_NE(urls, nullptr);
-    CHECK_GT(numUrls, 0);
-
-    for (int i = 0; i < numUrls; i++) {
-        auto threadChip = ndk::SharedRefBase::make<ThreadChip>(i, urls[i]);
-        CHECK_NE(threadChip, nullptr);
-        mThreadChips.push_back(std::move(threadChip));
-    }
-
+Service::Service(void) : mBinderFd(-1) {
     binder_status_t status = ABinderProcess_setupPolling(&mBinderFd);
     CHECK_EQ(status, ::STATUS_OK);
     CHECK_GE(mBinderFd, 0);
diff --git a/threadnetwork/aidl/default/service.hpp b/threadnetwork/aidl/default/service.hpp
index 4137049..6a94791 100644
--- a/threadnetwork/aidl/default/service.hpp
+++ b/threadnetwork/aidl/default/service.hpp
@@ -15,7 +15,6 @@
  */
 
 #include "mainloop.hpp"
-#include "thread_chip.hpp"
 
 namespace aidl {
 namespace android {
@@ -24,7 +23,7 @@
 
 class Service : public ot::Posix::Mainloop::Source {
   public:
-    Service(char* urls[], int numUrls);
+    Service(void);
 
     void Update(otSysMainloopContext& context) override;
     void Process(const otSysMainloopContext& context) override;
@@ -32,7 +31,6 @@
 
   private:
     int mBinderFd;
-    std::vector<std::shared_ptr<ThreadChip>> mThreadChips;
 };
 }  // namespace threadnetwork
 }  // namespace hardware
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index b5cc7eb..e542c7c 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -19,26 +19,19 @@
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
-
-#include "utils.hpp"
+#include <utils/Log.h>
 
 namespace aidl {
 namespace android {
 namespace hardware {
 namespace threadnetwork {
 
-ThreadChip::ThreadChip(uint8_t id, char* url)
+ThreadChip::ThreadChip(char* url)
     : mUrl(),
       mInterface(handleReceivedFrame, this, mRxFrameBuffer),
       mRxFrameBuffer(),
       mCallback(nullptr) {
-    const std::string name(std::string() + IThreadChip::descriptor + "/chip" + std::to_string(id));
-    binder_status_t status;
-
-    ALOGI("ServiceName: %s, Url: %s", name.c_str(), url);
     CHECK_EQ(mUrl.Init(url), 0);
-    status = AServiceManager_addService(asBinder().get(), name.c_str());
-    CHECK_EQ(status, STATUS_OK);
 }
 
 void ThreadChip::clientDeathCallback(void* context) {
@@ -85,17 +78,13 @@
     status = ndk::ScopedAStatus::ok();
 
 exit:
-    if (!status.isOk())
-    {
-        if (mBinderDeathRecipient != nullptr)
-        {
-           AIBinder_DeathRecipient_delete(mBinderDeathRecipient);
-           mBinderDeathRecipient = nullptr;
+    if (!status.isOk()) {
+        if (mBinderDeathRecipient != nullptr) {
+            AIBinder_DeathRecipient_delete(mBinderDeathRecipient);
+            mBinderDeathRecipient = nullptr;
         }
         ALOGW("Open failed, error: %s", status.getDescription().c_str());
-    }
-    else
-    {
+    } else {
         ALOGI("open()");
     }
 
@@ -137,8 +126,7 @@
     }
 
 exit:
-    if (!status.isOk())
-    {
+    if (!status.isOk()) {
         ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str());
     }
 
@@ -146,25 +134,20 @@
 }
 
 ndk::ScopedAStatus ThreadChip::reset() {
-    mInterface.OnRcpReset();
+    mInterface.HardwareReset();
     ALOGI("reset()");
     return ndk::ScopedAStatus::ok();
 }
 
 void ThreadChip::Update(otSysMainloopContext& context) {
     if (mCallback != nullptr) {
-        mInterface.UpdateFdSet(context.mReadFdSet, context.mWriteFdSet, context.mMaxFd,
-                               context.mTimeout);
+        mInterface.UpdateFdSet(&context);
     }
 }
 
 void ThreadChip::Process(const otSysMainloopContext& context) {
-    struct RadioProcessContext radioContext;
-
     if (mCallback != nullptr) {
-        radioContext.mReadFdSet = &context.mReadFdSet;
-        radioContext.mWriteFdSet = &context.mWriteFdSet;
-        mInterface.Process(radioContext);
+        mInterface.Process(&context);
     }
 }
 
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index d444374..d93dfef 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -33,7 +33,7 @@
 
 class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
   public:
-    ThreadChip(uint8_t id, char* url);
+    ThreadChip(char* url);
 
     ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
     ndk::ScopedAStatus close() override;
diff --git a/threadnetwork/aidl/default/utils.cpp b/threadnetwork/aidl/default/utils.cpp
index a8f3464..b4da7d7 100644
--- a/threadnetwork/aidl/default/utils.cpp
+++ b/threadnetwork/aidl/default/utils.cpp
@@ -15,9 +15,10 @@
  * limitations under the License.
  */
 
-#include "utils.hpp"
-
+#include <openthread/instance.h>
 #include <openthread/logging.h>
+#include <openthread/platform/alarm-milli.h>
+#include <utils/Log.h>
 
 void otLogCritPlat(const char* format, ...) {
     va_list args;
@@ -34,3 +35,7 @@
     __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, args);
     va_end(args);
 }
+
+OT_TOOL_WEAK void otPlatAlarmMilliFired(otInstance* aInstance) {
+    OT_UNUSED_VARIABLE(aInstance);
+}
diff --git a/threadnetwork/aidl/default/utils.hpp b/threadnetwork/aidl/default/utils.hpp
deleted file mode 100644
index 279c0ba..0000000
--- a/threadnetwork/aidl/default/utils.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#define LOG_TAG "threadnetwork_hal"
-#include <utils/Log.h>