diff --git a/adb_client/src/device/commands/shell.rs b/adb_client/src/device/commands/shell.rs index 895d928..12158f2 100644 --- a/adb_client/src/device/commands/shell.rs +++ b/adb_client/src/device/commands/shell.rs @@ -1,4 +1,5 @@ use std::io::{ErrorKind, Read, Write}; +use std::time::Duration; use crate::Result; use crate::device::ShellMessageWriter; @@ -12,6 +13,11 @@ impl ADBMessageDevice { pub(crate) fn shell_command(&mut self, command: &[&str], output: &mut dyn Write) -> Result<()> { let response = self.open_session(format!("shell:{}\0", command.join(" "),).as_bytes())?; + let mut transport = self.get_transport().clone(); + + let local_id = self.get_local_id()?; + let remote_id = self.get_remote_id()?; + if response.header().command() != MessageCommand::Okay { return Err(RustADBError::ADBRequestFailed(format!( "wrong command {}", @@ -20,12 +26,30 @@ impl ADBMessageDevice { } loop { - let response = self.get_transport_mut().read_message()?; - if response.header().command() != MessageCommand::Write { + let message = transport.read_message()?; + let command = message.header().command(); + + if command == MessageCommand::Clse { break; } - output.write_all(&response.into_payload())?; + self.get_transport_mut() + .write_message(ADBTransportMessage::new( + MessageCommand::Okay, + local_id, + remote_id, + &[], + ))?; + + output.write_all(&message.into_payload())?; + } + + // some devices will repeat the trailing CLSE command to ensure + // the client has acknowledged it. Read them quickly if present. + while let Ok(_discard_close_message) = + transport.read_message_with_timeout(Duration::from_millis(20)) + { + continue; } Ok(())