xref: /aosp_15_r20/external/autotest/client/common_lib/cros/cfm_meetings_api.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7
8from six.moves.urllib.parse import urlparse
9
10from autotest_lib.client.bin import utils
11from autotest_lib.client.common_lib import error
12
13
14DEFAULT_TIMEOUT = 30
15TELEMETRY_API = 'hrTelemetryApi'
16
17
18class CfmMeetingsAPI(object):
19    """Utility class for interacting with CfMs."""
20
21    def __init__(self, webview_context):
22        self._webview_context = webview_context
23
24    def _execute_telemetry_command(self, command):
25        self._webview_context.ExecuteJavaScript(
26            'window.%s.%s' % (TELEMETRY_API, command))
27
28    def _evaluate_telemetry_command(self, command):
29        return self._webview_context.EvaluateJavaScript(
30            'window.%s.%s' % (TELEMETRY_API, command))
31
32    # UI commands/functions
33    def wait_for_meetings_landing_page(self):
34        """Waits for the landing page screen."""
35        self._webview_context.WaitForJavaScriptCondition(
36            'window.hasOwnProperty("%s") '
37            '&& !window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API),
38            timeout=DEFAULT_TIMEOUT)
39        logging.info('Reached meetings landing page.')
40
41    def wait_for_meetings_in_call_page(self):
42        """Waits for the in-call page to launch."""
43        self._webview_context.WaitForJavaScriptCondition(
44            'window.hasOwnProperty("%s") '
45            '&& window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API),
46            timeout=DEFAULT_TIMEOUT)
47        logging.info('Reached meetings in-call page.')
48
49    def wait_for_oobe_start_page(self):
50        """Wait for oobe start screen to launch."""
51        self._webview_context.WaitForJavaScriptCondition(
52            'window.hasOwnProperty("%s") '
53            '&& typeof window.%s.skipOobe === "function"' % (
54                TELEMETRY_API, TELEMETRY_API),
55            timeout=DEFAULT_TIMEOUT)
56        logging.info('Reached oobe page.')
57
58    def skip_oobe_screen(self):
59        """Skip Chromebox for Meetings oobe screen."""
60        self._execute_telemetry_command('skipOobe()')
61        utils.poll_for_condition(
62                lambda: not self.is_oobe_start_page(),
63                exception=error.TestFail('Not able to skip oobe screen.'),
64                timeout=DEFAULT_TIMEOUT,
65                sleep_interval=1)
66        logging.info('Skipped oobe screen.')
67
68    def is_oobe_start_page(self):
69        """Check if device is on CFM oobe start screen."""
70        if self._webview_context.EvaluateJavaScript(
71                'window.hasOwnProperty("%s") '
72                '&& typeof window.%s.skipOobe === "function"' % (
73                    TELEMETRY_API, TELEMETRY_API)):
74            logging.info('Is on oobe start page.')
75            return True
76        logging.info('Is not on oobe start page.')
77        return False
78
79    # Hangouts commands/functions
80    def start_meeting_session(self):
81        """Start a meeting.
82
83        @return code for the started meeting
84        """
85        if self.is_in_meeting_session():
86            self.end_meeting_session()
87
88        self._execute_telemetry_command('startMeeting()')
89        self.wait_for_meetings_in_call_page()
90        meeting_code = self._get_meeting_code()
91        logging.info('Started meeting session %s', meeting_code)
92        return meeting_code
93
94    def _get_meeting_code(self):
95        path = urlparse(self._webview_context.GetUrl()).path
96        # The meeting code is the last part of the path.
97        return path.split('/')[-1]
98
99    def join_meeting_session(self, meeting_name):
100        """Joins a meeting.
101
102        @param meeting_name: Name of the meeting session.
103        """
104        if self.is_in_meeting_session():
105            self.end_meeting_session()
106
107        self._execute_telemetry_command('joinMeeting("%s")' % meeting_name)
108        self.wait_for_meetings_in_call_page()
109        logging.info('Started meeting session: %s', meeting_name)
110
111    def end_meeting_session(self):
112        """End current meeting session."""
113        self._execute_telemetry_command('endCall()')
114        self.wait_for_meetings_landing_page()
115        logging.info('Ended meeting session.')
116
117    def is_in_meeting_session(self):
118        """Check if device is in meeting session."""
119        if self._evaluate_telemetry_command('isInMeeting()'):
120            logging.info('Is in meeting session.')
121            return True
122        logging.info('Is not in meeting session.')
123        return False
124
125    def start_new_hangout_session(self, hangout_name):
126        """Start a new hangout session.
127
128        @param hangout_name: Name of the hangout session.
129        """
130        raise NotImplementedError
131
132    def end_hangout_session(self):
133        """End current hangout session."""
134        raise NotImplementedError
135
136    def is_in_hangout_session(self):
137        """Check if device is in hangout session."""
138        raise NotImplementedError
139
140    def is_ready_to_start_hangout_session(self):
141        """Check if device is ready to start a new hangout session."""
142        raise NotImplementedError
143
144    def get_participant_count(self):
145        """Returns the total number of participants in a meeting."""
146        return self._evaluate_telemetry_command('getParticipantCount()')
147
148    # Diagnostics commands/functions
149    def is_diagnostic_run_in_progress(self):
150        """Check if hotrod diagnostics is running."""
151        raise NotImplementedError
152
153    def wait_for_diagnostic_run_to_complete(self):
154        """Wait for hotrod diagnostics to complete."""
155        raise NotImplementedError
156
157    def run_diagnostics(self):
158        """Run hotrod diagnostics."""
159        raise NotImplementedError
160
161    def get_last_diagnostics_results(self):
162        """Get latest hotrod diagnostics results."""
163        raise NotImplementedError
164
165    # Mic audio commands/functions
166    def is_mic_muted(self):
167        """Check if mic is muted."""
168        if self._evaluate_telemetry_command('isMicMuted()'):
169            logging.info('Mic is muted.')
170            return True
171        logging.info('Mic is not muted.')
172        return False
173
174    def mute_mic(self):
175        """Local mic mute from toolbar."""
176        self._execute_telemetry_command('setMicMuted(true)')
177        logging.info('Locally muted mic.')
178
179    def unmute_mic(self):
180        """Local mic unmute from toolbar."""
181        self._execute_telemetry_command('setMicMuted(false)')
182        logging.info('Locally unmuted mic.')
183
184    def get_mic_devices(self):
185        """Get all mic devices detected by hotrod."""
186        return self._evaluate_telemetry_command('getAudioInDevices()')
187
188    def get_preferred_mic(self):
189        """Get preferred microphone for hotrod."""
190        return self._evaluate_telemetry_command('getPreferredAudioInDevice()')
191
192    def set_preferred_mic(self, mic_name):
193        """Set preferred mic for hotrod.
194
195        @param mic_name: String with mic name.
196        """
197        self._execute_telemetry_command('setPreferredAudioInDevice(%s)'
198                                        % mic_name)
199        logging.info('Setting preferred mic to %s.', mic_name)
200
201    def remote_mute_mic(self):
202        """Remote mic mute request from cPanel."""
203        raise NotImplementedError
204
205    def remote_unmute_mic(self):
206        """Remote mic unmute request from cPanel."""
207        raise NotImplementedError
208
209    # Speaker commands/functions
210    def get_speaker_devices(self):
211        """Get all speaker devices detected by hotrod."""
212        return self._evaluate_telemetry_command('getAudioOutDevices()')
213
214    def get_preferred_speaker(self):
215        """Get speaker preferred for hotrod."""
216        return self._evaluate_telemetry_command('getPreferredAudioOutDevice()')
217
218    def set_preferred_speaker(self, speaker_name):
219        """Set preferred speaker for hotrod.
220
221        @param speaker_name: String with speaker name.
222        """
223        self._execute_telemetry_command('setPreferredAudioOutDevice(%s)'
224                                        % speaker_name)
225        logging.info('Set preferred speaker to %s.', speaker_name)
226
227    def set_speaker_volume(self, volume_level):
228        """Set speaker volume.
229
230        @param volume_level: Number value ranging from 0-100 to set volume to.
231        """
232        self._execute_telemetry_command('setAudioOutVolume(%d)' % volume_level)
233        logging.info('Set speaker volume to %d', volume_level)
234
235    def get_speaker_volume(self):
236        """Get current speaker volume."""
237        return self._evaluate_telemetry_command('getAudioOutVolume()')
238
239    def play_test_sound(self):
240        """Play test sound."""
241        raise NotImplementedError
242
243    # Camera commands/functions
244    def get_camera_devices(self):
245        """Get all camera devices detected by hotrod.
246
247        @return List of camera devices.
248        """
249        return self._evaluate_telemetry_command('getVideoInDevices()')
250
251    def get_preferred_camera(self):
252        """Get camera preferred for hotrod."""
253        return self._evaluate_telemetry_command('getPreferredVideoInDevice()')
254
255    def set_preferred_camera(self, camera_name):
256        """Set preferred camera for hotrod.
257
258        @param camera_name: String with camera name.
259        """
260        self._execute_telemetry_command('setPreferredVideoInDevice(%s)'
261                                        % camera_name)
262        logging.info('Set preferred camera to %s.', camera_name)
263
264    def is_camera_muted(self):
265        """Check if camera is muted (turned off)."""
266        if self._evaluate_telemetry_command('isCameraMuted()'):
267            logging.info('Camera is muted.')
268            return True
269        logging.info('Camera is not muted.')
270        return False
271
272    def mute_camera(self):
273        """Mute (turn off) camera."""
274        self._execute_telemetry_command('setCameraMuted(true)')
275        logging.info('Camera muted.')
276
277    def unmute_camera(self):
278        """Unmute (turn on) camera."""
279        self._execute_telemetry_command('setCameraMuted(false)')
280        logging.info('Camera unmuted.')
281
282    def move_camera(self, camera_motion):
283        """Move camera(PTZ functions).
284
285        @param camera_motion: String of the desired camera motion.
286        """
287        ptz_motions = ['panLeft','panRight','panStop',
288                       'tiltUp','tiltDown','tiltStop',
289                       'zoomIn','zoomOut','resetPosition']
290
291        if camera_motion in ptz_motions:
292            self._execute_telemetry_command('ptz.%s()' % camera_motion)
293        else:
294            raise ValueError('Unsupported PTZ camera action: "%s"'
295                             % camera_motion)
296