@@ -36,7 +36,13 @@ import (
3636 "github.com/arduino/arduino-app-cli/pkg/x/ports"
3737)
3838
39- const username = "arduino"
39+ var (
40+ // NotFoundErr is returned when the ADB device is not found.
41+ NotFoundErr = fmt .Errorf ("ADB device not found" )
42+ // DeviceOfflineErr is returned when the ADB device is not reachable.
43+ // This usually requires a restart of the adbd server daemon on the device.
44+ DeviceOfflineErr = fmt .Errorf ("ADB device is offline" )
45+ )
4046
4147type ADBConnection struct {
4248 adbPath string
@@ -46,15 +52,21 @@ type ADBConnection struct {
4652// Ensures ADBConnection implements the RemoteConn interface at compile time.
4753var _ remote.RemoteConn = (* ADBConnection )(nil )
4854
55+ const username = "arduino"
56+
4957func FromSerial (serial string , adbPath string ) (* ADBConnection , error ) {
5058 if adbPath == "" {
5159 adbPath = FindAdbPath ()
5260 }
5361
54- return & ADBConnection {
55- host : serial ,
56- adbPath : adbPath ,
57- }, nil
62+ conn := ADBConnection {host : serial , adbPath : adbPath }
63+ if connected , err := conn .IsConnected (); err != nil {
64+ return nil , err
65+ } else if ! connected {
66+ return nil , fmt .Errorf ("device %s is not connected" , serial )
67+ }
68+
69+ return & conn , nil
5870}
5971
6072func FromHost (host string , adbPath string ) (* ADBConnection , error ) {
@@ -71,6 +83,26 @@ func FromHost(host string, adbPath string) (*ADBConnection, error) {
7183 return FromSerial (host , adbPath )
7284}
7385
86+ // IsConnected checks if the ADB device is connected and online.
87+ func (a * ADBConnection ) IsConnected () (bool , error ) {
88+ cmd , err := paths .NewProcess (nil , a .adbPath , "-s" , a .host , "get-state" )
89+ if err != nil {
90+ return false , fmt .Errorf ("failed to create ADB command: %w" , err )
91+ }
92+
93+ output , err := cmd .RunAndCaptureCombinedOutput (context .TODO ())
94+ if err != nil {
95+ if bytes .Contains (output , []byte ("device offline" )) {
96+ return false , DeviceOfflineErr
97+ } else if bytes .Contains (output , []byte ("not found" )) {
98+ return false , NotFoundErr
99+ }
100+ return false , fmt .Errorf ("failed to get ADB device state: %w: %s" , err , output )
101+ }
102+
103+ return string (bytes .TrimSpace (output )) == "device" , nil
104+ }
105+
74106func (a * ADBConnection ) Forward (ctx context.Context , localPort int , remotePort int ) error {
75107 if ! ports .IsAvailable (localPort ) {
76108 return remote .ErrPortAvailable
0 commit comments