1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import logging 16import time 17 18 19from mobly.controllers import android_device 20from mbs_utils import constants 21 22""" This exception may be expanded in the future to provide better error discoverability.""" 23class CallUtilsError(Exception): 24 pass 25 26class CallUtils: 27 """Calling sequence utility for BT calling test using Spectatio UI APIs. 28 29 This class provides functions that execute generic call sequences. Specific 30 methods 31 (e.g., verify_precall_state) are left to that implementation, and thus the 32 utilities housed here are meant to describe generic sequences of actions. 33 34 """ 35 36 def __init__(self, device): 37 self.device = device 38 39 def dial_a_number(self, callee_number): 40 """ Dial phone number """ 41 logging.info('Dial phone number <%s>', callee_number) 42 self.device.mbs.dialANumber(callee_number) 43 44 45 def end_call(self): 46 """ End the call. Throws an error if non call is currently ongoing. """ 47 logging.info('End the call') 48 self.device.mbs.endCall() 49 50 51 def execute_shell_on_device(self, device_target, shell_command): 52 """Execute any shell command on any device""" 53 logging.info( 54 'Executing shell command: <%s> on device <%s>', 55 shell_command, 56 device_target.serial, 57 ) 58 device_target.adb.shell(shell_command) 59 60 61 def get_dialing_number(self): 62 """ Get dialing phone number""" 63 return self.device.mbs.getDialedNumber() 64 65 def get_home_address_from_details(self): 66 """Return the home address of the contact whose details are currently being displayed""" 67 return self.device.mbs.getHomeAddress() 68 69 def get_device_summary(self): 70 """Assumes the device summary page is open.""" 71 return self.device.mbs.getDeviceSummary() 72 73 def import_contacts_from_vcf_file(self, device_target): 74 """ Importing contacts from VCF file""" 75 logging.info('Importing contacts from VCF file to device Contacts') 76 self.execute_shell_on_device( 77 device_target, 78 constants.IMPOST_CONTACTS_SHELL_COMAND, 79 ) 80 81 def make_call(self): 82 """ Make call""" 83 logging.info('Make a call') 84 self.device.mbs.makeCall() 85 86 def open_call_history(self): 87 """ Open call history """ 88 logging.info('Open call history') 89 self.device.mbs.openCallHistory() 90 91 def open_contacts(self): 92 """Open contacts""" 93 logging.info('Opening contacts') 94 self.device.mbs.openContacts() 95 96 def open_phone_app(self): 97 logging.info('Opening phone app') 98 self.device.mbs.openPhoneApp() 99 100 def open_first_contact_details(self): 101 """Open the contact details page for the first contact visible in the contact list. 102 Assumes we are on the contacts page. """ 103 logging.info('Getting details for first contact on the page') 104 self.device.mbs.openFirstContactDetails() 105 106 def open_bluetooth_settings(self): 107 """Assumes we are on the home screen. 108 Navigate to the Bluetooth setting page""" 109 logging.info("Pressing the bluetooth indicator icon in the status bar.") 110 self.device.mbs.openBluetoothSettings() 111 112 def press_bluetooth_toggle_on_device(self, device_name): 113 logging.info('Attempting to press the bluetooth toggle on device: ' + device_name) 114 self.device.mbs.pressBluetoothToggleOnDevice(device_name) 115 116 def press_device_entry_on_list_of_paired_devices(self, device_name): 117 logging.info('Attempting to press the device entry on device: ' + device_name) 118 self.device.mbs.pressDeviceName(device_name) 119 120 def device_displays_connected(self): 121 """Assumes the device bluetooth connection settings page is open""" 122 logging.info('Checking whether device is connected.') 123 self.device.mbs.deviceIsConnected() 124 125 def press_forget(self): 126 """Assumes the device bluetooth connection settings page is open""" 127 logging.info('Attempting to press \'Forget\'') 128 self.device.mbs.pressForget() 129 130 131 def press_home_screen_on_status_bar(self): 132 """Presses the Home screen button on the status bar 133 (to return the device to the home screen.""" 134 logging.info("Pressing home screen button") 135 self.device.mbs.pressHomeScreen() 136 137 def press_home(self): 138 """ Press the Home button to go back to the home page.""" 139 logging.info("Pressing HOME ") 140 self.device.mbs.pressHome(); 141 142 def press_enter_on_device(self, device_target): 143 """Press ENTER on device""" 144 logging.info('Pressing ENTER on device: ') 145 self.execute_shell_on_device(device_target, 'input keyevent KEYCODE_ENTER') 146 self.wait_with_log(constants.ONE_SEC) 147 148 def push_vcf_contacts_to_device(self, device_target, path_to_contacts_file): 149 """Pushing contacts file to device using adb command""" 150 logging.info( 151 'Pushing VCF contacts to device %s to destination <%s>', 152 device_target.serial, 153 constants.PHONE_CONTACTS_DESTINATION_PATH, 154 ) 155 device_target.adb.push( 156 [path_to_contacts_file, constants.PHONE_CONTACTS_DESTINATION_PATH], 157 timeout=20, 158 ) 159 160 def upload_vcf_contacts_to_device(self, device_target, path_to_contacts_file): 161 """Upload contacts do device""" 162 self.push_vcf_contacts_to_device(device_target, path_to_contacts_file) 163 self.import_contacts_from_vcf_file(device_target) 164 device_target.mbs.pressDevice() 165 166 def verify_contact_name(self, expected_contact): 167 actual_dialed_contact = self.device.mbs.getContactName() 168 logging.info( 169 'Expected contact name being called: <%s>, Actual: <%s>', 170 expected_contact, 171 actual_dialed_contact, 172 ) 173 if actual_dialed_contact != expected_contact: 174 raise CallUtilsError( 175 "Actual and Expected contacts on dial pad don't match." 176 ) 177 178 def wait_with_log(self, wait_time): 179 """ Wait for specific time for debugging""" 180 logging.info('Sleep for %s seconds', wait_time) 181 time.sleep(wait_time) 182 183 def open_bluetooth_media_app(self): 184 """ Open Bluetooth Audio app """ 185 logging.info('Open Bluetooth Audio app') 186 self.device.mbs.openMediaApp(); 187 self.wait_with_log(constants.WAIT_ONE_SEC) 188 189 190 def open_bluetooth_palette(self): 191 logging.info('Open Bluetooth Palette') 192 self.device.mbs.openBluetoothPalette() 193 194 def click_bluetooth_button(self): 195 logging.info('Click Bluetooth Button') 196 self.device.mbs.clickBluetoothButton() 197 198 def is_bluetooth_connected(self): 199 logging.info('Bluetooth Connected Status') 200 is_connected = self.device.mbs.isBluetoothConnected() 201 return is_connected 202 203 def is_bluetooth_audio_disconnected_label_visible(self): 204 """ Return is <Bluetooth Audio disconnected> label present """ 205 logging.info('Checking is <Bluetooth Audio disconnected> label present') 206 actual_disconnected_label_status = self.device.mbs.isBluetoothAudioDisconnectedLabelVisible() 207 logging.info('<Bluetooth Audio disconnected> label is present: %s', 208 actual_disconnected_label_status) 209 return actual_disconnected_label_status 210