1 /*
2 * Copyright 2020 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 <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include "service/a2dp_source.h"
21 #include "service/hal/fake_bluetooth_av_interface.h"
22
23 using ::testing::_;
24 using ::testing::Return;
25
26 namespace bluetooth {
27 namespace {
28
29 class MockA2dpSourceHandler
30 : public hal::FakeBluetoothAvInterface::TestA2dpSourceHandler {
31 public:
32 MockA2dpSourceHandler() = default;
33 ~MockA2dpSourceHandler() override = default;
34
35 MOCK_METHOD1(Connect, bt_status_t(RawAddress));
36 MOCK_METHOD1(Disconnect, bt_status_t(RawAddress));
37
38 private:
39 DISALLOW_COPY_AND_ASSIGN(MockA2dpSourceHandler);
40 };
41
42 class TestDelegate : public A2dpSource::Delegate {
43 public:
44 TestDelegate() = default;
45 ~TestDelegate() override = default;
46
47 struct RequestData {
48 std::string device_address;
49 int state = -1;
50 int count = 0;
51 };
52
53 // A2dpSource::Delegate implementation:
OnConnectionState(const std::string & device_address,int state)54 void OnConnectionState(const std::string& device_address,
55 int state) override {
56 ++connection_state_.count;
57 connection_state_.device_address = device_address;
58 connection_state_.state = state;
59 }
OnAudioState(const std::string & device_address,int state)60 void OnAudioState(const std::string& device_address, int state) override {
61 ++audio_state_.count;
62 audio_state_.device_address = device_address;
63 audio_state_.state = state;
64 }
OnAudioConfig(const std::string & device_address,A2dpCodecConfig codec_config,const std::vector<A2dpCodecConfig> & codecs_local_capabilities,const std::vector<A2dpCodecConfig> & codecs_selectable_capabilities)65 void OnAudioConfig(
66 const std::string& device_address, A2dpCodecConfig codec_config,
67 const std::vector<A2dpCodecConfig>& codecs_local_capabilities,
68 const std::vector<A2dpCodecConfig>& codecs_selectable_capabilities)
69 override {
70 ++audio_config_.count;
71 audio_config_.device_address = device_address;
72 }
73
connection_state() const74 const RequestData& connection_state() const { return connection_state_; }
audio_state() const75 const RequestData& audio_state() const { return audio_state_; }
audio_config() const76 const RequestData& audio_config() const { return audio_config_; }
77
78 private:
79 RequestData connection_state_;
80 RequestData audio_state_;
81 RequestData audio_config_;
82 };
83
84 class A2dpSourceTest : public ::testing::Test {
85 public:
86 A2dpSourceTest() = default;
87 ~A2dpSourceTest() override = default;
88
SetUp()89 void SetUp() override {
90 mock_handler_.reset(new MockA2dpSourceHandler());
91 fake_hal_av_iface_ = new hal::FakeBluetoothAvInterface(mock_handler_);
92 hal::BluetoothAvInterface::InitializeForTesting(fake_hal_av_iface_);
93 factory_.reset(new A2dpSourceFactory());
94 }
95
TearDown()96 void TearDown() override {
97 factory_.reset();
98 hal::BluetoothAvInterface::CleanUp();
99 }
100
101 protected:
102 hal::FakeBluetoothAvInterface* fake_hal_av_iface_;
103 std::shared_ptr<MockA2dpSourceHandler> mock_handler_;
104 std::unique_ptr<A2dpSourceFactory> factory_;
105
106 private:
107 DISALLOW_COPY_AND_ASSIGN(A2dpSourceTest);
108 };
109
110 class A2dpSourcePostRegisterTest : public A2dpSourceTest {
111 public:
112 A2dpSourcePostRegisterTest() = default;
113 ~A2dpSourcePostRegisterTest() override = default;
114
SetUp()115 void SetUp() override {
116 A2dpSourceTest::SetUp();
117 Uuid uuid = Uuid::GetRandom();
118 auto callback = [&](BLEStatus status, const Uuid& in_uuid,
119 std::unique_ptr<BluetoothInstance> in_client) {
120 CHECK(in_uuid == uuid);
121 CHECK(in_client.get());
122 CHECK(status == BLE_STATUS_SUCCESS);
123
124 a2dp_source_ = std::unique_ptr<A2dpSource>(
125 static_cast<A2dpSource*>(in_client.release()));
126 };
127
128 factory_->RegisterInstance(uuid, callback);
129 }
130
TearDown()131 void TearDown() override {
132 a2dp_source_ = nullptr;
133 A2dpSourceTest::TearDown();
134 }
135
136 protected:
Connect(const std::string & addr)137 void Connect(const std::string& addr) {
138 RawAddress hal_addr;
139 ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
140
141 EXPECT_CALL(*mock_handler_, Connect(hal_addr))
142 .WillOnce(Return(BT_STATUS_SUCCESS));
143
144 EXPECT_TRUE(a2dp_source_->Connect(addr));
145 }
146
Disconnect(const std::string & addr)147 void Disconnect(const std::string& addr) {
148 RawAddress hal_addr;
149 ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
150
151 EXPECT_CALL(*mock_handler_, Disconnect(hal_addr))
152 .WillOnce(Return(BT_STATUS_SUCCESS));
153
154 EXPECT_TRUE(a2dp_source_->Disconnect(addr));
155 }
156
157 std::unique_ptr<A2dpSource> a2dp_source_;
158
159 private:
160 DISALLOW_COPY_AND_ASSIGN(A2dpSourcePostRegisterTest);
161 };
162
TEST_F(A2dpSourceTest,RegisterA2dpSource)163 TEST_F(A2dpSourceTest, RegisterA2dpSource) {
164 // These will be asynchronously populate with a result when the callback
165 // executes.
166 BLEStatus status = BLE_STATUS_SUCCESS;
167 Uuid cb_uuid;
168 std::unique_ptr<A2dpSource> a2dp_source;
169 int callback_count = 0;
170
171 auto callback = [&](BLEStatus in_status, const Uuid& uuid,
172 std::unique_ptr<BluetoothInstance> in_a2dp_source) {
173 status = in_status;
174 cb_uuid = uuid;
175 a2dp_source = std::unique_ptr<A2dpSource>(
176 static_cast<A2dpSource*>(in_a2dp_source.release()));
177 callback_count++;
178 };
179
180 Uuid uuid0 = Uuid::GetRandom();
181
182 // This should always succeed.
183 EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
184 EXPECT_EQ(1, callback_count);
185
186 testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
187
188 ASSERT_TRUE(a2dp_source.get() !=
189 nullptr); // Assert to terminate in case of error
190 EXPECT_EQ(BLE_STATUS_SUCCESS, status);
191 EXPECT_EQ(bluetooth::A2dpSource::kSingletonInstanceId,
192 a2dp_source->GetInstanceId());
193 EXPECT_EQ(uuid0, a2dp_source->GetAppIdentifier());
194 EXPECT_EQ(uuid0, cb_uuid);
195
196 testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
197 }
198
TEST_F(A2dpSourcePostRegisterTest,Connect)199 TEST_F(A2dpSourcePostRegisterTest, Connect) {
200 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
201 Connect(kTestAddr);
202 Disconnect(kTestAddr);
203 }
204
TEST_F(A2dpSourcePostRegisterTest,CallbackTest)205 TEST_F(A2dpSourcePostRegisterTest, CallbackTest) {
206 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
207 RawAddress hal_addr;
208 ASSERT_TRUE(RawAddress::FromString(kTestAddr, hal_addr));
209
210 TestDelegate delegate;
211 a2dp_source_->SetDelegate(&delegate);
212 Connect(kTestAddr);
213
214 // OnConnectionState
215 const int kConnectionState = 2;
216 EXPECT_EQ(0, delegate.connection_state().count);
217 fake_hal_av_iface_->NotifyConnectionState(
218 hal_addr, static_cast<btav_connection_state_t>(kConnectionState));
219 EXPECT_EQ(1, delegate.connection_state().count);
220 EXPECT_EQ(kTestAddr, delegate.connection_state().device_address);
221 EXPECT_EQ(kConnectionState, delegate.connection_state().state);
222
223 // OnAudioState
224 const int kAudioState = 1;
225 EXPECT_EQ(0, delegate.audio_state().count);
226 fake_hal_av_iface_->NotifyAudioState(
227 hal_addr, static_cast<btav_audio_state_t>(kAudioState));
228 EXPECT_EQ(1, delegate.audio_state().count);
229 EXPECT_EQ(kTestAddr, delegate.audio_state().device_address);
230 EXPECT_EQ(kAudioState, delegate.audio_state().state);
231
232 // OnAudioConfig
233 const btav_a2dp_codec_config_t codec_config{};
234 const std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities(0);
235 const std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities(0);
236 EXPECT_EQ(0, delegate.audio_config().count);
237 fake_hal_av_iface_->NotifyAudioConfig(hal_addr, codec_config,
238 codecs_local_capabilities,
239 codecs_selectable_capabilities);
240 EXPECT_EQ(1, delegate.audio_config().count);
241 EXPECT_EQ(kTestAddr, delegate.audio_config().device_address);
242
243 fake_hal_av_iface_->QueryMandatoryCodecPreferred(hal_addr);
244
245 Disconnect(kTestAddr);
246 }
247
248 } // namespace
249 } // namespace bluetooth
250