def check_okay(self): data = self.read(4) if data == _FAIL: raise AdbError(self.read_string()) elif data == _OKAY: return raise AdbError("Unknown data: %s" % data)
def iter_content(self, path: str): with self._prepare_sync(path, "RECV") as c: while True: cmd = c.read(4) if cmd == _FAIL: str_size = struct.unpack("<I", c.read_raw(4))[0] error_message = c.read(str_size) raise AdbError(error_message) elif cmd == _DONE: break elif cmd == _DATA: chunk_size = struct.unpack("<I", c.read_raw(4))[0] chunk = c.read_raw(chunk_size) if len(chunk) != chunk_size: raise RuntimeError("read chunk missing") yield chunk else: raise AdbError("Invalid sync cmd", cmd)
def read_string(self) -> str: """ Raises: AdbError """ length = self.read(4) if not length: raise AdbError("connection closed") size = int(length, 16) return self.read(size)
def _raw_window_size(self) -> WindowSize: output = self.shell("wm size") 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")
def rotation(self) -> int: """ Returns: int [0, 1, 2, 3] """ for line in self.shell('dumpsys display').splitlines(): m = _DISPLAY_RE.search(line, 0) 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: data = json.loads(output) return data['rotation'] / 90 except ValueError: pass raise AdbError("rotation get failed")
def current_app(self): """ Returns: dict(package, activity, pid?) Raises: AdbError """ # Related issue: https://github.com/openatx/uiautomator2/issues/200 # $ adb shell dumpsys window windows # Example output: # mCurrentFocus=Window{41b37570 u0 com.incall.apps.launcher/com.incall.apps.launcher.Launcher} # mFocusedApp=AppWindowToken{422df168 token=Token{422def98 ActivityRecord{422dee38 u0 com.example/.UI.play.PlayActivity t14}}} # Regexp # r'mFocusedApp=.*ActivityRecord{\w+ \w+ (?P<package>.*)/(?P<activity>.*) .*' # r'mCurrentFocus=Window{\w+ \w+ (?P<package>.*)/(?P<activity>.*)\}') _focusedRE = re.compile( r'mCurrentFocus=Window{.*\s+(?P<package>[^\s]+)/(?P<activity>[^\s]+)\}' ) m = _focusedRE.search(self._run(['dumpsys', 'window', 'windows'])) if m: return dict( package=m.group('package'), activity=m.group('activity')) # try: adb shell dumpsys activity top _activityRE = re.compile( r'ACTIVITY (?P<package>[^\s]+)/(?P<activity>[^/\s]+) \w+ pid=(?P<pid>\d+)' ) output = self._run(['dumpsys', 'activity', 'top']) ms = _activityRE.finditer(output) ret = None for m in ms: ret = dict( package=m.group('package'), activity=m.group('activity'), pid=int(m.group('pid'))) if ret: # get last result return ret raise AdbError("Couldn't get focused app")
def push(self, src: typing.Union[pathlib.Path, str, bytes, bytearray, typing.BinaryIO], dst: str, mode: int = 0o755, check: bool = False) -> int: # IFREG: File Regular # IFDIR: File Directory if isinstance(src, pathlib.Path): src = src.open("rb") elif isinstance(src, str): src = pathlib.Path(src).open("rb") elif isinstance(src, (bytes, bytearray)): src = io.BytesIO(src) else: if not hasattr(src, "read"): raise TypeError("Invalid src type: %s" % type(src)) path = dst + "," + str(stat.S_IFREG | mode) total_size = 0 with self._prepare_sync(path, "SEND") as c: r = src if hasattr(src, "read") else open(src, "rb") try: while True: chunk = r.read(4096) if not chunk: mtime = int(datetime.datetime.now().timestamp()) c.conn.send(b"DONE" + struct.pack("<I", mtime)) break c.conn.send(b"DATA" + struct.pack("<I", len(chunk))) c.conn.send(chunk) total_size += len(chunk) assert c.read_string(4) == _OKAY finally: if hasattr(r, "close"): r.close() if check: file_size = self.stat(dst).size if total_size != file_size: raise AdbError("Push not complete, expect pushed %d, actually pushed %d" % (total_size, file_size)) return total_size