• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#  Copyright (C) 2024 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"""Test utils for UWB."""
15
16import time
17from lib.ranging_decorator import RangingTechnology
18from mobly import asserts
19from mobly.controllers import android_device
20
21WAIT_TIME_SEC = 3
22
23
24def initialize_uwb_country_code(ad: android_device.AndroidDevice):
25  """Sets UWB country code to US if the device does not have it set.
26
27  Note: This intentionally relies on an unstable API (shell command) since we
28  don't want to expose an API that allows users to circumvent the UWB
29  regulatory requirements.
30
31  Args:
32    ad: android device object.
33    handler: callback handler.
34  """
35  if not ad.ranging.isTechnologySupported(RangingTechnology.UWB) and \
36    ad.ranging.isTechnologyEnabled(RangingTechnology.UWB):
37    return
38
39  try:
40    ad.adb.shell(["cmd", "uwb", "force-country-code", "enabled", "US"])
41  except Exception as e:
42    ad.log.warning("Unable to force uwb country code")
43
44  #For Wear OS, this call will not enable uwb. So ignore verification whether the stack was enabled.
45  time.sleep(1)
46
47
48def request_hw_idle_vote(ad: android_device.AndroidDevice, enabled : bool):
49  if ad.uwb.isUwbHwIdleTurnOffEnabled():
50    ad.uwb.requestUwbHwEnabled(enabled)
51
52def _is_technology_state(
53    ad: android_device.AndroidDevice,
54    technology: RangingTechnology,
55    state: bool,
56    timeout_s=WAIT_TIME_SEC,
57) -> bool:
58  """Checks if the provided technology becomes enabled/disabled
59
60  Args:
61
62  ad: android device object.
63  technology: to check for enablement.
64  state: bool, True for on, False for off.
65  timeout_s: how long to wait for enablement before failing, in seconds.
66  """
67  start_time = time.time()
68  while state != ad.ranging.isTechnologyEnabled(technology):
69    if time.time() - start_time > timeout_s:
70      return False
71  return True
72
73
74def is_technology_enabled(
75    ad: android_device.AndroidDevice,
76    technology: RangingTechnology,
77    timeout_s=WAIT_TIME_SEC,
78) -> bool:
79  """Checks if the provided technology becomes enabled
80
81  Args:
82
83  ad: android device object.
84  technology: to check for enablement.
85  timeout_s: how long to wait for enablement before failing, in seconds.
86  """
87  return _is_technology_state(ad, technology, True, timeout_s)
88
89
90def set_airplane_mode(ad: android_device.AndroidDevice, state: bool):
91  """Sets the airplane mode to the given state.
92
93  Args:
94    ad: android device object.
95    state: True for Airplane mode enabled, False for disabled.
96  """
97  ad.ranging.setAirplaneMode(state)
98  start_time = time.time()
99  while get_airplane_mode(ad) != state:
100    time.sleep(0.5)
101    if time.time() - start_time > WAIT_TIME_SEC:
102      asserts.fail(f"Failed to set airplane mode to: {state}")
103
104
105def get_airplane_mode(ad: android_device.AndroidDevice) -> bool:
106  """Gets the current airplane mode setting.
107
108  Args:
109    ad: android device object.
110
111  Returns:
112    True if airplane mode On, False for Off.
113  """
114  state = ad.adb.shell(["settings", "get", "global", "airplane_mode_on"])
115  return bool(int(state.decode().strip()))
116
117def set_uwb_state_and_verify(
118    ad: android_device.AndroidDevice,
119    state: bool
120):
121  """Sets UWB state to on or off and verifies it.
122
123  Args:
124    ad: android device object.
125    state: bool, True for UWB on, False for off.
126  """
127  failure_msg = "enabled" if state else "disabled"
128  ad.uwb.setUwbEnabled(state)
129  asserts.assert_true(_is_technology_state(ad, RangingTechnology.UWB, state, timeout_s=10),
130                      "Uwb is not %s" % failure_msg)
131
132def set_bt_state_and_verify(
133    ad: android_device.AndroidDevice,
134    state: bool
135):
136  """Sets BT state to on or off and verifies it.
137
138  Args:
139    ad: android device object.
140    state: bool, True for BT on, False for off.
141  """
142  failure_msg = "enabled" if state else "disabled"
143  if state and not ad.bluetooth.isBluetoothOn():
144    ad.bluetooth.enableBluetooth()
145    time.sleep(3)
146  elif not state and ad.bluetooth.isBluetoothOn() :
147    ad.bluetooth.disableBluetooth()
148    time.sleep(3)
149  asserts.assert_equal(ad.bluetooth.isBluetoothOn(), state, 'Bluetooth state change failed')
150  # Check for BLE RSSI or BLE CS availability
151  asserts.assert_true(_is_technology_state(ad, RangingTechnology.BLE_RSSI, state, timeout_s=60),
152                      "BT is not %s in ranging API" % failure_msg)
153  ad.bluetooth.reset()
154
155def reset_wifi_state(
156    ad: android_device.AndroidDevice
157):
158  """Reset Wifi state to off and then on before each test.
159
160  Args:
161    ad: android device object.
162  """
163  ad.ranging.setWifiEnabled(False)
164  time.sleep(2)
165  asserts.assert_false(ad.ranging.isWifiEnabled(), 'Wifi did not stop')
166  ad.ranging.setWifiEnabled(True)
167  time.sleep(2)
168  asserts.assert_true(ad.ranging.isWifiEnabled(), 'Wifi did not stop')
169  # Check for WIFI RTT availability
170  asserts.assert_true(_is_technology_state(ad, RangingTechnology.WIFI_RTT, True, timeout_s=60),
171                      "Wifi RTT is not enabled in ranging API")
172
173def set_wifi_state_and_verify(
174    ad: android_device.AndroidDevice,
175    state: bool
176):
177  """Sets Wifi state to on or off and verifies it.
178
179  Args:
180    ad: android device object.
181    state: bool, True for BT on, False for off.
182  """
183  failure_msg = "enabled" if state else "disabled"
184  ad.ranging.setWifiEnabled(state)
185  time.sleep(1)
186  asserts.assert_equal(ad.ranging.isWifiEnabled(), state, 'Wifi state change failed')
187  # Check for WIFI RTT availability
188  asserts.assert_true(_is_technology_state(ad, RangingTechnology.WIFI_RTT, state, timeout_s=60),
189                      "Wifi RTT is not %s in ranging API" % failure_msg)
190
191
192def set_screen_rotation_landscape(
193    ad: android_device.AndroidDevice, isLandscape: bool
194):
195  """Sets screen orientation to landscape or portrait mode.
196
197  Args:
198    ad: android device object.
199    isLandscape: True for landscape mode, False for potrait.
200  """
201  ad.adb.shell(["settings", "put", "system", "accelerometer_rotation", "0"])
202  ad.adb.shell([
203      "settings",
204      "put",
205      "system",
206      "user_rotation",
207      "1" if isLandscape else "0",
208  ])
209
210
211def set_snippet_foreground_state(
212    ad: android_device.AndroidDevice, isForeground: bool
213):
214  """Sets the snippet app's foreground/background state.
215
216  Args:
217    ad: android device object.
218    isForeground: True to move snippet to foreground, False for background.
219  """
220  ad.adb.shell([
221      "cmd",
222      "uwb",
223      "simulate-app-state-change",
224      "com.google.snippet.ranging",
225      "foreground" if isForeground else "background",
226  ])
227
228
229def set_screen_state(
230    ad: android_device.AndroidDevice, on: bool
231):
232  """Sets the device screen state on/off.
233
234  Args:
235    ad: android device object.
236    on: True for screen on, False for screen off.
237  """
238  ad.adb.shell([
239      "svc", "power", "stayon", "true" if on else "false",
240  ])
241