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 #undef LOG_TAG // Undefine the LOG_TAG by this compilation unit
18 #include "btif/src/btif_rc.cc"
19
20 #include <bluetooth/log.h>
21 #include <gtest/gtest.h>
22
23 #include <cstdint>
24 #include <future>
25
26 #include "bta/include/bta_av_api.h"
27 #include "btif/avrcp/avrcp_service.h"
28 #include "btif/include/btif_common.h"
29 #include "common/message_loop_thread.h"
30 #include "device/include/interop.h"
31 #include "include/hardware/bt_rc.h"
32 #include "test/common/mock_functions.h"
33 #include "test/mock/mock_osi_alarm.h"
34 #include "test/mock/mock_osi_allocator.h"
35 #include "test/mock/mock_osi_list.h"
36 #include "types/raw_address.h"
37
38 namespace bluetooth {
39 namespace avrcp {
40 int VolChanged = 0;
41 AvrcpService* AvrcpService::instance_ = nullptr;
42
SendMediaUpdate(bool track_changed,bool play_state,bool queue)43 void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
44 bool queue){};
SendFolderUpdate(bool available_players,bool addressed_players,bool uids)45 void AvrcpService::SendFolderUpdate(bool available_players,
46 bool addressed_players, bool uids){};
SendActiveDeviceChanged(const RawAddress & address)47 void AvrcpService::SendActiveDeviceChanged(const RawAddress& address){};
SendPlayerSettingsChanged(std::vector<PlayerAttribute> attributes,std::vector<uint8_t> values)48 void AvrcpService::SendPlayerSettingsChanged(
49 std::vector<PlayerAttribute> attributes, std::vector<uint8_t> values){};
Init(MediaInterface * media_interface,VolumeInterface * volume_interface,PlayerSettingsInterface * player_settings_interface)50 void AvrcpService::ServiceInterfaceImpl::Init(
51 MediaInterface* media_interface, VolumeInterface* volume_interface,
52 PlayerSettingsInterface* player_settings_interface){};
RegisterBipServer(int psm)53 void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int psm){};
UnregisterBipServer()54 void AvrcpService::ServiceInterfaceImpl::UnregisterBipServer(){};
ConnectDevice(const RawAddress & bdaddr)55 bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
56 const RawAddress& bdaddr) {
57 return true;
58 };
DisconnectDevice(const RawAddress & bdaddr)59 bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
60 const RawAddress& bdaddr) {
61 return true;
62 };
SetBipClientStatus(const RawAddress & bdaddr,bool connected)63 void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(
64 const RawAddress& bdaddr, bool connected){};
Cleanup()65 bool AvrcpService::ServiceInterfaceImpl::Cleanup() { return true; };
66
Get()67 AvrcpService* AvrcpService::Get() {
68 EXPECT_EQ(instance_, nullptr);
69 instance_ = new AvrcpService();
70 return instance_;
71 }
72
RegisterVolChanged(const RawAddress & bdaddr)73 void AvrcpService::RegisterVolChanged(const RawAddress& bdaddr) {
74 VolChanged++;
75 }
76 } // namespace avrcp
77 } // namespace bluetooth
78
79 namespace {
80 const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
81 const uint8_t kRcHandle = 123;
82 } // namespace
83
btif_av_clear_remote_suspend_flag(const A2dpType local_a2dp_type)84 void btif_av_clear_remote_suspend_flag(const A2dpType local_a2dp_type) {}
btif_av_is_connected(const A2dpType local_a2dp_type)85 bool btif_av_is_connected(const A2dpType local_a2dp_type) { return true; }
btif_av_is_sink_enabled(void)86 bool btif_av_is_sink_enabled(void) { return true; }
btif_av_sink_active_peer(void)87 RawAddress btif_av_sink_active_peer(void) { return RawAddress(); }
btif_av_source_active_peer(void)88 RawAddress btif_av_source_active_peer(void) { return RawAddress(); }
btif_av_stream_started_ready(const A2dpType local_a2dp_type)89 bool btif_av_stream_started_ready(const A2dpType local_a2dp_type) {
90 return false;
91 }
btif_transfer_context(tBTIF_CBACK * p_cback,uint16_t event,char * p_params,int param_len,tBTIF_COPY_CBACK * p_copy_cback)92 bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
93 char* p_params, int param_len,
94 tBTIF_COPY_CBACK* p_copy_cback) {
95 return BT_STATUS_SUCCESS;
96 }
btif_av_src_sink_coexist_enabled()97 bool btif_av_src_sink_coexist_enabled() { return true; }
btif_av_is_connected_addr(const RawAddress & peer_address,const A2dpType local_a2dp_type)98 bool btif_av_is_connected_addr(const RawAddress& peer_address,
99 const A2dpType local_a2dp_type) {
100 return true;
101 }
btif_av_peer_is_connected_sink(const RawAddress & peer_address)102 bool btif_av_peer_is_connected_sink(const RawAddress& peer_address) {
103 return false;
104 }
btif_av_peer_is_connected_source(const RawAddress & peer_address)105 bool btif_av_peer_is_connected_source(const RawAddress& peer_address) {
106 return true;
107 }
btif_av_peer_is_sink(const RawAddress & peer_address)108 bool btif_av_peer_is_sink(const RawAddress& peer_address) { return false; }
btif_av_peer_is_source(const RawAddress & peer_address)109 bool btif_av_peer_is_source(const RawAddress& peer_address) { return true; }
btif_av_both_enable(void)110 bool btif_av_both_enable(void) { return true; }
111
112 static bluetooth::common::MessageLoopThread jni_thread("bt_jni_thread");
do_in_jni_thread(base::OnceClosure task)113 bt_status_t do_in_jni_thread(base::OnceClosure task) {
114 if (!jni_thread.DoInThread(FROM_HERE, std::move(task))) {
115 log::error("Post task to task runner failed!");
116 return BT_STATUS_JNI_THREAD_ATTACH_ERROR;
117 }
118 return BT_STATUS_SUCCESS;
119 }
get_main_thread()120 bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; }
interop_match_addr(const interop_feature_t feature,const RawAddress * addr)121 bool interop_match_addr(const interop_feature_t feature,
122 const RawAddress* addr) {
123 return false;
124 }
125
126 /**
127 * Test class to test selected functionality in hci/src/hci_layer.cc
128 */
129 class BtifRcTest : public ::testing::Test {
130 protected:
SetUp()131 void SetUp() override { reset_mock_function_count_map(); }
TearDown()132 void TearDown() override {}
133 };
134
TEST_F(BtifRcTest,get_element_attr_rsp)135 TEST_F(BtifRcTest, get_element_attr_rsp) {
136 btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
137 btif_rc_cb.rc_multi_cb[0].rc_connected = true;
138 btif_rc_cb.rc_multi_cb[0]
139 .rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP]
140 .is_rsp_pending = true;
141 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
142
143 btrc_element_attr_val_t p_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
144 uint8_t num_attr = BTRC_MAX_ELEM_ATTR_SIZE + 1;
145
146 ASSERT_EQ(get_element_attr_rsp(kDeviceAddress, num_attr, p_attrs),
147 BT_STATUS_SUCCESS);
148 ASSERT_EQ(1, get_func_call_count("AVRC_BldResponse"));
149 }
150
TEST_F(BtifRcTest,btif_rc_get_addr_by_handle)151 TEST_F(BtifRcTest, btif_rc_get_addr_by_handle) {
152 RawAddress bd_addr;
153
154 btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
155 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
156 btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
157
158 btif_rc_get_addr_by_handle(0, bd_addr);
159 ASSERT_EQ(kDeviceAddress, bd_addr);
160 }
161
162 static btrc_ctrl_callbacks_t default_btrc_ctrl_callbacks = {
163 .size = sizeof(btrc_ctrl_callbacks_t),
164 .passthrough_rsp_cb = [](const RawAddress& /* bd_addr */, int /* id */,
__anoneceeb2bd0202() 165 int /* key_state */) { FAIL(); },
__anoneceeb2bd0302() 166 .groupnavigation_rsp_cb = [](int /* id */, int /* key_state */) { FAIL(); },
167 .connection_state_cb = [](bool /* rc_connect */, bool /* bt_connect */,
__anoneceeb2bd0402() 168 const RawAddress& /* bd_addr */) { FAIL(); },
169 .getrcfeatures_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0502() 170 int /* features */) { FAIL(); },
171 .setplayerappsetting_rsp_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0602() 172 uint8_t /* accepted */) { FAIL(); },
173 .playerapplicationsetting_cb =
174 [](const RawAddress& /* bd_addr */, uint8_t /* num_attr */,
175 btrc_player_app_attr_t* /* app_attrs */, uint8_t /* num_ext_attr */,
__anoneceeb2bd0702() 176 btrc_player_app_ext_attr_t* /* ext_attrs */) { FAIL(); },
177 .playerapplicationsetting_changed_cb =
178 [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0802() 179 const btrc_player_settings_t& /* vals */) { FAIL(); },
180 .setabsvol_cmd_cb = [](const RawAddress& /* bd_addr */,
181 uint8_t /* abs_vol */,
__anoneceeb2bd0902() 182 uint8_t /* label */) { FAIL(); },
183 .registernotification_absvol_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0a02() 184 uint8_t /* label */) { FAIL(); },
185 .track_changed_cb = [](const RawAddress& /* bd_addr */,
186 uint8_t /* num_attr */,
__anoneceeb2bd0b02() 187 btrc_element_attr_val_t* /* p_attrs */) { FAIL(); },
188 .play_position_changed_cb = [](const RawAddress& /* bd_addr */,
189 uint32_t /* song_len */,
__anoneceeb2bd0c02() 190 uint32_t /* song_pos */) { FAIL(); },
191 .play_status_changed_cb =
192 [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0d02() 193 btrc_play_status_t /* play_status */) { FAIL(); },
194 .get_folder_items_cb = [](const RawAddress& /* bd_addr */,
195 btrc_status_t /* status */,
196 const btrc_folder_items_t* /* folder_items */,
__anoneceeb2bd0e02() 197 uint8_t /* count */) { FAIL(); },
198 .change_folder_path_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd0f02() 199 uint32_t /* count */) { FAIL(); },
200 .set_browsed_player_cb = [](const RawAddress& /* bd_addr */,
201 uint8_t /* num_items */,
__anoneceeb2bd1002() 202 uint8_t /* depth */) { FAIL(); },
203 .set_addressed_player_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd1102() 204 uint8_t /* status */) { FAIL(); },
205 .addressed_player_changed_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd1202() 206 uint16_t /* id */) { FAIL(); },
207 .now_playing_contents_changed_cb =
__anoneceeb2bd1302() 208 [](const RawAddress& /* bd_addr */) { FAIL(); },
209 .available_player_changed_cb =
__anoneceeb2bd1402() 210 [](const RawAddress& /* bd_addr */) { FAIL(); },
211 .get_cover_art_psm_cb = [](const RawAddress& /* bd_addr */,
__anoneceeb2bd1502() 212 const uint16_t /* psm */) { FAIL(); },
213 };
214 static btrc_ctrl_callbacks_t btrc_ctrl_callbacks = default_btrc_ctrl_callbacks;
215
216 struct rc_connection_state_cb_t {
217 bool rc_state;
218 bool bt_state;
219 RawAddress raw_address;
220 };
221
222 struct rc_feature_cb_t {
223 int feature;
224 RawAddress raw_address;
225 };
226
227 static std::promise<rc_connection_state_cb_t> g_btrc_connection_state_promise;
228 static std::promise<rc_feature_cb_t> g_btrc_feature;
229
230 class BtifRcWithCallbacksTest : public BtifRcTest {
231 protected:
SetUp()232 void SetUp() override {
233 BtifRcTest::SetUp();
234 btrc_ctrl_callbacks = default_btrc_ctrl_callbacks;
235 init_ctrl(&btrc_ctrl_callbacks);
236 jni_thread.StartUp();
237 btrc_ctrl_callbacks.getrcfeatures_cb = [](const RawAddress& bd_addr,
238 int features) {
239 rc_feature_cb_t rc_feature = {
240 .feature = features,
241 .raw_address = bd_addr,
242 };
243 g_btrc_feature.set_value(rc_feature);
244 };
245 }
246
TearDown()247 void TearDown() override {
248 jni_thread.ShutDown();
249 bt_rc_ctrl_callbacks->getrcfeatures_cb = [](const RawAddress& bd_addr,
250 int features) {};
251 btrc_ctrl_callbacks = default_btrc_ctrl_callbacks;
252 BtifRcTest::TearDown();
253 }
254 };
255
TEST_F(BtifRcWithCallbacksTest,handle_rc_ctrl_features)256 TEST_F(BtifRcWithCallbacksTest, handle_rc_ctrl_features) {
257 g_btrc_feature = std::promise<rc_feature_cb_t>();
258 std::future<rc_feature_cb_t> future = g_btrc_feature.get_future();
259 btif_rc_device_cb_t p_dev;
260
261 p_dev.peer_tg_features =
262 (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCCT |
263 BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_BROWSE |
264 BTA_AV_FEAT_COVER_ARTWORK);
265 p_dev.rc_connected = true;
266
267 handle_rc_ctrl_features(&p_dev);
268 ASSERT_EQ(1, get_func_call_count("AVRC_BldCommand"));
269
270 ASSERT_EQ(std::future_status::ready,
271 future.wait_for(std::chrono::seconds(2)));
272 auto res = future.get();
273 log::info("FEATURES:{}", res.feature);
274 ASSERT_EQ(res.feature, (BTRC_FEAT_ABSOLUTE_VOLUME | BTRC_FEAT_METADATA |
275 BTRC_FEAT_BROWSE | BTRC_FEAT_COVER_ARTWORK));
276 }
277
278 class BtifRcBrowseConnectionTest : public BtifRcTest {
279 protected:
SetUp()280 void SetUp() override {
281 BtifRcTest::SetUp();
282 init_ctrl(&btrc_ctrl_callbacks);
283 jni_thread.StartUp();
284 btrc_ctrl_callbacks.connection_state_cb = [](bool rc_state, bool bt_state,
285 const RawAddress& bd_addr) {
286 rc_connection_state_cb_t rc_connection_state = {
287 .rc_state = rc_state,
288 .bt_state = bt_state,
289 .raw_address = bd_addr,
290 };
291 g_btrc_connection_state_promise.set_value(rc_connection_state);
292 };
293 }
294
TearDown()295 void TearDown() override {
296 jni_thread.ShutDown();
297 bt_rc_ctrl_callbacks->connection_state_cb =
298 [](bool rc_state, bool bt_state, const RawAddress& bd_addr) {};
299 BtifRcTest::TearDown();
300 }
301 };
302
TEST_F(BtifRcBrowseConnectionTest,handle_rc_browse_connect)303 TEST_F(BtifRcBrowseConnectionTest, handle_rc_browse_connect) {
304 g_btrc_connection_state_promise = std::promise<rc_connection_state_cb_t>();
305 std::future<rc_connection_state_cb_t> future =
306 g_btrc_connection_state_promise.get_future();
307
308 tBTA_AV_RC_BROWSE_OPEN browse_data = {
309 .rc_handle = 0,
310 .peer_addr = {},
311 .status = BTA_AV_SUCCESS,
312 };
313
314 btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
315 btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty;
316 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
317 btif_rc_cb.rc_multi_cb[0].rc_connected = false;
318
319 /* process unit test handle_rc_browse_connect */
320 handle_rc_browse_connect(&browse_data);
321 ASSERT_EQ(std::future_status::ready,
322 future.wait_for(std::chrono::seconds(2)));
323 auto res = future.get();
324 ASSERT_TRUE(res.bt_state);
325 }
326
327 class BtifRcConnectionTest : public BtifRcTest {
328 protected:
SetUp()329 void SetUp() override {
330 BtifRcTest::SetUp();
331 init_ctrl(&btrc_ctrl_callbacks);
332 jni_thread.StartUp();
333 g_btrc_connection_state_promise = std::promise<rc_connection_state_cb_t>();
334 g_btrc_connection_state_future =
335 g_btrc_connection_state_promise.get_future();
336 btrc_ctrl_callbacks.connection_state_cb = [](bool rc_state, bool bt_state,
337 const RawAddress& bd_addr) {
338 rc_connection_state_cb_t rc_connection_state = {
339 .rc_state = rc_state,
340 .bt_state = bt_state,
341 .raw_address = bd_addr,
342 };
343 g_btrc_connection_state_promise.set_value(rc_connection_state);
344 };
345 }
346
TearDown()347 void TearDown() override {
348 jni_thread.ShutDown();
349 bt_rc_ctrl_callbacks->connection_state_cb =
350 [](bool rc_state, bool bt_state, const RawAddress& bd_addr) {};
351 BtifRcTest::TearDown();
352 }
353 std::future<rc_connection_state_cb_t> g_btrc_connection_state_future;
354 };
355
TEST_F(BtifRcConnectionTest,btif_rc_connection_test)356 TEST_F(BtifRcConnectionTest, btif_rc_connection_test) {}
357
TEST_F(BtifRcConnectionTest,handle_rc_browse_connect)358 TEST_F(BtifRcConnectionTest, handle_rc_browse_connect) {
359 tBTA_AV_RC_BROWSE_OPEN browse_data = {
360 .rc_handle = 0,
361 .peer_addr = {},
362 .status = BTA_AV_SUCCESS,
363 };
364
365 btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
366 btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty;
367 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
368 btif_rc_cb.rc_multi_cb[0].rc_connected = false;
369
370 /* process unit test handle_rc_browse_connect */
371 handle_rc_browse_connect(&browse_data);
372 ASSERT_EQ(std::future_status::ready,
373 g_btrc_connection_state_future.wait_for(std::chrono::seconds(2)));
374 auto res = g_btrc_connection_state_future.get();
375 ASSERT_TRUE(res.bt_state);
376 }
377
TEST_F(BtifRcConnectionTest,btif_rc_check_pending_cmd)378 TEST_F(BtifRcConnectionTest, btif_rc_check_pending_cmd) {
379 btif_rc_cb.rc_multi_cb[0].rc_handle = 0xff;
380 btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
381 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
382 btif_rc_cb.rc_multi_cb[0].rc_connected = true;
383 btif_rc_cb.rc_multi_cb[0].launch_cmd_pending |=
384 (RC_PENDING_ACT_REG_VOL | RC_PENDING_ACT_GET_CAP |
385 RC_PENDING_ACT_REPORT_CONN);
386
387 btif_rc_check_pending_cmd(kDeviceAddress);
388 ASSERT_EQ(1, get_func_call_count("AVRC_BldCommand"));
389
390 ASSERT_EQ(std::future_status::ready,
391 g_btrc_connection_state_future.wait_for(std::chrono::seconds(3)));
392 auto res = g_btrc_connection_state_future.get();
393 ASSERT_TRUE(res.rc_state);
394 }
395
TEST_F(BtifRcConnectionTest,bt_av_rc_open_evt)396 TEST_F(BtifRcConnectionTest, bt_av_rc_open_evt) {
397 btrc_ctrl_callbacks.get_cover_art_psm_cb = [](const RawAddress& /* bd_addr */,
398 const uint16_t /* psm */) {};
399 btrc_ctrl_callbacks.getrcfeatures_cb = [](const RawAddress& /* bd_addr */,
400 int /* features */) {};
401
402 /* handle_rc_connect */
403 tBTA_AV data = {
404 .rc_open =
405 {
406 .rc_handle = 0,
407 .cover_art_psm = 0,
408 .peer_features = 0,
409 .peer_ct_features = 0,
410 .peer_tg_features = (BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
411 BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT),
412 .peer_addr = kDeviceAddress,
413 .status = BTA_AV_SUCCESS,
414 },
415 };
416 btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
417 btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty;
418 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
419 btif_rc_cb.rc_multi_cb[0].rc_connected = false;
420
421 btif_rc_handler(BTA_AV_RC_OPEN_EVT, &data);
422
423 ASSERT_TRUE(btif_rc_cb.rc_multi_cb[data.rc_open.rc_handle].rc_connected);
424 ASSERT_EQ(btif_rc_cb.rc_multi_cb[data.rc_open.rc_handle].rc_state,
425 BTRC_CONNECTION_STATE_CONNECTED);
426
427 ASSERT_EQ(std::future_status::ready,
428 g_btrc_connection_state_future.wait_for(std::chrono::seconds(2)));
429 auto res = g_btrc_connection_state_future.get();
430 ASSERT_TRUE(res.rc_state);
431 }
432
433 class BtifTrackChangeCBTest : public BtifRcTest {
434 protected:
SetUp()435 void SetUp() override {
436 BtifRcTest::SetUp();
437 init_ctrl(&btrc_ctrl_callbacks);
438 jni_thread.StartUp();
439 btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& bd_addr,
440 uint8_t num_attr, btrc_element_attr_val_t* p_attrs) {
441 btif_rc_cb.rc_multi_cb[0].rc_addr = bd_addr;
442 };
443 }
444
TearDown()445 void TearDown() override {
446 jni_thread.ShutDown();
447 btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& bd_addr,
448 uint8_t num_attr, btrc_element_attr_val_t* p_attrs) {};
449 BtifRcTest::TearDown();
450 }
451 };
452
TEST_F(BtifTrackChangeCBTest,handle_get_metadata_attr_response)453 TEST_F(BtifTrackChangeCBTest, handle_get_metadata_attr_response) {
454 // Setup an already connected device
455 btif_rc_cb.rc_multi_cb[0].rc_connected = true;
456 btif_rc_cb.rc_multi_cb[0].br_connected = false;
457 btif_rc_cb.rc_multi_cb[0].rc_handle = kRcHandle;
458 btif_rc_cb.rc_multi_cb[0].rc_features = {};
459 btif_rc_cb.rc_multi_cb[0].rc_cover_art_psm = 0;
460 btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
461 btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
462 btif_rc_cb.rc_multi_cb[0].rc_pending_play = 0;
463 btif_rc_cb.rc_multi_cb[0].rc_volume = 0;
464 btif_rc_cb.rc_multi_cb[0].rc_vol_label = 0;
465 btif_rc_cb.rc_multi_cb[0].rc_supported_event_list = nullptr;
466 btif_rc_cb.rc_multi_cb[0].rc_app_settings = {};
467 btif_rc_cb.rc_multi_cb[0].rc_play_status_timer = nullptr;
468 btif_rc_cb.rc_multi_cb[0].rc_features_processed = false;
469 btif_rc_cb.rc_multi_cb[0].rc_playing_uid = 0;
470 btif_rc_cb.rc_multi_cb[0].rc_procedure_complete = false;
471 btif_rc_cb.rc_multi_cb[0].peer_ct_features = {};
472 btif_rc_cb.rc_multi_cb[0].peer_tg_features = {};
473 btif_rc_cb.rc_multi_cb[0].launch_cmd_pending = 0;
474 ASSERT_TRUE(btif_rc_get_device_by_handle(kRcHandle));
475
476 tBTA_AV_META_MSG meta_msg = {
477 .rc_handle = kRcHandle,
478 .len = 0,
479 .label = 0,
480 .code{},
481 .company_id = 0,
482 .p_data = {},
483 .p_msg = nullptr,
484 };
485
486 tAVRC_GET_ATTRS_RSP rsp = {
487 .pdu = 0,
488 .status = AVRC_STS_NO_ERROR,
489 .opcode = 0,
490 .num_attrs = 0,
491 .p_attrs = nullptr,
492 };
493
494 handle_get_metadata_attr_response(&meta_msg, &rsp);
495
496 ASSERT_EQ(1, get_func_call_count("osi_free_and_reset"));
497 }
498