• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""
17Test the HFP profile for calling and connection management.
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.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest
25from acts.test_utils.bt import BtEnum
26from acts.test_utils.bt import bt_test_utils
27from acts.test_utils.car import car_bt_utils
28from acts.test_utils.car import car_telecom_utils
29from acts.test_utils.tel import tel_defines
30from acts.test_utils.tel.tel_test_utils import hangup_call
31from acts.test_utils.tel.tel_test_utils import initiate_call
32from acts.test_utils.tel.tel_test_utils import wait_and_answer_call
33
34BLUETOOTH_PKG_NAME = "com.android.bluetooth"
35CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING"
36CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING"
37default_timeout = 20
38
39
40class BtCarHfpConnectionTest(BluetoothCarHfpBaseTest):
41    def setup_class(self):
42        if not super(BtCarHfpConnectionTest, self).setup_class():
43            return False
44
45        # Disable all
46        car_bt_utils.set_car_profile_priorities_off(self.hf, self.ag)
47
48        # Enable A2DP
49        bt_test_utils.set_profile_priority(
50            self.hf, self.ag, [BtEnum.BluetoothProfile.HEADSET_CLIENT],
51            BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
52
53        return True
54
55    def setup_test(self):
56        if not super(BtCarHfpConnectionTest, self).setup_test():
57            return False
58        self.hf.droid.bluetoothDisconnectConnected(
59            self.ag.droid.bluetoothGetLocalAddress())
60
61    @test_tracker_info(uuid='a6669f9b-fb49-4bd8-aa9c-9d6369e34442')
62    @BluetoothBaseTest.bt_test_wrap
63    def test_call_transfer_disconnect_connect(self):
64        """
65        Tests that after we connect when an active call is in progress,
66        we show the call.
67
68        Precondition:
69        1. AG & HF are disconnected but paired.
70
71        Steps:
72        1. Make a call from AG role (since disconnected)
73        2. Accept from RE role and transition the call to Active
74        3. Connect AG & HF
75        4. HF should transition into Active call state.
76
77        Returns:
78          Pass if True
79          Fail if False
80
81        Priority: 1
82        """
83        # make a call on AG
84        if not initiate_call(self.log, self.ag, self.re_phone_number):
85            self.ag.log.error("Failed to initiate call from ag.")
86            return False
87        if not wait_and_answer_call(self.log, self.re):
88            self.re.log.error("Failed to accept call on re.")
89            return False
90
91        # Wait for AG, RE to go into an Active state.
92        if not car_telecom_utils.wait_for_active(self.log, self.ag):
93            self.ag.log.error("AG not in Active state.")
94            return False
95        if not car_telecom_utils.wait_for_active(self.log, self.re):
96            self.re.log.error("RE not in Active state.")
97            return False
98
99        # Now connect the devices.
100        if not bt_test_utils.connect_pri_to_sec(
101                self.hf, self.ag,
102                set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
103            self.log.error("Could not connect HF and AG {} {}".format(
104                self.hf.serial, self.ag.serial))
105            return False
106
107        # Check that HF is in active state
108        if not car_telecom_utils.wait_for_active(self.log, self.hf):
109            self.hf.log.error("HF not in Active state.")
110            return False
111
112        # Hangup the call and check all devices are clean
113        self.hf.droid.telecomEndCall()
114        ret = True
115        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf)
116        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag)
117        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re)
118
119        return ret
120
121    @test_tracker_info(uuid='97727b64-a590-4d84-a257-1facd8aafd16')
122    @BluetoothBaseTest.bt_test_wrap
123    def test_call_transfer_off_on(self):
124        """
125        Tests that after we turn adapter on when an active call is in
126        progress, we show the call.
127
128        Precondition:
129        1. AG & HF are disconnected but paired.
130        2. HF's adapter is OFF
131
132        Steps:
133        1. Make a call from AG role (since disconnected)
134        2. Accept from RE role and transition the call to Active
135        3. Turn HF's adapter ON
136        4. HF should transition into Active call state.
137
138        Returns:
139          Pass if True
140          Fail if False
141
142        Priority: 1
143        """
144        # Connect HF & AG
145        if not bt_test_utils.connect_pri_to_sec(
146                self.hf, self.ag,
147                set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
148            self.log.error("Could not connect HF and AG {} {}".format(
149                self.hf.serial, self.ag.serial))
150            return False
151
152        # make a call on AG
153        if not initiate_call(self.log, self.ag, self.re_phone_number):
154            self.ag.log.error("Failed to initiate call from ag.")
155            return False
156
157        # Wait for all HF
158        if not car_telecom_utils.wait_for_dialing(self.log, self.hf):
159            self.hf.log.error("HF not in ringing state.")
160            return False
161
162        # Accept the call on RE
163        if not wait_and_answer_call(self.log, self.re):
164            self.re.log.error("Failed to accept call on re.")
165            return False
166        # Wait for all HF, AG, RE to go into an Active state.
167        if not car_telecom_utils.wait_for_active(self.log, self.hf):
168            self.hf.log.error("HF not in Active state.")
169            return False
170        if not car_telecom_utils.wait_for_active(self.log, self.ag):
171            self.ag.log.error("AG not in Active state.")
172            return False
173        if not car_telecom_utils.wait_for_active(self.log, self.re):
174            self.re.log.error("RE not in Active state.")
175            return False
176
177        # Turn the adapter OFF on HF
178        if not bt_test_utils.disable_bluetooth(self.hf.droid):
179            self.hf.log.error("Failed to turn BT off on HF.")
180            return False
181
182        # Turn adapter ON on HF
183        if not bt_test_utils.enable_bluetooth(self.hf.droid, self.hf.ed):
184            self.hf.log.error("Failed to turn BT ON after call on HF.")
185            return False
186
187        # Check that HF is in active state
188        if not car_telecom_utils.wait_for_active(self.log, self.hf):
189            self.hf.log.error("HF not in Active state.")
190            return False
191
192        # Hangup the call and check all devices are clean
193        self.hf.droid.telecomEndCall()
194        ret = True
195        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf)
196        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag)
197        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re)
198
199        return ret
200
201    @test_tracker_info(uuid='95f76e2c-1cdd-4a7c-8e26-863b4c4242be')
202    @BluetoothBaseTest.bt_test_wrap
203    def test_call_transfer_connect_disconnect_connect(self):
204        """
205        Test that when we go from connect -> disconnect -> connect on an active
206        call then the call is restored on HF.
207
208        Precondition:
209        1. AG & HF are paired
210
211        Steps:
212        0. Connect AG & HF
213        1. Make a call from HF role
214        2. Accept from RE role and transition the call to Active
215        3. Disconnect AG & HF
216        4. Verify that we don't have any calls on HF
217        5. Connect AG & HF
218        6. Verify that HF gets the call back.
219
220        Returns:
221          Pass if True
222          Fail if False
223
224        Priority: 1
225        """
226        # Now connect the devices.
227        if not bt_test_utils.connect_pri_to_sec(
228                self.hf, self.ag,
229                set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
230            self.log.error("Could not connect HF and AG {} {}".format(
231                self.hf.serial, self.ag.serial))
232            return False
233
234        # make a call on HF
235        if not car_telecom_utils.dial_number(self.log, self.hf,
236                                             self.re_phone_number):
237            self.hf.log.error("HF not in dialing state.")
238            return False
239
240        # Wait for HF, AG to be dialing and RE to be ringing
241        ret = True
242        ret &= car_telecom_utils.wait_for_dialing(self.log, self.hf)
243        #uncomment once sl4a code has been merged.
244        ret &= car_telecom_utils.wait_for_dialing(self.log, self.ag)
245        ret &= car_telecom_utils.wait_for_ringing(self.log, self.re)
246
247        if not ret:
248            self.log.error("Outgoing call did not get established")
249            return False
250
251        # Accept call on RE.
252        if not wait_and_answer_call(self.log, self.re):
253            self.re.log.error("Failed to accept call on re.")
254            return False
255
256        ret &= car_telecom_utils.wait_for_active(self.log, self.hf)
257        ret &= car_telecom_utils.wait_for_active(self.log, self.ag)
258        ret &= car_telecom_utils.wait_for_active(self.log, self.re)
259
260        if not ret:
261            self.log.error("Outgoing call did not transition to active")
262            return False
263
264        # Disconnect HF & AG
265        self.hf.droid.bluetoothDisconnectConnected(
266            self.ag.droid.bluetoothGetLocalAddress())
267
268        # We use the proxy of the Call going away as HF disconnected
269        if not car_telecom_utils.wait_for_not_in_call(self.log, self.hf):
270            self.hf.log.error("HF still in call after disconnection.")
271            return False
272
273        # Now connect the devices.
274        if not bt_test_utils.connect_pri_to_sec(
275                self.hf, self.ag,
276                set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
277            self.log.error("Could not connect HF and AG {} {}".format(
278                self.hf.serial, self.ag.serial))
279            # Additional profile connection check for b/
280            if not bt_test_utils.is_hfp_client_device_connected(
281                    self.hf, self.ag.droid.bluetoothGetLocalAddress()):
282                self.hf.log.info(
283                    "HFP Client connected even though connection state changed "
284                    + " event not found")
285                return False
286
287        # Check that HF is in active state
288        if not car_telecom_utils.wait_for_active(self.log, self.hf):
289            self.hf.log.error("HF not in Active state.")
290            return False
291
292        # Hangup the call and check all devices are clean
293        self.hf.droid.telecomEndCall()
294        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf)
295        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag)
296        ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re)
297
298        return ret
299