Do not add `--user` in snippet commands for SDK < 24. (#653)

diff --git a/mobly/controllers/android_device_lib/snippet_client.py b/mobly/controllers/android_device_lib/snippet_client.py
index 218ef46..735a921 100644
--- a/mobly/controllers/android_device_lib/snippet_client.py
+++ b/mobly/controllers/android_device_lib/snippet_client.py
@@ -40,10 +40,10 @@
 _PROTOCOL_MINOR_VERSION = 0
 
 _LAUNCH_CMD = (
-    '{shell_cmd} am instrument --user {user} -w -e action start {snippet_package}/'
-    + _INSTRUMENTATION_RUNNER_PACKAGE)
+    '{shell_cmd} am instrument {user} -w -e action start {snippet_package}/' +
+    _INSTRUMENTATION_RUNNER_PACKAGE)
 
-_STOP_CMD = ('am instrument -w -e action stop %s/' +
+_STOP_CMD = ('am instrument {user} -w -e action stop {snippet_package}/' +
              _INSTRUMENTATION_RUNNER_PACKAGE)
 
 # Test that uses UiAutomation requires the shell session to be maintained while
@@ -109,6 +109,23 @@
         """
         return self._conn is not None
 
+    def _get_user_command_string(self):
+        """Gets the appropriate command argument for specifying user IDs.
+
+        By default, `SnippetClient` operates within the current user.
+
+        We don't add the `--user {ID}` arg when Android's SDK is below 24,
+        where multi-user support is not well implemented.
+
+        Returns:
+            String, the command param section to be formatted into the adb
+            commands.
+        """
+        sdk_int = int(self._ad.build_info['build_version_sdk'])
+        if sdk_int < 24:
+            return ''
+        return '--user %s' % self._adb.current_user_id
+
     def start_app_and_connect(self):
         """Starts snippet apk on the device and connects to it.
 
@@ -157,7 +174,7 @@
                       self.package, _PROTOCOL_MAJOR_VERSION,
                       _PROTOCOL_MINOR_VERSION)
         cmd = _LAUNCH_CMD.format(shell_cmd=persists_shell_cmd,
-                                 user=self._adb.current_user_id,
+                                 user=self._get_user_command_string(),
                                  snippet_package=self.package)
         start_time = time.time()
         self._proc = self._do_start_app(cmd)
@@ -234,7 +251,10 @@
             if self._proc:
                 utils.stop_standing_subprocess(self._proc)
             self._proc = None
-            out = self._adb.shell(_STOP_CMD % self.package).decode('utf-8')
+            out = self._adb.shell(
+                _STOP_CMD.format(
+                    snippet_package=self.package,
+                    user=self._get_user_command_string())).decode('utf-8')
             if 'OK (0 tests)' not in out:
                 raise errors.DeviceError(
                     self._ad,
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 fa5b9fb..cb62345 100755
--- a/tests/mobly/controllers/android_device_lib/snippet_client_test.py
+++ b/tests/mobly/controllers/android_device_lib/snippet_client_test.py
@@ -293,6 +293,48 @@
                 'SnippetClient.connect')
     @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
                 'utils.get_available_host_port')
+    def test_snippet_start_on_sdk_21(self, mock_get_port, mock_connect,
+                                     mock_read_protocol_line,
+                                     mock_check_app_installed,
+                                     mock_do_start_app):
+        """Check that `--user` is not added to start command on SDK < 24."""
+
+        def _mocked_shell(arg):
+            if 'setsid' in arg:
+                raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code')
+            else:
+                return b'nohup'
+
+        mock_get_port.return_value = 123
+        mock_read_protocol_line.side_effect = [
+            'SNIPPET START, PROTOCOL 1 234',
+            'SNIPPET SERVING, PORT 1234',
+            'SNIPPET START, PROTOCOL 1 234',
+            'SNIPPET SERVING, PORT 1234',
+            'SNIPPET START, PROTOCOL 1 234',
+            'SNIPPET SERVING, PORT 1234',
+        ]
+
+        # Test 'setsid' exists
+        client = self._make_client()
+        client._ad.build_info['build_version_sdk'] = 21
+        client._adb.shell = mock.Mock(return_value=b'setsid')
+        client.start_app_and_connect()
+        cmd_setsid = '%s am instrument  -w -e action start %s/%s' % (
+            snippet_client._SETSID_COMMAND, MOCK_PACKAGE_NAME,
+            snippet_client._INSTRUMENTATION_RUNNER_PACKAGE)
+        mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)])
+
+    @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
+                'SnippetClient._do_start_app')
+    @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
+                'SnippetClient._check_app_installed')
+    @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
+                'SnippetClient._read_protocol_line')
+    @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
+                'SnippetClient.connect')
+    @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
+                'utils.get_available_host_port')
     def test_snippet_start_app_and_connect_persistent_session(
             self, mock_get_port, mock_connect, mock_read_protocol_line,
             mock_check_app_installed, mock_do_start_app):