diff --git a/adbutils/shell.py b/adbutils/shell.py index e3a1ae5..46076c8 100644 --- a/adbutils/shell.py +++ b/adbutils/shell.py @@ -7,6 +7,7 @@ import abc import datetime import json +import logging import re import time from typing import List, Optional, Union @@ -17,6 +18,8 @@ from adbutils.sync import Sync +logger = logging.getLogger(__name__) + _DISPLAY_RE = re.compile( r".*DisplayViewport{.*?valid=true, .*?orientation=(?P\d+), .*?deviceWidth=(?P\d+), deviceHeight=(?P\d+).*" ) @@ -104,34 +107,45 @@ def switch_wifi(self, enable: bool): def window_size(self) -> WindowSize: """ - Return screen (width, height) + Return screen (width, height) in pixel, width and height will be swapped if rotation is 90 or 270 - Virtual keyborad may get small d.info['displayHeight'] + Returns: + WindowSize + + Raises: + AdbError """ - w, h = self._raw_window_size() - s, l = min(w, h), max(w, h) - horizontal = self.rotation() % 2 == 1 - return WindowSize(l, s) if horizontal else WindowSize(s, l) - - def _raw_window_size(self) -> WindowSize: + try: + logger.debug("get window size from 'dumpsys display'") + return self._dumpsys_window_size() + except AdbError: + logger.debug("get window size from 'wm size'") + wsize = self._wm_size() + horizontal = self.rotation() % 2 == 1 + return WindowSize(wsize.height, wsize.width) if horizontal else wsize + + def _dumpsys_window_size(self) -> WindowSize: + output = self.shell("dumpsys display") + for line in output.splitlines(): + m = _DISPLAY_RE.search(line, 0) + if not m: + continue + w = int(m.group("width")) + h = int(m.group("height")) + return WindowSize(w, h) + raise AdbError("get window size from 'dumpsys display' failed", output) + + def _wm_size(self) -> WindowSize: output = self.shell("wm size") o = re.search(r"Override size: (\d+)x(\d+)", output) - m = re.search(r"Physical size: (\d+)x(\d+)", output) if o: w, h = o.group(1), o.group(2) return WindowSize(int(w), int(h)) - elif m: + m = re.search(r"Physical size: (\d+)x(\d+)", output) + if m: w, h = m.group(1), m.group(2) return WindowSize(int(w), int(h)) - - for line in self.shell("dumpsys display").splitlines(): - m = _DISPLAY_RE.search(line, 0) - if not m: - continue - w = int(m.group("width")) - h = int(m.group("height")) - return WindowSize(w, h) - raise AdbError("get window size failed") + raise AdbError("wm size output unexpected", output) def swipe(self, sx, sy, ex, ey, duration: float = 1.0) -> None: """ @@ -205,23 +219,11 @@ def rotation(self) -> int: int [0, 1, 2, 3] """ for line in self.shell("dumpsys display").splitlines(): - m = _DISPLAY_RE.search(line, 0) + m = re.search(r".*?orientation=(?P\d+)", line) if not m: continue o = int(m.group("orientation")) return int(o) - - output = self.shell( - "LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -i" - ) - try: - if output.startswith("INFO:"): - output = output[output.index("{"):] - data = json.loads(output) - return data["rotation"] / 90 - except ValueError: - pass - raise AdbError("rotation get failed") def remove(self, path: str): diff --git a/tests/test_adb_shell.py b/tests/test_adb_shell.py index a383e32..c1d04da 100644 --- a/tests/test_adb_shell.py +++ b/tests/test_adb_shell.py @@ -38,6 +38,22 @@ def mock_shell(cmd: str, encoding='utf-8', **kwargs): assert pixel[:3] == (0, 0, 0) +def test_window_size(adb: adbutils.AdbClient): + d = adb.device(serial="123456") + + def mock_shell(cmd): + if cmd == "wm size": + return "Physical size: 1080x1920" + if cmd == "dumpsys display": + return "mViewports=[DisplayViewport{orientation=0]" + return "" + + d.shell = mock_shell + wsize = d.window_size() + assert wsize.width == 1080 + assert wsize.height == 1920 + + def test_shell_battery(adb: adbutils.AdbClient): d = adb.device(serial="123456")