xpconanfan: I don't see how this is related to logging stderr as the issue described.
One of the msg is incorrect?

---

Review status: 0 of 2 files reviewed at latest revision, all discussions resolved.

---

*[mobly/controllers/android_device_lib/adb.py, line 215 at r1](https://reviewable.io/reviews/google/mobly/453#-LDIjCGd2zhkKzp2ablH:-LDIjCGd2zhkKzp2ablI:b-x8c38) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/mobly/controllers/android_device_lib/adb.py#L215)):*
> ```Python
>                     break
>         finally:
>             (unhandled_out, err) = proc.communicate()
> ```

wait, so this does happen?
shouldn't we call the handler with this out instead?

---


*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453#-:-LDIjnBO4MUgZxYNImBt:blud5im)*
<!-- Sent from Reviewable.io -->

winterfroststrom: 



Review status: 0 of 2 files reviewed at latest revision, 1 unresolved discussion.

---

*[mobly/controllers/android_device_lib/adb.py, line 215 at r1](https://reviewable.io/reviews/google/mobly/453#-LDIjCGd2zhkKzp2ablH:-LDIkOBz8aQLOE0ovB8O:brjczjz) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/mobly/controllers/android_device_lib/adb.py#L215)):*
<details><summary><i>Previously, xpconanfan (Ang Li) wrote…</i></summary><blockquote>

wait, so this does happen?
shouldn't we call the handler with this out instead?
</blockquote></details>

I'm not sure?
I'm adding logging here first to try to determine what the underlying problem is

---


*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453)*
<!-- Sent from Reviewable.io -->

xpconanfan: 



Review status: 0 of 2 files reviewed at latest revision, 1 unresolved discussion.

---

*[mobly/controllers/android_device_lib/adb.py, line 215 at r1](https://reviewable.io/reviews/google/mobly/453#-LDIjCGd2zhkKzp2ablH:-LDIl2971UfZ3LqypsHv:b332s67) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/mobly/controllers/android_device_lib/adb.py#L215)):*
<details><summary><i>Previously, winterfroststrom wrote…</i></summary><blockquote>

I'm not sure?
I'm adding logging here first to try to determine what the underlying problem is
</blockquote></details>

seems like we should pipe all stdout content through the handler as this function promised?
you could add additional logging to signify the existence of stdout from `communicate`?

---


*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453)*
<!-- Sent from Reviewable.io -->

xpconanfan: 



Review status: 0 of 2 files reviewed at latest revision, 1 unresolved discussion.

---

*[tests/mobly/controllers/android_device_lib/adb_test.py, line 156 at r1](https://reviewable.io/reviews/google/mobly/453#-LDImOOR-GL1gRhihxxl:-LDImOOR-GL1gRhihxxm:ba86vyn) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/tests/mobly/controllers/android_device_lib/adb_test.py#L156)):*
> ```Python
>     def test_execute_and_process_stdout_logs_cmd(self, mock_debug_logger,
>                                                  mock_popen):
>         self._mock_execute_and_process_stdout_process(mock_popen)
> ```

this test is relying on the default mock stdout value in `_mock_execute_and_process_stdout_process`, which is difficult to read.
Can we more explicitly set the mock value within the test?

---


*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453)*
<!-- Sent from Reviewable.io -->

winterfroststrom: 



Review status: 0 of 2 files reviewed at latest revision, 2 unresolved discussions.

---

*[mobly/controllers/android_device_lib/adb.py, line 215 at r1](https://reviewable.io/reviews/google/mobly/453#-LDIjCGd2zhkKzp2ablH:-LDIsvuPD4jS9CVrpnr5:bcy1d3j) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/mobly/controllers/android_device_lib/adb.py#L215)):*
<details><summary><i>Previously, xpconanfan (Ang Li) wrote…</i></summary><blockquote>

seems like we should pipe all stdout content through the handler as this function promised?
you could add additional logging to signify the existence of stdout from `communicate`?
</blockquote></details>

So, I've never seen this output actually get populated and I'm not sure it is in the case I'm debugging, but okay.

I'm preferring changing the logged command because otherwise you'd get semi-duplicate log lines.

---

*[tests/mobly/controllers/android_device_lib/adb_test.py, line 156 at r1](https://reviewable.io/reviews/google/mobly/453#-LDImOOR-GL1gRhihxxl:-LDItG5yEIdICTRzP1c0:b-896fix) ([raw file](https://github.com/google/mobly/blob/73f94e45966ec8566eabae03fc00893e5a13ee33/tests/mobly/controllers/android_device_lib/adb_test.py#L156)):*
<details><summary><i>Previously, xpconanfan (Ang Li) wrote…</i></summary><blockquote>

this test is relying on the default mock stdout value in `_mock_execute_and_process_stdout_process`, which is difficult to read.
Can we more explicitly set the mock value within the test?
</blockquote></details>

Done.

---


*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453)*
<!-- Sent from Reviewable.io -->

xpconanfan: <img class="emoji" title=":lgtm:" alt=":lgtm:" align="absmiddle" src="https://reviewable.io/lgtm.png" height="20" width="61"/>

---

Review status: 0 of 2 files reviewed at latest revision, all discussions resolved.

---



*Comments from [Reviewable](https://reviewable.io/reviews/google/mobly/453#-:-LEBweyyBV-cQJiSKgM7:bnfp4nl)*
<!-- Sent from Reviewable.io -->

diff --git a/mobly/controllers/android_device_lib/adb.py b/mobly/controllers/android_device_lib/adb.py
index 90dcd0b..95d1261 100644
--- a/mobly/controllers/android_device_lib/adb.py
+++ b/mobly/controllers/android_device_lib/adb.py
@@ -203,6 +203,7 @@ class AdbProxy(object):
             stderr=subprocess.PIPE,
             shell=shell,
             bufsize=1)
+        out = '[elided, processed via handler]'
         try:
             while proc.poll() is None:
                 line = proc.stdout.readline()
@@ -211,16 +212,19 @@ class AdbProxy(object):
                 else:
                     break
         finally:
-            (_, err) = proc.communicate()
+            (unexpected_out, err) = proc.communicate()
+            if unexpected_out:
+                out = '[unexpected stdout] %s' % unexpected_out
+                for line in unexpected_out.splitlines():
+                    handler(line)
+
         ret = proc.returncode
+        logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
+                      cli_cmd_to_string(args), out, err, ret)
         if ret == 0:
             return err
         else:
-            raise AdbError(
-                cmd=args,
-                stdout='[elided, processed via handler]',
-                stderr=err,
-                ret_code=ret)
+            raise AdbError(cmd=args, stdout=out, stderr=err, ret_code=ret)
 
     def _construct_adb_cmd(self, raw_name, args, shell):
         """Constructs an adb command with arguments for a subprocess call.
diff --git a/mobly/controllers/android_device_lib/snippet_client.py b/mobly/controllers/android_device_lib/snippet_client.py
index e3e835d..03674ff 100644
--- a/mobly/controllers/android_device_lib/snippet_client.py
+++ b/mobly/controllers/android_device_lib/snippet_client.py
@@ -125,8 +125,7 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
 
         # Yaaay! We're done!
         self.log.debug('Snippet %s started after %.1fs on host port %s',
-                       self.package,
-                       time.time() - start_time, self.host_port)
+                       self.package, time.time() - start_time, self.host_port)
 
     def restore_app_connection(self, port=None):
         """Restores the app after device got reconnected.
@@ -151,12 +150,13 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
         try:
             self.connect()
         except:
-            # Failed to connect to app, something went wrong.
+            # Log the original error and raise AppRestoreConnectionError.
+            self.log.exception('Failed to re-connect to app.')
             raise jsonrpc_client_base.AppRestoreConnectionError(
-                self._ad(
-                    'Failed to restore app connection for %s at host port %s, '
-                    'device port %s'), self.package, self.host_port,
-                self.device_port)
+                self._ad,
+                ('Failed to restore app connection for %s at host port %s, '
+                 'device port %s') % (self.package, self.host_port,
+                                      self.device_port))
 
         # Because the previous connection was lost, update self._proc
         self._proc = None

