1 /*
2 * Copyright 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 <bluetooth/log.h>
18 #include <gtest/gtest.h>
19 #include <unistd.h>
20
21 #include "stack/include/avct_api.h"
22 #include "stack/include/bt_psm_types.h"
23 #include "test/fake/fake_osi.h"
24 #include "test/mock/mock_stack_l2cap_interface.h"
25
26 using ::testing::_;
27 using ::testing::Args;
28 using ::testing::DoAll;
29 using ::testing::SaveArg;
30
31 namespace {
32 constexpr uint16_t kRemoteCid = 0x0123;
33 constexpr uint16_t kRemoteBrowseCid = 0x0456;
34 const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
35 } // namespace
36
37 class StackAvctpWithMocksTest : public ::testing::Test {
38 protected:
SetUp()39 void SetUp() override {
40 fake_osi_ = std::make_unique<::test::fake::FakeOsi>();
41 bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
42 }
43
TearDown()44 void TearDown() override {}
45
46 bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
47 std::unique_ptr<test::fake::FakeOsi> fake_osi_;
48 };
49
50 class StackAvctpTest : public StackAvctpWithMocksTest {
51 protected:
SetUp()52 void SetUp() override {
53 StackAvctpWithMocksTest::SetUp();
54 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
55 .WillRepeatedly([this](uint16_t psm, const tL2CAP_APPL_INFO& cb, bool /* c */,
56 tL2CAP_ERTM_INFO* /*d*/, uint16_t /* e */, uint16_t /* f */,
57 uint16_t /* g */) {
58 this->callback_map_.insert(std::make_tuple(psm, cb));
59 return psm;
60 });
61 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).WillRepeatedly([]() {
62 return true;
63 });
64 AVCT_Register();
65 // Make sure we have a callback for both PSMs
66 ASSERT_EQ(2U, callback_map_.size());
67 }
68
TearDown()69 void TearDown() override {
70 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP));
71 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE));
72 AVCT_Deregister();
73 StackAvctpWithMocksTest::TearDown();
74 }
75
76 std::map<uint16_t, tL2CAP_APPL_INFO> callback_map_;
77 int fd_{STDOUT_FILENO};
78 };
79
TEST_F(StackAvctpTest,AVCT_Dumpsys)80 TEST_F(StackAvctpTest, AVCT_Dumpsys) { AVCT_Dumpsys(fd_); }
81
TEST_F(StackAvctpTest,AVCT_CreateConn)82 TEST_F(StackAvctpTest, AVCT_CreateConn) {
83 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
84 .WillRepeatedly([](uint16_t /* psm */, const RawAddress /* bd_addr */,
85 uint16_t /* sec_level */) { return 0x1234; });
86
87 uint8_t handle;
88 tAVCT_CC cc = {
89 .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */,
90 const RawAddress* /* peer_addr */) {},
91 .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */,
92 BT_HDR* /* p_pkt */) {},
93 .pid = 0x1234,
94 .role = AVCT_ROLE_INITIATOR,
95 .control = 1,
96 };
97 ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress));
98 ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle));
99 }
100
TEST_F(StackAvctpTest,AVCT_CreateBrowse)101 TEST_F(StackAvctpTest, AVCT_CreateBrowse) {
102 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
103 .WillRepeatedly([](uint16_t /* psm */, const RawAddress /* bd_addr */,
104 uint16_t /* sec_level */) { return 0x1234; });
105
106 uint8_t handle;
107 tAVCT_CC cc = {
108 .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */,
109 const RawAddress* /* peer_addr */) {},
110 .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */,
111 BT_HDR* /* p_pkt */) {},
112 .pid = 0x1234,
113 .role = AVCT_ROLE_INITIATOR,
114 .control = 1,
115 };
116 ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress));
117 ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR));
118
119 ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle));
120 ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle));
121 }
122
TEST_F(StackAvctpTest,AVCT_RemoteInitiatesControl)123 TEST_F(StackAvctpTest, AVCT_RemoteInitiatesControl) {
124 // AVCT Control
125 callback_map_[BT_PSM_AVCTP].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid, BT_PSM_AVCTP, 0);
126 callback_map_[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK);
127 }
128
TEST_F(StackAvctpTest,AVCT_RemoteInitiatesBrowse)129 TEST_F(StackAvctpTest, AVCT_RemoteInitiatesBrowse) {
130 // AVCT Control
131 callback_map_[BT_PSM_AVCTP].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid, BT_PSM_AVCTP, 0);
132 callback_map_[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK);
133
134 // AVCT Browse
135 callback_map_[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid,
136 BT_PSM_AVCTP_BROWSE, 0);
137 callback_map_[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK);
138
139 AVCT_Dumpsys(fd_);
140 }
141
TEST_F(StackAvctpWithMocksTest,AVCT_Lifecycle)142 TEST_F(StackAvctpWithMocksTest, AVCT_Lifecycle) {
143 // Register the AVCT profile and capture the l2cap callbacks
144 std::map<uint16_t, tL2CAP_APPL_INFO> callback_map;
145 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
146 .WillRepeatedly([&callback_map](uint16_t psm, const tL2CAP_APPL_INFO& cb, bool /* c */,
147 tL2CAP_ERTM_INFO* /*d*/, uint16_t /* e */,
148 uint16_t /* f */, uint16_t /* g */) {
149 callback_map.insert(std::make_tuple(psm, cb));
150 return psm;
151 });
152 AVCT_Register();
153
154 // Return well known l2cap channel IDs for each of the two PSMs
155 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
156 .WillRepeatedly(
157 [](uint16_t psm, const RawAddress /* bd_addr */, uint16_t /* sec_level */) {
158 return (psm == BT_PSM_AVCTP) ? kRemoteCid : kRemoteBrowseCid;
159 });
160
161 uint8_t handle;
162 tAVCT_CC cc = {
163 .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */,
164 const RawAddress* /* peer_addr */) {},
165 .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */,
166 BT_HDR* /* p_pkt */) {},
167 .pid = 0x1234,
168 .role = AVCT_ROLE_INITIATOR,
169 .control = 1,
170 };
171
172 // Initiate the creation of both control and browse AVCT connections
173 ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress));
174 ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR));
175
176 // Provide appropriate l2cap remote responses to open both channels
177 tL2CAP_CFG_INFO l2cap_cfg{};
178 callback_map[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK);
179 callback_map[BT_PSM_AVCTP].pL2CA_ConfigCfm_Cb(kRemoteCid, 0, &l2cap_cfg);
180 callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteBrowseCid,
181 tL2CAP_CONN::L2CAP_CONN_OK);
182 callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConfigCfm_Cb(kRemoteBrowseCid, 0, &l2cap_cfg);
183
184 // Close the profile by deregistering from l2cap
185 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP));
186 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE));
187 AVCT_Deregister();
188
189 // Ensure that API calls with a cached handle value or any run from a reactor
190 // thread or message loop do not fail
191 ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle));
192 ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle));
193 }
194