JeffLIrion / adb_shell

A Python implementation of ADB with shell and FileSync functionality.
Apache License 2.0
530 stars 60 forks source link

Unable to yield from a second AdbDevice.streaming_shell on the same AdbDevice #143

Closed ggallo closed 2 years ago

ggallo commented 3 years ago

I have a routine looking for events. I'm mapping user input on the screen to a series of well-defined actions ("swipe left", etc.). I want a streaming_shell() for each gesture so I can delineate between them.

for g in gesture:
    print("record the {} gesture".format(g))
    gesture_stream = device.streaming_shell('getevent -t -q')
    while True:
        try:
            events = process_getevent(next(gesture_stream))
            # ... process events ...
        except adb_shell.exceptions.TcpTimeoutException:
            # Events have dried up and/or we timed out
            break

It goes through the first gesture just fine, but on the second gesture it errors at the next(). Here is the output:

Traceback (most recent call last):
  File "/home/ggallo/.pyenv/versions/3.9.1/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/ggallo/.pyenv/versions/3.9.1/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/ggallo/mytest.py", line 186, in <module>
    exit(main(sys.argv[1:]))
  File "/home/ggallo/mytest.py", line 177, in main
    record_gestures(device, ident, args.gestures)
  File "/home/ggallo/mytest.py", line 140, in record_gestures
    events = process_getevent(next(gesture_stream))
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 441, in streaming_shell
    for line in self._streaming_service(b'shell', command.encode('utf8'), transport_timeout_s, read_timeout_s, decode):
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 362, in _streaming_service
    for line in (stream_line.decode('utf8') for stream_line in stream):
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 362, in <genexpr>
    for line in (stream_line.decode('utf8') for stream_line in stream):
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 965, in _streaming_command
    for data in self._read_until_close(adb_info):
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 900, in _read_until_close
    cmd, data = self._read_until([constants.CLSE, constants.WRTE], adb_info)
  File "/home/ggallo/venv/lib/python3.9/site-packages/adb_shell/adb_device.py", line 870, in _read_until
    raise exceptions.InvalidResponseError('Incorrect remote id, expected {0} got {1}'.format(adb_info.remote_id, remote_id2))
adb_shell.exceptions.InvalidResponseError: Incorrect remote id, expected 177 got 176

I can open two non-streaming shells in a row and run commands without incident. Of course this won't work for my use case, because I'm waiting on input, but it's just to show that shell() doesn't have the same problem.

# adb_test.py
... other prep ...
d = AdbDeviceTcp(ip, port)
d.connect(rsa_keys=[signer])
print(d.shell('echo hello'))
print(d.shell('echo world'))

$ python adb_test.py 
hello

world

$

Is this intended behavior? Are we meant to close the entire TCP cxn and retry for each streaming shell? (This isn't asked to be snarky, I haven't done much serious shell-adjacent programming in some time and am very rusty.)

JeffLIrion commented 3 years ago

That shouldn't happen. Can you try this branch and see if the issue is fixed: https://github.com/JeffLIrion/adb_shell/tree/streaming-shell-fix

JeffLIrion commented 3 years ago

You can install that branch via:

pip install https://github.com/JeffLIrion/adb_shell/archive/streaming-shell-fix.zip
JeffLIrion commented 3 years ago

You can install that branch via:

pip install https://github.com/JeffLIrion/adb_shell/archive/streaming-shell-fix.zip

@ggallo any feedback on whether this fixes the issue?

ggallo commented 3 years ago

@JeffLIrion I haven't forgotten about this! Sadly I am blocked by what appears to be a similar issue over at #152 (see comment there)

JeffLIrion commented 3 years ago

@ggallo this pull request should fix the issue: https://github.com/JeffLIrion/adb_shell/pull/172

I think it will fix #152, too.

You can install that branch via

pip install https://github.com/JeffLIrion/adb_shell/archive/support-multiple-streams.zip
JeffLIrion commented 3 years ago

This should be fixed in the latest release (0.4.0).

pip install -U adb-shell