code: def _execute_and_process_stdout(self, args, shell, handler):
          
          proc = subprocess.Popen(
              args,
              stdout=subprocess.PIPE,
              stderr=subprocess.PIPE,
              shell=shell,
              bufsize=1)
          out = '[elided, processed via handler]'
          try:
              # Even if the process dies, stdout.readline still works
              # and will continue until it runs out of stdout to process.
              while True:
                  line = proc.stdout.readline()
                  if line:
                      handler(line)
                  else:
                      break
          finally:
              # Note, communicate will not contain any buffered output.
              (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',
                        utils.cli_cmd_to_string(args), out, err, ret)
          if ret == 0:
              return err
          else:
              raise AdbError(cmd=args, stdout=out, stderr=err, ret_code=ret)
docs: Executes adb commands and processes the stdout with a handler.
  
          Args:
              args: string or list of strings, program arguments.
                  See subprocess.Popen() documentation.
              shell: bool, True to run this command through the system shell,
                  False to invoke it directly. See subprocess.Popen() docs.
              handler: func, a function to handle adb stdout line by line.
  
          Returns:
              The stderr of the adb command run if exit code is 0.
  
          Raises:
              AdbError: The adb command exit code is not 0.