From d7dbc7672780347f95bab0b7268bfe8e71415840 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Tue, 23 Dec 2025 13:46:12 +0530 Subject: [PATCH] Acknowledge shell_command response with OKAY messages for long responses (#154) * fix: acknowledge write commands to continue partial data streams * fix: read spurious close messages with a small timeout * fix: clippy in CI not erro'ing on warnings * breaking: bump msrv to 1.91.0 * fix: handle as many spurious CLSE messages as possible --------- Co-authored-by: Corentin LIAUD --- adb_client/src/device/commands/shell.rs | 30 ++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) 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(())