1 /*
2 * Copyright (C) 2024 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 #include <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <aidl/android/hardware/bluetooth/socket/BnBluetoothSocketCallback.h>
20 #include <aidl/android/hardware/bluetooth/socket/IBluetoothSocket.h>
21 #include <aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.h>
22 #include <android-base/logging.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25 #include <binder/IServiceManager.h>
26 #include <utils/Log.h>
27
28 #include <future>
29
30 using ::aidl::android::hardware::bluetooth::socket::BnBluetoothSocketCallback;
31 using ::aidl::android::hardware::bluetooth::socket::IBluetoothSocket;
32 using ::aidl::android::hardware::bluetooth::socket::SocketCapabilities;
33 using ::aidl::android::hardware::bluetooth::socket::SocketContext;
34 using ::ndk::ScopedAStatus;
35
36 namespace {
37 constexpr static int kCallbackTimeoutMs = 250;
38 constexpr static int kOpenedCallbackTimeoutMs = 5000;
39 } // namespace
40
41 class BluetoothSocketCallback : public BnBluetoothSocketCallback {
42 public:
BluetoothSocketCallback(const std::function<void (int64_t in_socketId,::aidl::android::hardware::bluetooth::socket::Status in_status,const std::string & in_reason)> & on_hal_opened_complete_cb)43 BluetoothSocketCallback(
44 const std::function<
45 void(int64_t in_socketId,
46 ::aidl::android::hardware::bluetooth::socket::Status in_status,
47 const std::string& in_reason)>& on_hal_opened_complete_cb)
48 : on_hal_opened_complete_cb_(on_hal_opened_complete_cb) {}
49
openedComplete(int64_t in_socketId,::aidl::android::hardware::bluetooth::socket::Status in_status,const std::string & in_reason)50 ScopedAStatus openedComplete(
51 int64_t in_socketId,
52 ::aidl::android::hardware::bluetooth::socket::Status in_status,
53 const std::string& in_reason) override {
54 on_hal_opened_complete_cb_(in_socketId, in_status, in_reason);
55 return ::ndk::ScopedAStatus::ok();
56 }
57
close(int64_t,const std::string &)58 ScopedAStatus close(int64_t /* in_socketId */,
59 const std::string& /* in_reason */) override {
60 return ::ndk::ScopedAStatus::ok();
61 }
62
63 private:
64 std::function<void(
65 int64_t in_socketId,
66 ::aidl::android::hardware::bluetooth::socket::Status in_status,
67 const std::string& in_reason)>
68 on_hal_opened_complete_cb_;
69 };
70
71 class BluetoothSocketTest : public ::testing::TestWithParam<std::string> {
72 public:
SetUp()73 virtual void SetUp() override {
74 ALOGI("SetUp Socket Test");
75 bluetooth_socket_ = IBluetoothSocket::fromBinder(
76 ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
77 ASSERT_NE(bluetooth_socket_, nullptr);
78 }
79
TearDown()80 virtual void TearDown() override {
81 ALOGI("TearDown Socket Test");
82 bluetooth_socket_ = nullptr;
83 ASSERT_EQ(bluetooth_socket_, nullptr);
84 }
85
86 std::shared_ptr<IBluetoothSocket> bluetooth_socket_;
87 };
88
TEST_P(BluetoothSocketTest,registerCallback)89 TEST_P(BluetoothSocketTest, registerCallback) {
90 std::promise<void> open_cb_promise;
91 std::future<void> open_cb_future{open_cb_promise.get_future()};
92 std::shared_ptr<BluetoothSocketCallback> callback =
93 ndk::SharedRefBase::make<BluetoothSocketCallback>(
94 [&open_cb_promise](auto /* socket_id */, auto /* status */,
95 auto /* reason */) {
96 open_cb_promise.set_value();
97 });
98 ScopedAStatus status = bluetooth_socket_->registerCallback(callback);
99 ASSERT_TRUE(status.isOk());
100 }
101
TEST_P(BluetoothSocketTest,GetSocketCapabilities)102 TEST_P(BluetoothSocketTest, GetSocketCapabilities) {
103 SocketCapabilities socket_capabilities;
104 ScopedAStatus status =
105 bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
106 ASSERT_TRUE(status.isOk());
107 ASSERT_TRUE(socket_capabilities.leCocCapabilities.numberOfSupportedSockets >=
108 0);
109 if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets) {
110 // When LE COC is supported, the local MTU must be configured within the
111 // valid range defined in the L2CAP specification.
112 ASSERT_TRUE(socket_capabilities.leCocCapabilities.mtu >= 23 &&
113 socket_capabilities.leCocCapabilities.mtu <= 65535);
114 }
115 ASSERT_TRUE(socket_capabilities.rfcommCapabilities.numberOfSupportedSockets >=
116 0);
117 if (socket_capabilities.rfcommCapabilities.numberOfSupportedSockets) {
118 // When RFCOMM is supported, the maximum frame size must be configured
119 // within the valid range defined in the RFCOMM specification.
120 ASSERT_TRUE(socket_capabilities.rfcommCapabilities.maxFrameSize >= 23 &&
121 socket_capabilities.rfcommCapabilities.maxFrameSize <= 32767);
122 }
123 }
124
TEST_P(BluetoothSocketTest,Opened)125 TEST_P(BluetoothSocketTest, Opened) {
126 std::promise<void> open_cb_promise;
127 std::future<void> open_cb_future{open_cb_promise.get_future()};
128 std::shared_ptr<BluetoothSocketCallback> callback =
129 ndk::SharedRefBase::make<BluetoothSocketCallback>(
130 [&open_cb_promise](auto /* socket_id */, auto /* status */,
131 auto /* reason */) {
132 open_cb_promise.set_value();
133 });
134 bluetooth_socket_->registerCallback(callback);
135 SocketCapabilities socket_capabilities;
136 bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
137
138 SocketContext socket_context;
139 ScopedAStatus status = bluetooth_socket_->opened(socket_context);
140 std::chrono::milliseconds timeout{kOpenedCallbackTimeoutMs};
141 if (status.isOk()) {
142 // If IBluetoothSocket.opened() returns success, the callback
143 // BluetoothSocketCallback.openedComplete() must be called within the
144 // timeout.
145 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
146 } else {
147 // If IBluetoothSocket.opened() returns failure, the callback
148 // BluetoothSocketCallback.openedComplete() must not be called.
149 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::timeout);
150 }
151 }
152
TEST_P(BluetoothSocketTest,Closed)153 TEST_P(BluetoothSocketTest, Closed) {
154 std::promise<void> open_cb_promise;
155 std::future<void> open_cb_future{open_cb_promise.get_future()};
156 std::shared_ptr<BluetoothSocketCallback> callback =
157 ndk::SharedRefBase::make<BluetoothSocketCallback>(
158 [&open_cb_promise](auto /* socket_id */, auto /* status */,
159 auto /* reason */) {
160 open_cb_promise.set_value();
161 });
162 bluetooth_socket_->registerCallback(callback);
163 SocketCapabilities socket_capabilities;
164 bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
165
166 long socket_id = 1;
167 bluetooth_socket_->closed(socket_id);
168 }
169
170 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothSocketTest);
171 INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothSocketTest,
172 testing::ValuesIn(android::getAidlHalInstanceNames(
173 IBluetoothSocket::descriptor)),
174 android::PrintInstanceNameToString);
175
main(int argc,char ** argv)176 int main(int argc, char** argv) {
177 ::testing::InitGoogleTest(&argc, argv);
178 ABinderProcess_startThreadPool();
179 int status = RUN_ALL_TESTS();
180 ALOGI("Test result = %d", status);
181 return status;
182 }
183