Skip to content

Commit 7e2e6ba

Browse files
authored
fix(pkg/board): handle adb connection error (#98)
* fix(pkg/board): handle adb connection error * add a warning * don't expose the function * rename errors * fixup! rename errors * fixup! don't expose the function * implement code review suggestions * nit
1 parent 93c65e1 commit 7e2e6ba

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

pkg/board/board.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ func FromFQBN(ctx context.Context, fqbn string) ([]Board, error) {
192192
if name, err := GetCustomName(ctx, conn); err == nil {
193193
customName = name
194194
}
195+
} else {
196+
slog.Warn("failed to get custom name", "serial", serial, "error", err)
195197
}
196198

197199
boards = append(boards, Board{

pkg/board/remote/adb/adb.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,50 @@ type ADBConnection struct {
4646
// Ensures ADBConnection implements the RemoteConn interface at compile time.
4747
var _ remote.RemoteConn = (*ADBConnection)(nil)
4848

49+
var (
50+
// ErrNotFound is returned when the ADB device is not found.
51+
ErrNotFound = fmt.Errorf("ADB device not found")
52+
// ErrDeviceOffline is returned when the ADB device is not reachable.
53+
// This usually requires a restart of the adbd server daemon on the device.
54+
ErrDeviceOffline = fmt.Errorf("ADB device is offline")
55+
)
56+
57+
// FromSerial creates an ADBConnection from a device serial number.
58+
// returns an error NotFoundErr if the device is not found, and DeviceOfflineErr if the device is offline.
4959
func FromSerial(serial string, adbPath string) (*ADBConnection, error) {
5060
if adbPath == "" {
5161
adbPath = FindAdbPath()
5262
}
5363

64+
isConnected := func(serial, adbPath string) (bool, error) {
65+
cmd, err := paths.NewProcess(nil, adbPath, "-s", serial, "get-state")
66+
if err != nil {
67+
return false, fmt.Errorf("failed to create ADB command: %w", err)
68+
}
69+
70+
output, err := cmd.RunAndCaptureCombinedOutput(context.TODO())
71+
if err != nil {
72+
slog.Error("unable to connect to ADB device", "error", err, "output", string(output), "serial", serial)
73+
if bytes.Contains(output, []byte("device offline")) {
74+
return false, ErrDeviceOffline
75+
} else if bytes.Contains(output, []byte("not found")) {
76+
return false, ErrNotFound
77+
}
78+
return false, fmt.Errorf("failed to get ADB device state: %w: %s", err, output)
79+
}
80+
81+
return string(bytes.TrimSpace(output)) == "device", nil
82+
}
83+
84+
if connected, err := isConnected(serial, adbPath); err != nil {
85+
return nil, err
86+
} else if !connected {
87+
return nil, fmt.Errorf("device %s is not connected", serial)
88+
}
89+
5490
return &ADBConnection{
55-
host: serial,
5691
adbPath: adbPath,
92+
host: serial,
5793
}, nil
5894
}
5995

@@ -65,8 +101,8 @@ func FromHost(host string, adbPath string) (*ADBConnection, error) {
65101
if err != nil {
66102
return nil, err
67103
}
68-
if err := cmd.Run(); err != nil {
69-
return nil, fmt.Errorf("failed to connect to ADB host %s: %w", host, err)
104+
if out, err := cmd.RunAndCaptureCombinedOutput(context.TODO()); err != nil {
105+
return nil, fmt.Errorf("failed to connect to ADB host %s: %w: %s", host, err, out)
70106
}
71107
return FromSerial(host, adbPath)
72108
}

0 commit comments

Comments
 (0)