blob: 1069207e1e65b7ff3f8b698516a22e692fe5f1b3 [file] [log] [blame]
/*
* Copyright (C) 2024 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 <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/bluetooth/socket/BnBluetoothSocketCallback.h>
#include <aidl/android/hardware/bluetooth/socket/IBluetoothSocket.h>
#include <aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <future>
using ::aidl::android::hardware::bluetooth::socket::BnBluetoothSocketCallback;
using ::aidl::android::hardware::bluetooth::socket::IBluetoothSocket;
using ::aidl::android::hardware::bluetooth::socket::SocketCapabilities;
using ::aidl::android::hardware::bluetooth::socket::SocketContext;
using ::ndk::ScopedAStatus;
namespace {
constexpr static int kCallbackTimeoutMs = 250;
constexpr static int kOpenedCallbackTimeoutMs = 5000;
} // namespace
class BluetoothSocketCallback : public BnBluetoothSocketCallback {
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)
: on_hal_opened_complete_cb_(on_hal_opened_complete_cb) {}
ScopedAStatus openedComplete(
int64_t in_socketId,
::aidl::android::hardware::bluetooth::socket::Status in_status,
const std::string& in_reason) override {
on_hal_opened_complete_cb_(in_socketId, in_status, in_reason);
return ::ndk::ScopedAStatus::ok();
}
ScopedAStatus close(int64_t /* in_socketId */,
const std::string& /* in_reason */) override {
return ::ndk::ScopedAStatus::ok();
}
private:
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_;
};
class BluetoothSocketTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
ALOGI("SetUp Socket Test");
bluetooth_socket_ = IBluetoothSocket::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
ASSERT_NE(bluetooth_socket_, nullptr);
}
virtual void TearDown() override {
ALOGI("TearDown Socket Test");
bluetooth_socket_ = nullptr;
ASSERT_EQ(bluetooth_socket_, nullptr);
}
std::shared_ptr<IBluetoothSocket> bluetooth_socket_;
};
TEST_P(BluetoothSocketTest, registerCallback) {
std::promise<void> open_cb_promise;
std::future<void> open_cb_future{open_cb_promise.get_future()};
std::shared_ptr<BluetoothSocketCallback> callback =
ndk::SharedRefBase::make<BluetoothSocketCallback>(
[&open_cb_promise](auto /* socket_id */, auto /* status */,
auto /* reason */) {
open_cb_promise.set_value();
});
ScopedAStatus status = bluetooth_socket_->registerCallback(callback);
ASSERT_TRUE(status.isOk());
}
TEST_P(BluetoothSocketTest, GetSocketCapabilities) {
SocketCapabilities socket_capabilities;
ScopedAStatus status =
bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(socket_capabilities.leCocCapabilities.numberOfSupportedSockets >=
0);
if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets) {
// When LE COC is supported, the local MTU must be configured within the
// valid range defined in the L2CAP specification.
ASSERT_TRUE(socket_capabilities.leCocCapabilities.mtu >= 23 &&
socket_capabilities.leCocCapabilities.mtu <= 65535);
}
ASSERT_TRUE(socket_capabilities.rfcommCapabilities.numberOfSupportedSockets >=
0);
if (socket_capabilities.rfcommCapabilities.numberOfSupportedSockets) {
// When RFCOMM is supported, the maximum frame size must be configured
// within the valid range defined in the RFCOMM specification.
ASSERT_TRUE(socket_capabilities.rfcommCapabilities.maxFrameSize >= 23 &&
socket_capabilities.rfcommCapabilities.maxFrameSize <= 32767);
}
}
TEST_P(BluetoothSocketTest, Opened) {
std::promise<void> open_cb_promise;
std::future<void> open_cb_future{open_cb_promise.get_future()};
std::shared_ptr<BluetoothSocketCallback> callback =
ndk::SharedRefBase::make<BluetoothSocketCallback>(
[&open_cb_promise](auto /* socket_id */, auto /* status */,
auto /* reason */) {
open_cb_promise.set_value();
});
bluetooth_socket_->registerCallback(callback);
SocketCapabilities socket_capabilities;
bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
SocketContext socket_context;
ScopedAStatus status = bluetooth_socket_->opened(socket_context);
std::chrono::milliseconds timeout{kOpenedCallbackTimeoutMs};
if (status.isOk()) {
// If IBluetoothSocket.opened() returns success, the callback
// BluetoothSocketCallback.openedComplete() must be called within the
// timeout.
EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
} else {
// If IBluetoothSocket.opened() returns failure, the callback
// BluetoothSocketCallback.openedComplete() must not be called.
EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::timeout);
}
}
TEST_P(BluetoothSocketTest, Closed) {
std::promise<void> open_cb_promise;
std::future<void> open_cb_future{open_cb_promise.get_future()};
std::shared_ptr<BluetoothSocketCallback> callback =
ndk::SharedRefBase::make<BluetoothSocketCallback>(
[&open_cb_promise](auto /* socket_id */, auto /* status */,
auto /* reason */) {
open_cb_promise.set_value();
});
bluetooth_socket_->registerCallback(callback);
SocketCapabilities socket_capabilities;
bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
long socket_id = 1;
bluetooth_socket_->closed(socket_id);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothSocketTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothSocketTest,
testing::ValuesIn(android::getAidlHalInstanceNames(
IBluetoothSocket::descriptor)),
android::PrintInstanceNameToString);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_startThreadPool();
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
}