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