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 re
17import time
18
19from mobly.controllers import android_device
20from utilities import constants
21
22""" This exception may be expanded in the future to provide better error discoverability."""
23
24
25class CallUtilsError(Exception):
26    pass
27class CallUtils:
28    """Calling sequence utility for BT calling test using Spectatio UI APIs.
29
30    This class provides functions that execute generic call sequences. Specific
31    methods
32    (e.g., verify_precall_state) are left to that implementation, and thus the
33    utilities housed here are meant to describe generic sequences of actions.
34
35    """
36
37    def __init__(self, device):
38        self.device = device
39
40    def device_displays_connected(self):
41        """Assumes the device bluetooth connection settings page is open"""
42        logging.info('Checking whether device is connected.')
43        self.device.mbs.deviceIsConnected()
44    def open_app_grid(self):
45        """Opens app Grid """
46        logging.info("Opening app grid")
47        self.device.mbs.openAppGrid()
48    def dial_a_number(self, callee_number):
49        """Dial phone number"""
50        logging.info("Dial phone number <%s>", callee_number)
51        self.device.mbs.dialANumber(callee_number)
52
53    def end_call(self):
54        """End the call. Throws an error if non call is currently ongoing."""
55        logging.info("End the call")
56        self.device.mbs.endCall()
57
58    def execute_shell_on_device(self, device_target, shell_command):
59        """Execute any shell command on any device"""
60        logging.info(
61            "Executing shell command: <%s> on device <%s>",
62            shell_command,
63            device_target.serial,
64        )
65        return device_target.adb.shell(shell_command)
66
67    def get_dialing_number(self):
68        """Get dialing phone number"""
69        return self.device.mbs.getDialingNumber()
70
71    def get_user_phone_number(self):
72        """Get user phone number"""
73        return self.device.mbs.getUserProfilePhoneNumber()
74
75
76    def get_home_address_from_details(self):
77        """Return the home address of the contact whose details are currently being displayed"""
78        return self.device.mbs.getHomeAddress()
79
80    def get_device_summary(self):
81        """Assumes the device summary page is open."""
82        return self.device.mbs.getDeviceSummary()
83
84    def import_contacts_from_vcf_file(self, device_target):
85        """Importing contacts from VCF file"""
86        logging.info("Importing contacts from VCF file to device Contacts")
87        self.execute_shell_on_device(
88            device_target,
89            constants.IMPOST_CONTACTS_SHELL_COMAND,
90        )
91
92    def make_call(self):
93        """Make call"""
94        logging.info("Make a call")
95        self.device.mbs.makeCall()
96
97    def open_call_history(self):
98        """Open call history"""
99        logging.info("Open call history")
100        self.device.mbs.openCallHistory()
101
102
103    def open_contacts(self):
104        """Open contacts"""
105        logging.info("Opening contacts")
106        self.device.mbs.openContacts()
107
108    def open_dialpad(self):
109        """Open the dial pad from the dialer main screen"""
110        logging.info("Opening the dialpad")
111        self.device.mbs.openDialPad()
112
113    def open_dialer_settings(self):
114        logging.info("Opening the dialer settings")
115        self.device.mbs.openDialerSettings()
116
117    def open_phone_app(self):
118        logging.info("Opening phone app")
119        self.device.mbs.openPhoneApp()
120
121    def open_first_contact_details(self):
122        """Open the contact details page for the first contact visible in the contact list.
123        Assumes we are on the contacts page."""
124        logging.info("Getting details for first contact on the page")
125        self.device.mbs.openFirstContactDetails()
126
127    def open_bluetooth_settings(self):
128        """Assumes we are on the home screen.
129        Navigate to the Bluetooth setting page"""
130        logging.info("Opening bluetooth settings (via the Status Bar)")
131        self.device.mbs.openBluetoothSettings()
132
133    def press_active_call_toggle(self):
134        logging.info("Pressing the Active Call toggle")
135        self.device.mbs.pressActiveCallToggle()
136
137    def open_dialer_settings(self):
138        """Open dialer settings"""
139        logging.info('Opening Dialer settings')
140        self.device.mbs.openDialerSettings()
141
142    def press_bluetooth_toggle_on_device(self, device_name):
143        logging.info('Attempting to press the bluetooth toggle on device: \'%s\'' % device_name)
144        self.device.mbs.pressBluetoothToggleOnDevice(device_name)
145
146    def press_media_toggle_on_device(self, device_name):
147        logging.info('Attempting to press the media toggle on device: \'%s\'' % device_name)
148        self.device.mbs.pressMediaToggleOnDevice(device_name)
149
150    def press_contact_search_result(self, expected_first_name):
151        logging.info('Attempting to press the contact result with name \'%s\'' % expected_first_name)
152        self.device.mbs.pressContactResult(expected_first_name)
153
154    def press_device_entry_on_list_of_paired_devices(self, device_name):
155        logging.info('Attempting to press the device entry on device: ' + device_name)
156        self.device.mbs.pressDeviceInBluetoothSettings(device_name)
157
158    def press_home_screen_on_status_bar(self):
159        """Presses the Home screen button on the status bar
160        (to return the device to the home screen."""
161        logging.info("Pressing home screen button")
162        self.device.mbs.pressHomeScreen()
163
164    def press_phone_toggle_on_device(self, device_name):
165        logging.info('Attempting to press the phone toggle on device: \'%s\'' % device_name)
166        self.device.mbs.pressPhoneToggleOnDevice(device_name)
167
168    def press_dialer_button_on_phone_card(self):
169        logging.info('Attempting to press the dialer button on the phone card')
170        self.device.mbs.pressDialerButtonOnPhoneCard()
171
172    def device_displays_connected(self):
173        """Assumes the device bluetooth connection settings page is open"""
174        logging.info('Checking whether device is connected.')
175        self.device.mbs.deviceIsConnected()
176
177    def press_forget(self):
178        """Assumes the device bluetooth connection settings page is open"""
179        logging.info('Attempting to press \'Forget\'')
180        self.device.mbs.pressForget()
181
182    def press_home(self):
183        """Press the Home button to go back to the home page."""
184        logging.info("Pressing HOME ")
185        self.device.mbs.pressHome()
186
187    def press_enter_on_device(self, device_target):
188        """Press ENTER on device"""
189        logging.info("Pressing ENTER on device: ")
190        self.execute_shell_on_device(device_target, "input keyevent KEYCODE_ENTER")
191        self.wait_with_log(constants.ONE_SEC)
192
193    def push_vcf_contacts_to_device(self, device_target, path_to_contacts_file):
194        """Pushing contacts file to device using adb command"""
195        logging.info(
196            "Pushing VCF contacts to device %s to destination <%s>",
197            device_target.serial,
198            constants.PHONE_CONTACTS_DESTINATION_PATH,
199        )
200        device_target.adb.push(
201            [path_to_contacts_file, constants.PHONE_CONTACTS_DESTINATION_PATH],
202            timeout=20,
203        )
204
205    def validate_three_preference_buttons(self, bluetooth_enabled):
206        """ Checks each of the three preference buttons (bluetooth, phone, audio).
207
208        If bluetooth is enabled, all three buttons should be enabled, and the bluetooth
209        button should be checked.
210
211        If bluetooth is disabled, the bluetooth button should not be checked,
212        and the phone and media buttons should be disabled.
213        """
214        logging.info("Checking the three Preference buttons on the listed device")
215        expected_check_status = "checked" if bluetooth_enabled else "unchecked"
216        if (self.device.mbs.isBluetoothPreferenceChecked() != bluetooth_enabled):
217            logging.info("Bluetooth preference check status does not match expected status: "
218                         + str(bluetooth_enabled))
219            return False
220
221        expected_status = "enabled" if bluetooth_enabled else "disabled"
222        if (self.device.mbs.isPhonePreferenceEnabled()  != bluetooth_enabled):
223            logging.info("Phone preference was does not match expected status: %s",
224                         str(expected_status))
225            return False
226
227        if (self.device.mbs.isMediaPreferenceEnabled() != bluetooth_enabled):
228            logging.info("Media preference does not match enabled status: " + str(expected_status))
229            return False
230
231        return True
232
233
234    def upload_vcf_contacts_to_device(self, device_target, path_to_contacts_file):
235        """Upload contacts do device"""
236        self.import_contacts_from_vcf_file(device_target)
237        device_target.mbs.pressDevice()
238
239    def verify_contact_name(self, expected_contact):
240        actual_dialed_contact = self.device.mbs.getContactName()
241        logging.info(
242            "Expected contact name being called: <%s>, Actual: <%s>",
243            expected_contact,
244            actual_dialed_contact,
245        )
246        if actual_dialed_contact != expected_contact:
247            raise CallUtilsError(
248                "Actual and Expected contacts on dial pad don't match."
249            )
250
251    def wait_with_log(self, wait_time):
252        """Wait for specific time for debugging"""
253        logging.info("Sleep for %s seconds", wait_time)
254        time.sleep(wait_time)
255    # Open contacts detais page
256    def open_details_page(self, contact_name):
257        logging.info('open contacts details page')
258        self.device.mbs.openDetailsPage(contact_name)
259    # Close contact details page
260    def close_details_page(self):
261        logging.info('close contacts details page')
262        self.device.mbs.closeDetailsPage()
263    # Add Remove Favorite contact
264    def add_remove_favorite_contact(self):
265        logging.info('add remove favorite contact')
266        self.device.mbs.addRemoveFavoriteContact()
267    # Add Favorites from Favorite Tab
268    def add_favorites_from_favorites_tab(self, contact_name):
269        logging.info('add favorites from favorites tab')
270        self.device.mbs.addFavoritesFromFavoritesTab(contact_name)
271    # Add Remove Favorite contact
272    def is_contact_in_favorites(self, contact_name, expected_result):
273        logging.info('check if contact is in favorites')
274        actual_result =self.device.mbs.isContactInFavorites(contact_name)
275        logging.info(
276            ' Add/Remove contacts expected : <%s>, Actual : <%s>',
277            expected_result,
278            actual_result,
279        )
280        if expected_result == 'True' and expected_result != actual_result:
281            raise CallUtilsError('Contact not added to favorites')
282        if expected_result == 'False' and expected_result != actual_result:
283            raise CallUtilsError('Contact not removed from favorites')
284
285
286    def open_bluetooth_media_app(self):
287        """ Open Bluetooth Audio app """
288        logging.info('Open Bluetooth Audio app')
289        self.device.mbs.openBluetoothMediaApp();
290        self.wait_with_log(1)
291
292    def open_bluetooth_sms_app(self):
293        """ Open Bluetooth SMS app """
294        logging.info('Open Bluetooth SMS app')
295        self.device.mbs.openSmsApp();
296        self.wait_with_log(1)
297
298    def click_phone_button(self):
299        logging.info("Click phone button")
300        self.device.mbs.clickPhoneButton()
301
302    def verify_disabled_phone_profile(self):
303        logging.info("Checks if phone profile is disabled")
304        return self.device.mbs.isBluetoothPhoneButtonEnabled()
305
306    def verify_bluetooth_hfp_error_displayed(self):
307        logging.info("Checks if bluetooth hfp error")
308        return self.device.mbs.isBluetoothHfpErrorDisplayed()
309
310    def verify_dialer_recents_tab(self):
311        logging.info("Checks if dialer recents tab is displayed")
312        return self.device.mbs.verifyDialerRecentsTab()
313
314    def verify_dialer_contacts_tab(self):
315        logging.info("Checks if dialer contacts tab is displayed")
316        return self.device.mbs.verifyDialerContactsTab()
317
318    def verify_dialer_favorites_tab(self):
319        logging.info("Checks if favorites tab is displayed")
320        return self.device.mbs.verifyDialerFavoritesTab()
321
322    def verify_dialer_dialpad_tab(self):
323        logging.info("Checks if dialpad is displayed")
324        return self.device.mbs.verifyDialerDialpadTab()
325
326    def open_sms_app(self):
327        """Open sms app"""
328        logging.info('Opening sms app')
329        self.device.mbs.openSmsApp()
330
331    def open_bluetooth_palette(self):
332        logging.info("Open Bluetooth Palette")
333        self.device.mbs.openBluetoothPalette()
334
335    def click_bluetooth_button(self):
336        logging.info("Click Bluetooth Button")
337        self.device.mbs.clickBluetoothButton()
338
339    def is_bluetooth_connected(self):
340        logging.info("Bluetooth Connected Status")
341        is_connected = self.device.mbs.isBluetoothConnected()
342        return is_connected
343
344    def is_bluetooth_audio_disconnected_label_visible(self):
345        """ Return is <Bluetooth Audio disconnected> label present """
346        logging.info('Checking is <Bluetooth Audio disconnected> label present')
347        actual_disconnected_label_status = self.device.mbs.isBluetoothAudioDisconnectedLabelVisible()
348        logging.info('<Bluetooth Audio disconnected> label is present: %s',
349                     actual_disconnected_label_status)
350        return actual_disconnected_label_status
351
352    def is_connect_to_bluetooth_label_visible_on_bluetooth_audio_page(self):
353        """ Return is <Connect to Bluetooth> label present """
354        logging.info('Checking is <Connect to Bluetooth> label present')
355        actual_status = self.device.mbs.isBluetoothAudioDisconnectedLabelVisible()
356        logging.info('<Connect to Bluetooth> label is present: %s',actual_status)
357        return actual_status
358
359    def click_cancel_label_visible_on_bluetooth_audio_page(self):
360        """ Clicks on <Cancel> label present on bluetooth Audio page"""
361        self.device.mbs.cancelBluetoothAudioConncetion()
362        logging.info('Clicked on <Cancel> label present on bluetooth Audio page')
363
364    def update_device_timezone(self, expected_timezone):
365        logging.info('Update the device timezone to %s',
366                     expected_timezone)
367        self.device.mbs.setTimeZone(expected_timezone)
368        actual_timezone = self.device.mbs.getTimeZone()
369        logging.info('<actual timezone> : %s  and <expected_timezone> %s',
370                     actual_timezone, expected_timezone)
371        if expected_timezone not in actual_timezone:
372            raise CallUtilsError(
373                "Time Zone did not set properly."
374            )
375
376    def is_bluetooth_hfp_error_displayed(self):
377        logging.info('Verify Bluetooth HFP error is displayed,'
378                     'when bluetooth is disconnected')
379        return self.device.mbs.isBluetoothHfpErrorDisplayed()
380
381    def search_contacts_name(self, contact_name):
382        logging.info('Searching <%s> in contacts', contact_name)
383        self.device.mbs.searchContactsByName(contact_name)
384
385    def sort_contacts_by_first_name(self):
386        logging.info('Sorting contacts by first name')
387        self.device.mbs.sortContactListByFirstName()
388
389    def get_list_of_visible_contacts(self):
390        logging.info('Getting list of visible contacts')
391        actual_visible_contacts_list = self.device.mbs.getListOfAllContacts()
392        logging.info(
393            'Actual list of visible contacts: <%s>', actual_visible_contacts_list
394        )
395        return actual_visible_contacts_list
396
397    def verify_ascending_sorting_order(self, actual_sorting_order):
398        expected_sorting_order = sorted(actual_sorting_order)
399        logging.info(
400            'Expected sorting order: <%s>, Actual sorting order: <%s>',
401            expected_sorting_order,
402            actual_sorting_order,
403        )
404        if actual_sorting_order != expected_sorting_order:
405            raise CallUtilsError("Actual and Expected sorting orders don't match.")
406
407    def is_bluetooth_sms_disconnected_label_visible(self):
408        """ Return is <Bluetooth SMS disconnected> label present """
409        logging.info('Checking is <Bluetooth SMS disconnected> label present')
410        actual_disconnected_label_status = self.device.mbs.isSmsBluetoothErrorDisplayed()
411        logging.info('<Bluetooth SMS disconnected> label is present: %s',
412                     actual_disconnected_label_status)
413        return actual_disconnected_label_status
414
415    # Verify dialing number the same as expected
416    def verify_dialing_number(self, expected_dialing_number):
417        """Replace all non-digits characters to null"""
418        actual_dialing_number = re.sub(r'\D', '', str(self.get_dialing_number()))
419        logging.info(
420            'Expected dialing number: %s, Actual: %s',
421            expected_dialing_number,
422            actual_dialing_number,
423        )
424        if actual_dialing_number != expected_dialing_number:
425            raise CallUtilsError(
426                "Actual and Expected dialing numbers don't match.")
427
428
429    # Verify dialing number the same as expected
430    def verify_user_phone_number(self, expected_dialing_number):
431        """Replace all non-digits characters to null"""
432        actual_dialing_number = re.sub(r'\D', '', str(self.get_user_phone_number()))
433        logging.info(
434            'Expected dialing number: %s, Actual: %s',
435            expected_dialing_number,
436            actual_dialing_number,
437        )
438        if actual_dialing_number != expected_dialing_number:
439            raise CallUtilsError(
440                "Actual and Expected dialing numbers don't match.")
441
442    def is_ongoing_call_displayed_on_home(self, expected_result):
443        logging.info('Open Home screen and verify the ongoing call')
444        self.device.mbs.isOngoingCallDisplayedOnHome()
445        actual_result = self.device.mbs.isOngoingCallDisplayedOnHome()
446        logging.info(
447            'Call Displayed on home expected : <%s>, Actual : <%s>',
448            expected_result,
449            actual_result,
450        )
451        if expected_result != actual_result:
452            raise CallUtilsError('Ongoing call not displayed on home')
453
454    def get_recent_call_history(self):
455        actual_recent_call_from_history = self.device.mbs.getRecentCallHistory()
456        logging.info(
457            'The latest call from history: <%s>', actual_recent_call_from_history
458        )
459        return actual_recent_call_from_history
460
461    def verify_last_dialed_number(self, expected_last_dialed_number):
462        actual_last_dialed_number = self.get_recent_call_history()
463        actual_last_dialed_number = ''.join(
464            char for char in actual_last_dialed_number if char.isdigit()
465        )
466        logging.info(
467            'Expected last called number: %s, Actual: %s',
468            expected_last_dialed_number,
469            actual_last_dialed_number,
470        )
471        if actual_last_dialed_number != expected_last_dialed_number:
472            raise CallUtilsError(
473                "Actual and Expected last dialed numbers don't match."
474            )
475
476    def open_phone_app_from_home(self):
477        logging.info('Open Phone from Home Screen card.')
478        self.device.mbs.openPhoneAppFromHome()
479
480    # Search contact by name
481    def search_contact_by_name(self, search_contact_name):
482        logging.info('Searching <%s> in contacts', search_contact_name)
483        self.device.mbs.searchContactsByName(search_contact_name)
484
485    # Get first search result
486    def get_first_search_result(self):
487        logging.info('Getting first search result')
488        actual_first_search_result = self.device.mbs.getFirstSearchResult()
489        logging.info('Actual first search result: <%s>', actual_first_search_result)
490        return actual_first_search_result
491
492    # Verify search result contains expected searach input
493    def verify_search_results_contain_target_search(self, expected_search_result):
494        actual_search_result = self.get_first_search_result()
495        logging.info(
496            'Expected search result: <%s>, Actual search result: <%s>',
497            expected_search_result,
498            actual_search_result,
499        )
500        if expected_search_result not in actual_search_result:
501            raise CallUtilsError('Actual search result does not contain Expected.')
502
503
504    def verify_sms_app_unread_message(self, expected):
505        """Verify unread message on sms app"""
506        logging.info('Verify Unread Message on SMS app')
507        actual_unread_message_badge_displayed = self.device.mbs.isUnreadSmsDisplayed()
508        logging.info(
509            'Unread message Expected: <%s>, Actual: <%s>',
510            expected,
511            actual_unread_message_badge_displayed,
512        )
513        if actual_unread_message_badge_displayed != expected:
514            raise CallUtilsError(
515                "SMS Unread messages - Actual and Expected doesn't match."
516            )
517
518    def verify_sms_preview_text(self, expected, text):
519        """Verify sms preview text"""
520        logging.info('Verify SMS Preview Text')
521        actual_message_preview_displayed = self.device.mbs.isSmsPreviewTextDisplayed(text)
522        logging.info(
523            'SMS Preview Text Expected: <%s>, Actual: <%s>',
524            expected,
525            actual_message_preview_displayed,
526        )
527        if actual_message_preview_displayed != expected:
528            raise CallUtilsError(
529                "SMS Preview Text- Actual and Expected doesn't match."
530            )
531
532    def tap_to_read_aloud(self):
533        """Tap on Received Text message"""
534        logging.info('Click on the text >>> tap to read aloud ')
535        self.device.mbs.tapToReadAloud()
536
537    def is_assistant_sms_transcription_plate_displayed(self,expected):
538        """ Checks if assistant transcription plate has displayed """
539        visibility_status = self.device.mbs.isAssistantSMSTranscriptionPlateDisplayed()
540        if visibility_status == expected:
541            logging.info("Assistant SMS Transcription plate has opened upon tapping the SMS.")
542        return visibility_status
543
544    def verify_sms_preview_timestamp(self, expected):
545        """Verify sms preview timestamp"""
546        logging.info('Verify SMS Preview TimeStamp')
547        actual_message_preview_timestamp = self.device.mbs.isSmsTimeStampDisplayed()
548        logging.info(
549            'SMS Preview TimeStamp Expected: <%s>, Actual: <%s>',
550            expected,
551            actual_message_preview_timestamp,
552        )
553        if actual_message_preview_timestamp != expected:
554            raise CallUtilsError(
555                "SMS Preview TimeStamp - Actual and Expected doesn't match."
556            )
557
558    def verify_sms_no_messages_displayed(self, expected):
559        """Verify sms preview timestamp"""
560        logging.info('Verify No Msg displayed')
561        actual_message_preview_timestamp = self.device.mbs.isNoMessagesDisplayed()
562        logging.info(
563            'SMS No Messages Expected: <%s>, Actual: <%s>',
564            expected,
565            actual_message_preview_timestamp,
566        )
567        if actual_message_preview_timestamp != expected:
568            raise CallUtilsError(
569                "No messages - Actual and Expected doesn't match."
570            )
571    def clear_sms_app(self, device_target):
572        """Verify sms preview timestamp"""
573        logging.debug('clearing the sms app')
574        # self.execute_shell_on_device(device_target, constants.ROOT)
575        self.execute_shell_on_device(device_target, constants.DELETE_MESSAGING_DB)
576        self.execute_shell_on_device(device_target, constants.CLEAR_MESSAGING_APP)
577
578    def reboot_device(self, device_target):
579        self.execute_shell_on_device(device_target, constants.REBOOT)
580
581    def has_bluetooth_button(self):
582        logging.info('Has Bluetooth Button ')
583        return self.device.mbs.hasBluetoothButton()
584
585    def has_bluetooth_palette_phone_button(self):
586        logging.info('Has Phone Button')
587        return self.device.mbs.hasBluetoothPalettePhoneButton()
588
589    def has_bluetooth_palette_media_button(self):
590        logging.info('Has Media Button')
591        return self.device.mbs.hasBluetoothPaletteMediaButton()
592
593    def verify_device_name(self):
594        logging.info('Verify Device Name')
595        return self.device.mbs.verifyDeviceName()
596
597    def is_bluetooth_button_enabled(self):
598        logging.info('Is Bluetooth Button Enabled')
599        return self.device.mbs.isBluetoothButtonEnabled()
600
601    def is_active_call_enabled(self):
602        logging.info("Verifying whether active call is enabled")
603        return self.device.mbs.isActiveCallEnabled()
604
605    def is_active_call_ongoing_full_screen(self):
606        logging.info("Verify whether an ongoing call is currently showing in full-screen mode")
607        return self.device.mbs.isOngoingCallInFullScreen()
608
609    def is_bluetooth_phone_button_enabled(self):
610        logging.info('Is Bluetooth Palette PhoneButton Enabled')
611        return self.device.mbs.isBluetoothPhoneButtonEnabled()
612
613    def is_bluetooth_media_button_enabled(self):
614        logging.info('Is Bluetooth Palette Media Button Enabled')
615        return self.device.mbs.isBluetoothMediaButtonEnabled()
616
617    def get_dial_in_number(self):
618        return self.device.mbs.getNumberInDialPad()
619
620    # Verify dialed number on Dial Pad the same as expected
621    def verify_dialed_number_on_dial_pad(self, expected_dialed_number):
622        actual_dialed_number = self.get_dial_in_number()
623        logging.info('Expected number on Dial Pad: <%s>, Actual: <%s>',
624                     expected_dialed_number,
625                     actual_dialed_number,)
626
627        if actual_dialed_number != expected_dialed_number:
628            raise CallUtilsError(
629                "Actual and Expected dialing numbers on dial pad don't match.")
630
631    # Delete dialed number on Dial Pad
632    def delete_dialed_number_on_dial_pad(self):
633        logging.info('Deleting dialed number on Dial Pad')
634        self.device.mbs.deleteDialedNumber()
635    # End call on IVI using adb shell command
636    def end_call_using_adb_command(self, device_target):
637        self.execute_shell_on_device(device_target, 'input keyevent KEYCODE_ENDCALL')
638
639    # Make a call most recent history
640    def call_most_recent_call_history(self):
641        logging.info('Calling most recent call in history')
642        self.device.mbs.callMostRecentHistory()
643
644    # Change audio source to PHONE
645    def change_audio_source_to_phone(self):
646        logging.info('Changing audio source to PHONE')
647        self.device.mbs.changeAudioSourceToPhone()
648
649    # Change audio source to CAR SPEAKERS
650    def change_audio_source_to_car_speakers(self):
651        logging.info('Changing audio source to CAR SPEAKERS')
652        self.device.mbs.changeAudioSourceToCarSpeakers()
653
654    def enable_driving_mode(self):
655        self.device.mbs.enableDrivingMode()
656
657    def disable_driving_mode(self):
658        self.device.mbs.disableDrivingMode()
659
660    # Check if microphone chip is displayed on status bar
661    def is_microphone_displayed_on_status_bar(self, expected_result):
662       logging.info('Mute the call, verify microphone on status bar')
663       actual_result = self.device.mbs.isMicChipPresentOnStatusBar()
664       logging.info(
665           'Microphone Chip on status bar expected : <%s>, Actual : <%s>',
666           expected_result,
667           actual_result,
668       )
669       if expected_result != actual_result:
670         raise CallUtilsError(
671             'MicroPhone Chip not in sync with call status'
672         )
673
674    # Mute call
675    def mute_call(self):
676        logging.info('Muting call')
677        self.device.mbs.muteCall()
678
679    # Unmute call
680    def unmute_call(self):
681        logging.info('Unmuting call')
682        self.device.mbs.unmuteCall()
683
684    def click_on_bluetooth_palette_media_button(self):
685        """Performs click operation on Bluetooth Palette media button"""
686        self.device.mbs.clickOnBluetoothPaletteMediaButton()
687        logging.info("Clicked on bluetooth palette media button")
688
689    def open_notification_on_phone(self, device_target):
690        """Open notifications on Phone"""
691        logging.debug('Open notifications on Phone')
692        self.execute_shell_on_device(device_target, constants.OPEN_NOTIFICATION)
693
694    def press_phone_home_icon_using_adb_command(self, device_target):
695        self.execute_shell_on_device(device_target, 'input keyevent KEYCODE_HOME')
696