1"""Bluetooth stub class.
2
3This controller offers no direct control to any device. It simply prompts the
4user to perform a certain action on the device it is standing in for. For use
5in test scripts where no controller for the DUT exists.
6"""
7
8from __future__ import absolute_import
9from __future__ import division
10from __future__ import print_function
11
12from typing import Any, List
13
14import six
15
16
17class BtStub(object):
18  """Stub for when controller class does not exist for a Bluetooth device.
19
20  This class will simulate semi-automation by prompting user to manually
21  perform actions on the Bluetooth device.
22  """
23
24  # Connection Commands
25  def power_off(self) -> None:
26    """Prompt the user to power off the Bluetooth device."""
27    six.moves.input('Power Off Bluetooth device, then press enter.')
28
29  def power_on(self) -> None:
30    """Prompt the user to power on the Bluetooth device."""
31    six.moves.input('Power ON Bluetooth device, then press enter.')
32
33  def activate_pairing_mode(self) -> None:
34    """Prompt the user to put the Bluetooth device into pairing mode."""
35    six.moves.input('Put Bluetooth device into pairing mode, then press enter.')
36
37  def get_bluetooth_mac_address(self) -> str:
38    """Prompt the user to input the Bluetooth MAC address for this device.
39
40    Returns:
41      mac_address (str): the string received from user input.
42    """
43    mac_address = six.moves.input('Enter BT MAC address, then press enter.')
44    return mac_address
45
46  def set_device_name(self, device_name: str) -> None:
47    """Prompt the user to set the device name (Carkit Only).
48
49    Args:
50      device_name: String of device name to be set.
51
52    Returns: None
53    """
54    six.moves.input(f'Device name is: {device_name}')
55
56  def factory_reset_bluetooth(self) -> None:
57    """Prompt the user to factory reset Bluetooth on the device."""
58    six.moves.input('Factory reset Bluetooth on the Bluetooth device, '
59                    'then press enter.')
60
61  # A2DP: Bluetooth stereo streaming protocol methods.
62  def is_audio_playing(self) -> bool:
63    """Prompt the user to indicate if the audio is playing.
64
65    Returns:
66      A Bool, true is audio is playing, false if not.
67    """
68    audio_playing = six.moves.input('Indicate if audio is playing: '
69                                    'true/false.')
70    return bool(audio_playing)
71
72  # AVRCP Commands
73  def volume_up(self) -> None:
74    """Prompt the user to raise the volume on the Bluetooth device."""
75    six.moves.input('Press the Volume Up Button on the Bluetooth device, '
76                    'then press enter.')
77
78  def volume_down(self) -> None:
79    """Prompt the user to lower the volume on the Bluetooth device."""
80    six.moves.input('Press the Volume Down Button on the Bluetooth device, '
81                    'then press enter.')
82
83  def track_next(self) -> None:
84    """Prompt the user to skip the track on the Bluetooth device."""
85    six.moves.input('Press the Skip Track Button on the Bluetooth device, '
86                    'then press enter.')
87
88  def track_previous(self) -> None:
89    """Prompt the user to rewind the track on the Bluetooth device."""
90    six.moves.input('Press the Rewind Track Button on the Bluetooth device, '
91                    'then press enter.')
92
93  def play(self) -> None:
94    """Prompt the user to press play on the Bluetooth device."""
95    six.moves.input('Press the Play Button on the Bluetooth device, '
96                    'then press enter.')
97
98  def pause(self) -> None:
99    """Prompt the user to press pause on the Bluetooth device."""
100    six.moves.input('Press the Pause Button on the Bluetooth device, '
101                    'then press enter.')
102
103  def repeat(self) -> None:
104    """Prompt the user to set the repeat option on the device."""
105    six.moves.input('Press the Repeat Button on the Bluetooth device, '
106                    'then press enter.')
107
108  def fast_forward(self) -> None:
109    """Prompt the user to press the fast forward option/button on the device.
110
111    Returns: None
112    """
113    six.moves.input('Press the Fast Forward Button on the Bluetooth device, '
114                    'then press enter.')
115
116  def rewind(self) -> None:
117    """Prompt the user to press Rewind option on the device.
118
119    Returns: None
120    """
121    six.moves.input('Press the Rewind option on the Bluetooth device, '
122                    'then press enter.')
123
124  # TODO(user): browse_media_content may need more work in terms of input
125  # params and value(s) returned
126  def browse_media_content(self, directory: str = '') -> List[Any]:
127    """Prompt the user to enter to the paired device media folders.
128
129    Args:
130      directory: A path to the directory to browse to.
131
132    Returns:
133      List - empty
134    """
135    six.moves.input(f'Navigate to directory: {directory}')
136    return []
137
138  def delete_song(self, file_path: str = '') -> None:
139    """Prompt the user to delete a song.
140
141    Args:
142      file_path (optional): A file path to the song to be deleted.
143
144    Returns: None
145    """
146    six.moves.input(f'Delete a song {file_path}')
147
148  def shuffle_song(self) -> None:
149    """Prompt the user to shuffle a playlist.
150
151    Returns: None
152    """
153    six.moves.input('Shuffle a playlist')
154
155  # HFP (Hands Free Phone protocol) Commands
156  def call_volume_up(self) -> None:
157    """Prompt the user to press the volume up button on an active call.
158
159    Returns: None
160    """
161    six.moves.input('Press the volume up button for an active call.')
162
163  def call_volume_down(self) -> None:
164    """Prompt the user to press the volume down button on an active call.
165
166    Returns: None
167    """
168    six.moves.input('Press the volume down button for an active call.')
169
170  def answer_phone_call(self) -> None:
171    """Prompt the user to press the button to answer a phone call..
172
173    Returns: None
174    """
175    six.moves.input('Press the button to answer the phone call.')
176
177  def hangup_phone_call(self) -> None:
178    """Prompt the user to press the button to hang up on an active phone call.
179
180    Returns: None
181    """
182    six.moves.input('Press the button to hang up on the phone call.')
183
184  def call_contact(self, name: str) -> None:
185    """Prompt the user to select a contact from the phonebook and call.
186
187    Args:
188      name: string name of contact to call
189
190    Returns: None
191    """
192    six.moves.input(f'Select contact, {name}, to call.')
193
194  def call_number(self, phone_number: str) -> None:
195    """Prompt the user to dial a phone number and call.
196
197    Args:
198      phone_number: string of phone number to dial and call
199
200    Returns: None
201    """
202    six.moves.input(f'Dial phone number and initiate a call. {phone_number}')
203
204  def swap_call(self) -> None:
205    """Prompt the user to push the button to swap.
206
207       Function swaps between the primary and secondary calls.  One call will
208       be active and the other will be on hold.
209
210    Returns: None
211    """
212    six.moves.input('Press the button to swap calls.')
213
214  def merge_call(self) -> None:
215    """Prompt the user to push the button to merge calls.
216
217       Merges calls between the primary and secondary calls into a conference
218       call.
219
220    Returns: None
221    """
222    six.moves.input('Press the button to merge calls into a conference call.')
223
224  def hold_call(self) -> None:
225    """Prompt the user to put the primary call on hold.
226
227    Primary call will be on hold, while the secondary call becomes active.
228
229    Returns: None
230    """
231    six.moves.input('Press the hold button to put primary call on hold.')
232
233  def mute_call(self) -> None:
234    """Prompt the user to mute the ongoing active call.
235
236    Returns: None
237    """
238    six.moves.input('Press Mute button on active call.')
239
240  def unmute_call(self) -> None:
241    """Prompt the user to unmute the ongoing active call.
242
243    Returns: None
244    """
245    six.moves.input('Press the Unmute button on an active call.')
246
247  def reject_phone_call(self) -> None:
248    """Prompt the user to reject an incoming call.
249
250    Returns: None
251    """
252    six.moves.input('Press the Reject button to reject an incoming call.')
253
254  def answer_voip_call(self) -> None:
255    """Prompt the user to press the button to answer a VOIP call.
256
257    Returns: None
258    """
259    six.moves.input('Press the Answer button on an incoming VOIP phone call.')
260
261  def hangup_voip_call(self) -> None:
262    """Prompt the user to press the button to hangup on the active VOIP call.
263
264    Returns: None
265    """
266    six.moves.input('Press the hangup button on the active VOIP call.')
267
268  def reject_voip_call(self) -> None:
269    """Prompt the user to press the Reject button on the incoming VOIP call.
270
271    Returns: None
272    """
273    six.moves.input('Press the Reject button on the incoming VOIP call.')
274
275  def voice_dial(self) -> None:
276    """Prompt user to initiate a voice dial from the phone.
277
278    Returns: None
279    """
280    six.moves.input('Initiate a voice dial.')
281
282  def last_number_dial(self) -> None:
283    """Prompt user to iniate a call to the last number dialed.
284
285    Returns: None
286    """
287    six.moves.input('Initiate a call to the last number dialed.')
288
289  # TODO(user): does this method need a input parameter?
290  def route_call_audio(self) -> None:
291    """Prompt user to route a call from AG to HF, and vice versa.
292
293    Returns: None
294    """
295    six.moves.input('Reroute call audio.')
296