1 //
2 // Copyright 2017 Google, Inc.
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_sink.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 MockA2dpSinkHandler
30 : public hal::FakeBluetoothAvInterface::TestA2dpSinkHandler {
31 public:
32 MockA2dpSinkHandler() = default;
33 ~MockA2dpSinkHandler() override = default;
34
35 MOCK_METHOD1(Connect, bt_status_t(RawAddress));
36 MOCK_METHOD1(Disconnect, bt_status_t(RawAddress));
37 MOCK_METHOD1(SetAudioFocusState, void(int));
38 MOCK_METHOD1(SetAudioTrackGain, void(float));
39
40 private:
41 DISALLOW_COPY_AND_ASSIGN(MockA2dpSinkHandler);
42 };
43
44 class TestDelegate : public A2dpSink::Delegate {
45 public:
46 TestDelegate() = default;
47 ~TestDelegate() override = default;
48
49 struct RequestData {
50 std::string device_address;
51 int state = -1;
52 uint32_t sample_rate = 0;
53 uint8_t channel_count = 0;
54 int count = 0;
55 };
56
57 // A2dpSink::Delegate implementation:
OnConnectionState(const std::string & device_address,int state)58 void OnConnectionState(const std::string& device_address,
59 int state) override {
60 ++connection_state_.count;
61 connection_state_.device_address = device_address;
62 connection_state_.state = state;
63 }
OnAudioState(const std::string & device_address,int state)64 void OnAudioState(const std::string& device_address, int state) override {
65 ++audio_state_.count;
66 audio_state_.device_address = device_address;
67 audio_state_.state = state;
68 }
OnAudioConfig(const std::string & device_address,uint32_t sample_rate,uint8_t channel_count)69 void OnAudioConfig(const std::string& device_address, uint32_t sample_rate,
70 uint8_t channel_count) override {
71 ++audio_config_.count;
72 audio_config_.device_address = device_address;
73 audio_config_.sample_rate = sample_rate;
74 audio_config_.channel_count = channel_count;
75 }
76
connection_state() const77 const RequestData& connection_state() const { return connection_state_; }
audio_state() const78 const RequestData& audio_state() const { return audio_state_; }
audio_config() const79 const RequestData& audio_config() const { return audio_config_; }
80
81 private:
82 RequestData connection_state_;
83 RequestData audio_state_;
84 RequestData audio_config_;
85 };
86
87 class A2dpSinkTest : public ::testing::Test {
88 public:
89 A2dpSinkTest() = default;
90 ~A2dpSinkTest() override = default;
91
SetUp()92 void SetUp() override {
93 mock_handler_.reset(new MockA2dpSinkHandler());
94 fake_hal_av_iface_ = new hal::FakeBluetoothAvInterface(mock_handler_);
95 hal::BluetoothAvInterface::InitializeForTesting(fake_hal_av_iface_);
96 factory_.reset(new A2dpSinkFactory());
97 }
98
TearDown()99 void TearDown() override {
100 factory_.reset();
101 hal::BluetoothAvInterface::CleanUp();
102 }
103
104 protected:
105 hal::FakeBluetoothAvInterface* fake_hal_av_iface_;
106 std::shared_ptr<MockA2dpSinkHandler> mock_handler_;
107 std::unique_ptr<A2dpSinkFactory> factory_;
108
109 private:
110 DISALLOW_COPY_AND_ASSIGN(A2dpSinkTest);
111 };
112
113 class A2dpSinkPostRegisterTest : public A2dpSinkTest {
114 public:
115 A2dpSinkPostRegisterTest() = default;
116 ~A2dpSinkPostRegisterTest() override = default;
117
SetUp()118 void SetUp() override {
119 A2dpSinkTest::SetUp();
120 Uuid uuid = Uuid::GetRandom();
121 auto callback = [&](BLEStatus status, const Uuid& in_uuid,
122 std::unique_ptr<BluetoothInstance> in_client) {
123 CHECK(in_uuid == uuid);
124 CHECK(in_client.get());
125 CHECK(status == BLE_STATUS_SUCCESS);
126
127 a2dp_sink_ = std::unique_ptr<A2dpSink>(
128 static_cast<A2dpSink*>(in_client.release()));
129 };
130
131 factory_->RegisterInstance(uuid, callback);
132 }
133
TearDown()134 void TearDown() override {
135 a2dp_sink_ = nullptr;
136 A2dpSinkTest::TearDown();
137 }
138
139 protected:
Connect(const std::string & addr)140 void Connect(const std::string& addr) {
141 RawAddress hal_addr;
142 ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
143
144 EXPECT_CALL(*mock_handler_, Connect(hal_addr))
145 .WillOnce(Return(BT_STATUS_SUCCESS));
146
147 EXPECT_TRUE(a2dp_sink_->Connect(addr));
148 }
149
Disconnect(const std::string & addr)150 void Disconnect(const std::string& addr) {
151 RawAddress hal_addr;
152 ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
153
154 EXPECT_CALL(*mock_handler_, Disconnect(hal_addr))
155 .WillOnce(Return(BT_STATUS_SUCCESS));
156
157 EXPECT_TRUE(a2dp_sink_->Disconnect(addr));
158 }
159
160 std::unique_ptr<A2dpSink> a2dp_sink_;
161
162 private:
163 DISALLOW_COPY_AND_ASSIGN(A2dpSinkPostRegisterTest);
164 };
165
TEST_F(A2dpSinkTest,RegisterA2dpSink)166 TEST_F(A2dpSinkTest, RegisterA2dpSink) {
167 // These will be asynchronously populate with a result when the callback
168 // executes.
169 BLEStatus status = BLE_STATUS_SUCCESS;
170 Uuid cb_uuid;
171 std::unique_ptr<A2dpSink> a2dp_sink;
172 int callback_count = 0;
173
174 auto callback = [&](BLEStatus in_status, const Uuid& uuid,
175 std::unique_ptr<BluetoothInstance> in_a2dp_sink) {
176 status = in_status;
177 cb_uuid = uuid;
178 a2dp_sink = std::unique_ptr<A2dpSink>(
179 static_cast<A2dpSink*>(in_a2dp_sink.release()));
180 callback_count++;
181 };
182
183 Uuid uuid0 = Uuid::GetRandom();
184
185 // This should always succeed.
186 EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
187 EXPECT_EQ(1, callback_count);
188
189 testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
190
191 ASSERT_TRUE(a2dp_sink.get() !=
192 nullptr); // Assert to terminate in case of error
193 EXPECT_EQ(BLE_STATUS_SUCCESS, status);
194 EXPECT_EQ(bluetooth::A2dpSink::kSingletonInstanceId,
195 a2dp_sink->GetInstanceId());
196 EXPECT_EQ(uuid0, a2dp_sink->GetAppIdentifier());
197 EXPECT_EQ(uuid0, cb_uuid);
198
199 testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
200 }
201
TEST_F(A2dpSinkPostRegisterTest,Connect)202 TEST_F(A2dpSinkPostRegisterTest, Connect) {
203 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
204 Connect(kTestAddr);
205 Disconnect(kTestAddr);
206 }
207
TEST_F(A2dpSinkPostRegisterTest,SetAudioFocusState)208 TEST_F(A2dpSinkPostRegisterTest, SetAudioFocusState) {
209 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
210 static const int kFocusState = 2;
211 Connect(kTestAddr);
212
213 EXPECT_CALL(*mock_handler_, SetAudioFocusState(kFocusState));
214 a2dp_sink_->SetAudioFocusState(kFocusState);
215
216 Disconnect(kTestAddr);
217 }
218
TEST_F(A2dpSinkPostRegisterTest,SetAudioTrackGain)219 TEST_F(A2dpSinkPostRegisterTest, SetAudioTrackGain) {
220 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
221 static const float kTrackGain = 0.5;
222 Connect(kTestAddr);
223
224 EXPECT_CALL(*mock_handler_, SetAudioTrackGain(kTrackGain));
225 a2dp_sink_->SetAudioTrackGain(kTrackGain);
226
227 Disconnect(kTestAddr);
228 }
229
TEST_F(A2dpSinkPostRegisterTest,CallbackTest)230 TEST_F(A2dpSinkPostRegisterTest, CallbackTest) {
231 static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
232 RawAddress hal_addr;
233 ASSERT_TRUE(RawAddress::FromString(kTestAddr, hal_addr));
234
235 TestDelegate delegate;
236 a2dp_sink_->SetDelegate(&delegate);
237 Connect(kTestAddr);
238
239 // OnConnectionState
240 const int kConnectionState = 2;
241 EXPECT_EQ(0, delegate.connection_state().count);
242 fake_hal_av_iface_->NotifyConnectionState(
243 hal_addr, static_cast<btav_connection_state_t>(kConnectionState));
244 EXPECT_EQ(1, delegate.connection_state().count);
245 EXPECT_EQ(kTestAddr, delegate.connection_state().device_address);
246 EXPECT_EQ(kConnectionState, delegate.connection_state().state);
247
248 // OnAudioState
249 const int kAudioState = 1;
250 EXPECT_EQ(0, delegate.audio_state().count);
251 fake_hal_av_iface_->NotifyAudioState(
252 hal_addr, static_cast<btav_audio_state_t>(kAudioState));
253 EXPECT_EQ(1, delegate.audio_state().count);
254 EXPECT_EQ(kTestAddr, delegate.audio_state().device_address);
255 EXPECT_EQ(kAudioState, delegate.audio_state().state);
256
257 // OnAudioConfig
258 const uint32_t kSampleRate = 44100;
259 const uint32_t kChannelCount = 2;
260 EXPECT_EQ(0, delegate.audio_config().count);
261 fake_hal_av_iface_->NotifyAudioConfig(hal_addr, kSampleRate, kChannelCount);
262 EXPECT_EQ(1, delegate.audio_config().count);
263 EXPECT_EQ(kTestAddr, delegate.audio_config().device_address);
264 EXPECT_EQ(kSampleRate, delegate.audio_config().sample_rate);
265 EXPECT_EQ(kChannelCount, delegate.audio_config().channel_count);
266
267 Disconnect(kTestAddr);
268 }
269
270 } // namespace
271 } // namespace bluetooth
272