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