1#!/usr/bin/env python3
2#
3# Copyright (C) 2016 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16"""
17Automated tests for the testing Connectivity of Avrcp/A2dp profile.
18"""
19
20import time
21
22from acts.test_decorators import test_tracker_info
23from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
24from acts.test_utils.bt import bt_test_utils
25from acts.test_utils.car import car_bt_utils
26from acts.test_utils.bt import BtEnum
27from acts.test_utils.bt.bt_test_utils import is_a2dp_connected
28
29
30class BtCarMediaConnectionTest(BluetoothBaseTest):
31    def setup_class(self):
32        # AVRCP roles
33        self.CT = self.android_devices[0]
34        self.TG = self.android_devices[1]
35        # A2DP roles for the same devices
36        self.SNK = self.CT
37        self.SRC = self.TG
38
39        # Setup devices
40        bt_test_utils.setup_multiple_devices_for_bt_test([self.CT, self.TG])
41
42        self.btAddrCT = self.CT.droid.bluetoothGetLocalAddress()
43        self.btAddrTG = self.TG.droid.bluetoothGetLocalAddress()
44
45        # Additional time from the stack reset in setup.
46        time.sleep(4)
47        # Pair the devices.
48        if not bt_test_utils.pair_pri_to_sec(
49                self.CT, self.TG, attempts=4, auto_confirm=False):
50            self.log.error("Failed to pair")
51            return False
52
53        # Disable all
54        car_bt_utils.set_car_profile_priorities_off(self.SNK, self.SRC)
55
56        # Enable A2DP
57        bt_test_utils.set_profile_priority(
58            self.SNK, self.SRC, [BtEnum.BluetoothProfile.A2DP_SINK],
59            BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
60
61    @test_tracker_info(uuid='1934c0d5-3fa3-43e5-a91f-2c8a4424f5cd')
62    @BluetoothBaseTest.bt_test_wrap
63    def test_a2dp_connect_disconnect_from_src(self):
64        """
65        Test Connect/Disconnect on A2DP profile.
66
67        Pre-Condition:
68        1. Devices previously bonded and NOT connected on A2dp
69
70        Steps:
71        1. Initiate a connection on A2DP profile from SRC
72        2. Check if they connected.
73        3. Initiate a disconnect on A2DP profile from SRC
74        4. Ensure they disconnected on A2dp alone
75
76        Returns:
77        True    if we connected/disconnected successfully
78        False   if we did not connect/disconnect successfully
79
80        Priority: 0
81        """
82        if (is_a2dp_connected(self.SNK, self.SRC)):
83            self.log.info("Already Connected")
84        else:
85            if (not bt_test_utils.connect_pri_to_sec(
86                    self.SRC, self.SNK,
87                    set([BtEnum.BluetoothProfile.A2DP.value]))):
88                return False
89        # Delay to establish A2DP connection before disconnecting
90        time.sleep(5)
91        result = bt_test_utils.disconnect_pri_from_sec(
92            self.SRC, self.SNK, [BtEnum.BluetoothProfile.A2DP.value])
93        # Grace timeout to allow a2dp time to disconnect
94        time.sleep(2)
95        if not result:
96            # Additional profile connection check for b/
97            if bt_test_utils.is_a2dp_src_device_connected(
98                    self.SRC, self.SNK.droid.bluetoothGetLocalAddress()):
99                self.SRC.log.error("Failed to disconnect on A2dp")
100                return False
101        # Logging if we connected right back, since that happens sometimes
102        # Not failing the test if it did though
103        if (is_a2dp_connected(self.SNK, self.SRC)):
104            self.SNK.log.error("Still connected after a disconnect")
105
106        return True
107
108    @test_tracker_info(uuid='70d30007-540a-4e86-bd75-ab218774350e')
109    @BluetoothBaseTest.bt_test_wrap
110    def test_a2dp_connect_disconnect_from_snk(self):
111        """
112        Test Connect/Disconnect on A2DP Sink profile.
113
114        Pre-Condition:
115        1. Devices previously bonded and NOT connected on A2dp
116
117        Steps:
118        1. Initiate a connection on A2DP Sink profile from SNK
119        2. Check if they connected.
120        3. Initiate a disconnect on A2DP Sink profile from SNK
121        4. Ensure they disconnected on A2dp alone
122
123        Returns:
124        True    if we connected/disconnected successfully
125        False   if we did not connect/disconnect successfully
126
127        Priority: 0
128        """
129        # Connect
130        if is_a2dp_connected(self.SNK, self.SRC):
131            self.log.info("Already Connected")
132        else:
133            if (not bt_test_utils.connect_pri_to_sec(
134                    self.SNK, self.SRC,
135                    set([BtEnum.BluetoothProfile.A2DP_SINK.value]))):
136                return False
137        # Delay to establish A2DP connection before disconnecting
138        time.sleep(5)
139        # Disconnect
140        result = bt_test_utils.disconnect_pri_from_sec(
141            self.SNK, self.SRC, [BtEnum.BluetoothProfile.A2DP_SINK.value])
142        # Grace timeout to allow a2dp time to disconnect
143        time.sleep(2)
144        if not result:
145            # Additional profile connection check for b/
146            if bt_test_utils.is_a2dp_snk_device_connected(
147                    self.SNK, self.SRC.droid.bluetoothGetLocalAddress()):
148                self.SNK.log.error("Failed to disconnect on A2dp Sink")
149                return False
150        # Logging if we connected right back, since that happens sometimes
151        # Not failing the test if it did though
152        if is_a2dp_connected(self.SNK, self.SRC):
153            self.SNK.log.error("Still connected after a disconnect")
154        return True
155