1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "ThreadNetworkHalTargetTest"
18 
19 #include <future>
20 
21 #include <aidl/Gtest.h>
22 #include <aidl/Vintf.h>
23 #include <android-base/logging.h>
24 #include <android/binder_auto_utils.h>
25 #include <android/binder_manager.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/ProcessState.h>
28 #include <log/log.h>
29 
30 #include <aidl/android/hardware/threadnetwork/BnThreadChipCallback.h>
31 #include <aidl/android/hardware/threadnetwork/IThreadChip.h>
32 
33 using aidl::android::hardware::threadnetwork::BnThreadChipCallback;
34 using aidl::android::hardware::threadnetwork::IThreadChip;
35 using android::ProcessState;
36 using ndk::ScopedAStatus;
37 using ndk::SpAIBinder;
38 
39 namespace {
40 constexpr static int kCallbackTimeoutMs = 5000;
41 }  // namespace
42 
43 class ThreadChipCallback : public BnThreadChipCallback {
44   public:
ThreadChipCallback(const std::function<void (const std::vector<uint8_t> &)> & on_spinel_message_cb)45     ThreadChipCallback(const std::function<void(const std::vector<uint8_t>&)>& on_spinel_message_cb)
46         : on_spinel_message_cb_(on_spinel_message_cb) {}
47 
onReceiveSpinelFrame(const std::vector<uint8_t> & in_aFrame)48     ScopedAStatus onReceiveSpinelFrame(const std::vector<uint8_t>& in_aFrame) {
49         on_spinel_message_cb_(in_aFrame);
50         return ScopedAStatus::ok();
51     }
52 
53   private:
54     std::function<void(const std::vector<uint8_t>&)> on_spinel_message_cb_;
55 };
56 
57 class ThreadNetworkAidl : public testing::TestWithParam<std::string> {
58   public:
SetUp()59     virtual void SetUp() override {
60         std::string serviceName = GetParam();
61 
62         ALOGI("serviceName: %s", serviceName.c_str());
63 
64         thread_chip = IThreadChip::fromBinder(
65                 SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
66         ASSERT_NE(thread_chip, nullptr);
67     }
68 
TearDown()69     virtual void TearDown() override { thread_chip->close(); }
70 
71     std::shared_ptr<IThreadChip> thread_chip;
72 };
73 
TEST_P(ThreadNetworkAidl,Open)74 TEST_P(ThreadNetworkAidl, Open) {
75     std::shared_ptr<ThreadChipCallback> callback =
76             ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
77 
78     EXPECT_TRUE(thread_chip->open(callback).isOk());
79 }
80 
TEST_P(ThreadNetworkAidl,Close)81 TEST_P(ThreadNetworkAidl, Close) {
82     std::shared_ptr<ThreadChipCallback> callback =
83             ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
84 
85     EXPECT_TRUE(thread_chip->open(callback).isOk());
86     EXPECT_TRUE(thread_chip->close().isOk());
87 }
88 
TEST_P(ThreadNetworkAidl,Reset)89 TEST_P(ThreadNetworkAidl, Reset) {
90     ndk::ScopedAStatus status;
91     std::shared_ptr<ThreadChipCallback> callback =
92             ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
93 
94     EXPECT_TRUE(thread_chip->open(callback).isOk());
95     status = thread_chip->hardwareReset();
96     EXPECT_TRUE(status.isOk() || (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION));
97     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
98         GTEST_SKIP() << "Hardware reset is not supported";
99     }
100 }
101 
TEST_P(ThreadNetworkAidl,SendSpinelFrame)102 TEST_P(ThreadNetworkAidl, SendSpinelFrame) {
103     const uint8_t kCmdOffset = 2;
104     const uint8_t kMajorVersionOffset = 3;
105     const uint8_t kMinorVersionOffset = 4;
106     const std::vector<uint8_t> kGetSpinelProtocolVersion({0x81, 0x02, 0x01});
107     const std::vector<uint8_t> kGetSpinelProtocolVersionResponse({0x81, 0x06, 0x01, 0x04, 0x03});
108     uint8_t min_major_version = kGetSpinelProtocolVersionResponse[kMajorVersionOffset];
109     uint8_t min_minor_version = kGetSpinelProtocolVersionResponse[kMinorVersionOffset];
110     uint8_t major_version;
111     uint8_t minor_version;
112     std::promise<void> open_cb_promise;
113     std::future<void> open_cb_future{open_cb_promise.get_future()};
114     std::shared_ptr<ThreadChipCallback> callback;
115     std::vector<uint8_t> received_frame;
116     std::chrono::milliseconds timeout{kCallbackTimeoutMs};
117 
118     callback = ndk::SharedRefBase::make<ThreadChipCallback>(
119             [&](const std::vector<uint8_t>& in_aFrame) {
120                 if (in_aFrame.size() == kGetSpinelProtocolVersionResponse.size() &&
121                     in_aFrame[kCmdOffset] == kGetSpinelProtocolVersionResponse[kCmdOffset]) {
122                     major_version = in_aFrame[kMajorVersionOffset];
123                     minor_version = in_aFrame[kMinorVersionOffset];
124                     open_cb_promise.set_value();
125                 }
126             });
127 
128     ASSERT_NE(callback, nullptr);
129 
130     EXPECT_TRUE(thread_chip->open(callback).isOk());
131 
132     EXPECT_TRUE(thread_chip->sendSpinelFrame(kGetSpinelProtocolVersion).isOk());
133     EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
134 
135     EXPECT_GE(major_version, min_major_version);
136     if (major_version == min_major_version) {
137         EXPECT_GE(minor_version, min_minor_version);
138     }
139 }
140 
141 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThreadNetworkAidl);
142 INSTANTIATE_TEST_SUITE_P(
143         Thread, ThreadNetworkAidl,
144         testing::ValuesIn(android::getAidlHalInstanceNames(IThreadChip::descriptor)),
145         android::PrintInstanceNameToString);
146 
main(int argc,char ** argv)147 int main(int argc, char** argv) {
148     ::testing::InitGoogleTest(&argc, argv);
149     ProcessState::self()->setThreadPoolMaxThreadCount(1);
150     ProcessState::self()->startThreadPool();
151     return RUN_ALL_TESTS();
152 }
153