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