`_execute_and_process_stdout` should log cmd
diff --git a/tests/mobly/controllers/android_device_lib/adb_test.py b/tests/mobly/controllers/android_device_lib/adb_test.py
index 1c75a9d..8dec8aa 100755
--- a/tests/mobly/controllers/android_device_lib/adb_test.py
+++ b/tests/mobly/controllers/android_device_lib/adb_test.py
@@ -76,8 +76,7 @@ class AdbTest(unittest.TestCase):
         mock_popen.return_value.stdout.readline.side_effect = ['']
 
         mock_proc.communicate = mock.Mock(
-            return_value=(MOCK_DEFAULT_STDOUT.encode('utf-8'),
-                          MOCK_DEFAULT_STDERR.encode('utf-8')))
+            return_value=('', MOCK_DEFAULT_STDERR.encode('utf-8')))
         mock_proc.returncode = 0
         return mock_popen
 
@@ -150,6 +149,57 @@ class AdbTest(unittest.TestCase):
         mock_handler.assert_any_call('1')
         mock_handler.assert_any_call('2')
 
+    @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
+    def test_execute_and_process_stdout_reads_unexpected_stdout(
+            self, mock_popen):
+        unexpected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8')
+
+        self._mock_execute_and_process_stdout_process(mock_popen)
+        mock_handler = mock.MagicMock()
+        mock_popen.return_value.communicate = mock.Mock(
+            return_value=(unexpected_stdout, MOCK_DEFAULT_STDERR.encode(
+                'utf-8')))
+
+        err = adb.AdbProxy()._execute_and_process_stdout(
+            ['fake_cmd'], shell=False, handler=mock_handler)
+        self.assertEqual(mock_handler.call_count, 1)
+        mock_handler.assert_called_with(unexpected_stdout)
+
+    @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
+    @mock.patch('logging.debug')
+    def test_execute_and_process_stdout_logs_cmd(self, mock_debug_logger,
+                                                 mock_popen):
+        raw_expected_stdout = ''
+        expected_stdout = '[elided, processed via handler]'
+        expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8')
+        self._mock_execute_and_process_stdout_process(mock_popen)
+        mock_popen.return_value.communicate = mock.Mock(
+            return_value=(raw_expected_stdout, expected_stderr))
+
+        err = adb.AdbProxy()._execute_and_process_stdout(
+            ['fake_cmd'], shell=False, handler=mock.MagicMock())
+        mock_debug_logger.assert_called_with(
+            'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd',
+            expected_stdout, expected_stderr, 0)
+
+    @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
+    @mock.patch('logging.debug')
+    def test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout(
+            self, mock_debug_logger, mock_popen):
+        raw_expected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8')
+        expected_stdout = '[unexpected stdout] %s' % raw_expected_stdout
+        expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8')
+
+        self._mock_execute_and_process_stdout_process(mock_popen)
+        mock_popen.return_value.communicate = mock.Mock(
+            return_value=(raw_expected_stdout, expected_stderr))
+
+        err = adb.AdbProxy()._execute_and_process_stdout(
+            ['fake_cmd'], shell=False, handler=mock.MagicMock())
+        mock_debug_logger.assert_called_with(
+            'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd',
+            expected_stdout, expected_stderr, 0)
+
     @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
     def test_execute_and_process_stdout_when_cmd_exits(self, mock_popen):
         self._mock_execute_and_process_stdout_process(mock_popen)
