# Copyright (C) 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging import re import time from utilities import constants from utilities.common_utils import CommonUtils class MediaUtils: """A utility that provides Media controls for handheld device and HU.""" def __init__(self, target, discoverer): self.target = target self.discoverer = discoverer self.common_utils = CommonUtils(self.target, self.discoverer) # Execute any shell command on phone device def execute_shell_on_device(self, shell_command): self.target.log.info( 'Executing shell command: <%s> on phone device <%s>', shell_command, self.target.serial, ) return self.target.adb.shell(shell_command) # Execute any shell command on HU def execute_shell_on_hu_device(self, shell_command): self.target.log.info( 'Executing shell command: <%s> on HU device <%s>', shell_command, self.discoverer.serial, ) return self.discoverer.adb.shell(shell_command) # Start YouTube Music app on phone device def open_youtube_music_app(self): logging.info("Open YouTube Music on phone device") self.execute_shell_on_device( constants.DEFAULT_YOUTUBE_MUSIC_PLAYLIST ) # Stop YouTube Music app on phone device def close_youtube_music_app(self): logging.info("Close YouTube Music on phone device") self.execute_shell_on_device( constants.STOP_YOUTUBE_MEDIA_SHELL ) # Press TAB button on phone device def press_tab_on_device(self): logging.info("Press on phone device") self.execute_shell_on_device(constants.KEYCODE_TAB) # Press ENTER button on phone device def press_enter_on_device(self): logging.info("Press on phone device") self.execute_shell_on_device(constants.KEYCODE_ENTER) # Press NEXT song on phone device def press_next_song_button(self): logging.info("Press button on phone device") self.execute_shell_on_device(constants.KEYCODE_MEDIA_NEXT) # Press PREVIOUS song on phone device def press_previous_song_button(self): logging.info("Press button on phone device") self.execute_shell_on_device(constants.KEYCODE_MEDIA_PREVIOUS) # Press PAUSE song on phone device def press_pause_song_button(self): logging.info("Press button on phone device") self.execute_shell_on_device(constants.KEYCODE_MEDIA_PAUSE) # Press PLAY song on phone device def press_play_song_button(self): logging.info("Press button on phone device") self.execute_shell_on_device(constants.KEYCODE_MEDIA_PLAY) # Press STOP playing song on phone device def press_stop_playing_song_button(self): logging.info("Press playing song button on phone device") self.execute_shell_on_device(constants.KEYCODE_MEDIA_STOP) # Get song metadata from phone device def get_song_metadata(self): logging.info("Getting song metadata from phone device") # get dumpsys dumpsys_metadata = self.execute_shell_on_device(constants.GET_DUMPSYS_METADATA).decode( 'utf8') # compile regex regex_pattern = re.compile(constants.SONG_METADATA_PATTERN) # match regex actual_dumpsys_metadata = regex_pattern.findall(dumpsys_metadata) # check if dumpsys_metadata is not empty if len(actual_dumpsys_metadata) < 1: logging.info('dumpsys media_session metadata is empty after matching with RegEx ' + 'pattern <%s>', constants.SONG_METADATA_PATTERN) return constants.NULL_VALUE logging.info('Actual dumpsys media_session on phone device metadata: %s"', actual_dumpsys_metadata) # assign actual_song_metadata after '=' sign in actual_dumpsys_metadata # if actual_dumpsys_metadata contains less than 3 'null', # and split on '=' is an array with more than 1 element actual_song_metadata = [x.split('=', 1)[1] for x in actual_dumpsys_metadata if x.count(constants.NULL_VALUE) < 3 and len(x.split('=', 1)) > 1] logging.info("Actual song metadata on phone device: %s", actual_song_metadata) # assign parsed_song_metadata parsed_song_metadata = actual_song_metadata[0] if len( actual_song_metadata) > 0 else constants.NULL_VALUE logging.info("Parsed song metadata on phone device: %s", parsed_song_metadata) return parsed_song_metadata # Get song title from phone device def get_song_title_from_phone(self): logging.info("Getting song title from phone device") time.sleep(constants.YOUTUBE_SYNC_TIME) song_metadata_array = self.get_song_metadata().split(',') actual_song_title = song_metadata_array[0] logging.info("Actual song title on phone device: %s", actual_song_title) return actual_song_title # Get song title from HU def get_song_title_from_hu(self): logging.info("Getting song title from HU") actual_song_title = self.discoverer.mbs.getMediaTrackName() logging.info("Actual song title on HU: %s", actual_song_title) return actual_song_title # Click on NEXT track on HU def click_next_track_on_hu(self): logging.info("Click on NEXT track on HU") self.discoverer.mbs.clickNextTrack() time.sleep(constants.WAIT_FOR_LOAD) # Click on PREVIOUS track on HU def click_previous_track_on_hu(self): logging.info("Click on PREVIOUS track on HU") self.discoverer.mbs.clickPreviousTrack() time.sleep(constants.WAIT_FOR_LOAD) # Open Media app on HU def open_media_app_on_hu(self): logging.info("Open Media app on HU") self.discoverer.mbs.openBluetoothMediaApp() # Pause Media app on HU def pause_media_on_hu(self): logging.info("Press PAUSE button on HU") self.discoverer.mbs.pauseMedia() # Play Media app on HU def play_media_on_hu(self): logging.info("Press PLAY button on HU") self.discoverer.mbs.playMedia() # Click on CANCEL button on Connect BT Audio page on HU def click_on_cancel_bt_audio_connection_button_on_hu(self): logging.info("Click on Cancel Bluetooth Audio connection button on HU") self.discoverer.mbs.cancelBluetoothAudioConncetion() # Reboot HU def reboot_hu(self): logging.info("Starting HU reboot...") self.execute_shell_on_hu_device(constants.REBOOT) # Is song playing on HU def is_song_playing_on_hu(self): logging.info("Checking is song playing on HU") actual_song_playing_status = self.discoverer.mbs.isPlaying() logging.info("Is song playing: %s", actual_song_playing_status) return actual_song_playing_status # Maximize playing song def maximize_now_playing(self): logging.info("Maximizing playing song on HU") self.discoverer.mbs.maximizeNowPlaying() # Minimize playing song def minimize_now_playing(self): logging.info("Maximizing playing song on HU") self.discoverer.mbs.minimizeNowPlaying() # Open playlist def open_media_playlist(self): logging.info("Open Playlist content on HU") self.discoverer.mbs.openMediaAppMenuItems() # Scroll playlist to the button def scroll_playlist_to_the_button(self): logging.info("Scroll Playlist to the button on HU") self.discoverer.mbs.scrollPlayListDown() # Select first visible song from playlist def select_song_from_playlist(self): logging.info("Select song from playlist on HU") self.discoverer.mbs.clickOnSongFromPlaylist() # Get playing Album title def get_album_title_on_hu(self): logging.info("Getting Album title on HU") actual_album_title = self.discoverer.mbs.getAlbumTitle() logging.info("Actual Album title on HU: <%s>", actual_album_title) return actual_album_title # Get Artist title on HU def get_artist_title_on_hu(self): logging.info("Getting Artist title on HU") actual_artist_title = self.discoverer.mbs.getArtistrTitle() logging.info("Actual Artist title on HU: <%s>", actual_artist_title) return actual_artist_title # Get current song playing time on HU def get_current_song_playing_time_on_hu(self): logging.info("Getting current song playing time on HU") actual_current_song_playing_time = self.discoverer.mbs.getSongCurrentPlayingTime() logging.info("Actual current song playing time on HU: <%s>", actual_current_song_playing_time) return actual_current_song_playing_time def get_current_song_max_playing_time_on_hu(self): logging.info("Getting current song max playing time on HU") actual_current_song_max_playing_time = self.discoverer.mbs.getCurrentSongMaxPlayingTime() logging.info("Actual current song max playing time on HU: <%s>", actual_current_song_max_playing_time) return actual_current_song_max_playing_time # Check is NOW PLAYING label displayed def is_now_playing_label_displayed(self): logging.info("Checking is label displayed on HU") actual_is_now_playing_label_display_status = self.discoverer.mbs.isNowPlayingLabelVisible() logging.info(" label displayed: <%s>", actual_is_now_playing_label_display_status) return actual_is_now_playing_label_display_status # Check is PLAYLIST icon visible def is_playlist_icon_visible(self): logging.info("Checking is Playlist icon displayed on HU") actual_is_playlist_icon_displayed = self.discoverer.mbs.isPlaylistIconVisible() logging.info("Playlist icon displayed: <%s>", actual_is_playlist_icon_displayed) return actual_is_playlist_icon_displayed # Click on Playlist icon def click_on_playlist_icon(self): logging.info("Click on Playlist icon on HU") self.discoverer.mbs.clickOnPlaylistIcon() # Open Youtube Music app on HU def open_youtube_music_app_on_hu(self): logging.info("Open <%s> app on HU", constants.YOUTUBE_MUSIC_APP) self.common_utils.click_on_ui_element_with_text(constants.YOUTUBE_MUSIC_APP) # Open Bluetooth Audio app on HU def open_bluetooth_audio_app_on_hu(self): logging.info("Open <%s> app on HU", constants.BLUETOOTH_AUDIO_APP) self.common_utils.click_on_ui_element_with_text(constants.BLUETOOTH_AUDIO_APP) # Open Media Apps menu def open_media_apps_menu(self): logging.info("Open Media apps menu items on HU") self.discoverer.mbs.openMediaAppMenuItems() # Open Bluetooth player def open_bluetooth_player(self): logging.info("Open <%s> on HU", constants.BLUETOOTH_PLAYER) self.common_utils.click_on_ui_element_with_text(constants.BLUETOOTH_PLAYER) # Open Radio app def open_radio_app(self): logging.info("Open <%s> app on HU", constants.RADIO_APP) self.common_utils.click_on_ui_element_with_text(constants.RADIO_APP) # Tune FM Radio on HU def tune_fm_radio_on_hu(self, fm_frequency): if re.match(constants.FM_FREQUENCY_PATTERN, fm_frequency): logging.info("Tune FM Radio on HU for frequency <%s>", fm_frequency) logging.info("Select <%s> range for radio", constants.RADIO_FM_RANGE) self.common_utils.click_on_ui_element_with_text(constants.RADIO_FM_RANGE) for x in fm_frequency: self.common_utils.click_on_ui_element_with_text(x) time.sleep(constants.WAIT_ONE_SEC) logging.info("Confirm selected %s frequency on HU", constants.RADIO_FM_RANGE) self.common_utils.click_on_ui_element_with_text(constants.CONFIRM_RADIO_FREQUENCY) else: logging.error("Invalid FM Radio frequency. Expected pattern: <%s>", constants.FM_FREQUENCY_PATTERN)