| # Copyright (C) 2024 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 re | |
| from mobly.controllers import android_device | |
| from net_tests_utils.host.python import assert_utils | |
| BYTE_DECODE_UTF_8 = "utf-8" | |
| def set_doze_mode(ad: android_device.AndroidDevice, enable: bool) -> None: | |
| if enable: | |
| adb_shell(ad, "cmd battery unplug") | |
| expect_dumpsys_state_with_retry( | |
| ad, "deviceidle", key="mCharging", expected_state=False | |
| ) | |
| _set_screen_state(ad, False) | |
| adb_shell(ad, "dumpsys deviceidle enable deep") | |
| expect_dumpsys_state_with_retry( | |
| ad, "deviceidle", key="mDeepEnabled", expected_state=True | |
| ) | |
| adb_shell(ad, "dumpsys deviceidle force-idle deep") | |
| expect_dumpsys_state_with_retry( | |
| ad, "deviceidle", key="mForceIdle", expected_state=True | |
| ) | |
| else: | |
| adb_shell(ad, "cmd battery reset") | |
| expect_dumpsys_state_with_retry( | |
| ad, "deviceidle", key="mCharging", expected_state=True | |
| ) | |
| adb_shell(ad, "dumpsys deviceidle unforce") | |
| expect_dumpsys_state_with_retry( | |
| ad, "deviceidle", key="mForceIdle", expected_state=False | |
| ) | |
| def _set_screen_state( | |
| ad: android_device.AndroidDevice, target_state: bool | |
| ) -> None: | |
| assert_utils.expect_with_retry( | |
| predicate=lambda: _get_screen_state(ad) == target_state, | |
| retry_action=lambda: adb_shell( | |
| ad, "input keyevent KEYCODE_POWER" | |
| ), # Toggle power key again when retry. | |
| ) | |
| def _get_screen_state(ad: android_device.AndroidDevice) -> bool: | |
| return get_value_of_key_from_dumpsys(ad, "power", "mWakefulness") == "Awake" | |
| def get_value_of_key_from_dumpsys( | |
| ad: android_device.AndroidDevice, service: str, key: str | |
| ) -> str: | |
| output = get_dumpsys_for_service(ad, service) | |
| # Search for key=value pattern from the dumpsys output. | |
| # e.g. mWakefulness=Awake | |
| pattern = rf"{key}=(.*)" | |
| # Only look for the first occurrence. | |
| match = re.search(pattern, output) | |
| if match: | |
| ad.log.debug( | |
| "Getting key-value from dumpsys: " + key + "=" + match.group(1) | |
| ) | |
| return match.group(1) | |
| else: | |
| return None | |
| def expect_dumpsys_state_with_retry( | |
| ad: android_device.AndroidDevice, | |
| service: str, | |
| key: str, | |
| expected_state: bool, | |
| retry_interval_sec: int = 1, | |
| ) -> None: | |
| def predicate(): | |
| value = get_value_of_key_from_dumpsys(ad, service, key) | |
| if value is None: | |
| return False | |
| return value.lower() == str(expected_state).lower() | |
| assert_utils.expect_with_retry( | |
| predicate=predicate, | |
| retry_interval_sec=retry_interval_sec, | |
| ) | |
| def get_dumpsys_for_service( | |
| ad: android_device.AndroidDevice, service: str | |
| ) -> str: | |
| return adb_shell(ad, "dumpsys " + service) | |
| def adb_shell(ad: android_device.AndroidDevice, shell_cmd: str) -> str: | |
| """Runs adb shell command. | |
| Args: | |
| ad: Android device object. | |
| shell_cmd: string of list of strings, adb shell command. | |
| Returns: | |
| string, replies from adb shell command. | |
| """ | |
| ad.log.debug("Executing adb shell %s", shell_cmd) | |
| data = ad.adb.shell(shell_cmd) | |
| return data.decode(BYTE_DECODE_UTF_8).strip() |