diff --git a/tests/mobly/controllers/android_device_lib/snippet_client_test.py b/tests/mobly/controllers/android_device_lib/snippet_client_test.py
index 2c875d8..d964ae3 100755
--- a/tests/mobly/controllers/android_device_lib/snippet_client_test.py
+++ b/tests/mobly/controllers/android_device_lib/snippet_client_test.py
@@ -166,6 +166,15 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
         self.assertEqual(789, callback._event_client.host_port)
         self.assertEqual(456, callback._event_client.device_port)
 
+        # if unable to reconnect for any reason, a
+        # jsonrpc_client_base.AppRestoreConnectionError is raised.
+        mock_create_connection.side_effect = IOError('socket timed out')
+        with self.assertRaisesRegex(
+                jsonrpc_client_base.AppRestoreConnectionError,
+            ('Failed to restore app connection for %s at host port %s, '
+             'device port %s') % (MOCK_PACKAGE_NAME, 789, 456)):
+            client.restore_app_connection()
+
     @mock.patch('socket.create_connection')
     @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
                 'utils.start_standing_subprocess')

pip install -e .[dev]
parse_log_pytest
pytest
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
coverage==7.8.0
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
execnet==2.1.1
future==1.0.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
-e git+https://github.com/google/mobly.git@f1aff6a7f06887424759e3c192b1bf6e13d2a6bf#egg=mobly
mock==1.0.1
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
portpicker==1.6.0
psutil==7.0.0
pyserial==3.5
pytest @ file:///croot/pytest_1738938843180/work
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-xdist==3.6.1
pytz==2025.2
PyYAML==6.0.2
timeout-decorator==0.5.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions==4.13.0

name: mobly
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.8.0
      - execnet==2.1.1
      - future==1.0.0
      - mock==1.0.1
      - portpicker==1.6.0
      - psutil==7.0.0
      - pyserial==3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - pytz==2025.2
      - pyyaml==6.0.2
      - timeout-decorator==0.5.0
      - typing-extensions==4.13.0
prefix: /opt/conda/envs/mobly

tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_logs_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_reads_unexpected_stdout tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_restore_event_client
tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_cli_cmd_to_string tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_arg_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_arg_command_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_serial_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_auto_quotes tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_arg_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_arg_command_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_serial_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_special_characters tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_formats_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_formats_command_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_with_stderr_pipe tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_error_no_timeout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_no_timeout_success tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_timed_out tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_with_negative_timeout_value tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_with_timeout_success tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_adb_and_process_stdout_formats_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_raises_adb_error tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_reads_stdout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_returns_stderr tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_when_cmd_eof tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_when_cmd_exits tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_when_handler_crash tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_forward tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_called_correctly tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_existing_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_missing_command_on_newer_devices tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_missing_command_on_older_devices tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler_with_options tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler_with_runner tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_options tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_runner tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_without_parameters tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_check_app_installed_fail_app_not_installed tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_check_app_installed_fail_not_instrumented tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_check_app_installed_fail_target_not_installed tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_check_app_installed_normal tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_and_connect tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_and_connect_header_junk tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_and_connect_no_valid_line tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_and_connect_persistent_session tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_and_connect_unknown_protocol tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_app_crash tests/mobly/controllers/android_device_lib/snippet_client_test.py::SnippetClientTest::test_snippet_start_event_client
mobly/controllers/android_device_lib/snippet_client.py mobly/controllers/android_device_lib/adb.py
mobly/controllers/android_device_lib/snippet_client.py mobly/controllers/android_device_lib/adb.py