diff --git a/device.go b/device.go index 6a6b2a1..594fcf9 100644 --- a/device.go +++ b/device.go @@ -46,10 +46,10 @@ func (c *Device) DevicePath() (string, error) { return attr, wrapClientError(err, c, "DevicePath") } -// State returns the connection state of the device (e.g. "device"). -func (c *Device) State() (string, error) { +func (c *Device) State() (DeviceState, error) { attr, err := c.getAttribute("get-state") - return attr, wrapClientError(err, c, "State") + state, err := parseDeviceState(attr) + return state, wrapClientError(err, c, "State") } func (c *Device) DeviceInfo() (*DeviceInfo, error) { diff --git a/device_state.go b/device_state.go new file mode 100644 index 0000000..17cb0ed --- /dev/null +++ b/device_state.go @@ -0,0 +1,32 @@ +package adb + +import "github.com/zach-klippenstein/goadb/util" + +// DeviceState represents one of the 3 possible states adb will report devices. +// A device can be communicated with when it's in StateOnline. +// A USB device will make the following state transitions: +// Plugged in: StateDisconnected->StateOffline->StateOnline +// Unplugged: StateOnline->StateDisconnected +//go:generate stringer -type=DeviceState +type DeviceState int8 + +const ( + StateInvalid DeviceState = iota + StateDisconnected + StateOffline + StateOnline +) + +var deviceStateStrings = map[string]DeviceState{ + "": StateDisconnected, + "offline": StateOffline, + "device": StateOnline, +} + +func parseDeviceState(str string) (DeviceState, error) { + state, ok := deviceStateStrings[str] + if !ok { + return StateInvalid, util.Errorf(util.ParseError, "invalid device state: %q", state) + } + return state, nil +} diff --git a/device_state_test.go b/device_state_test.go new file mode 100644 index 0000000..2ab10dc --- /dev/null +++ b/device_state_test.go @@ -0,0 +1,31 @@ +package adb + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseDeviceState(t *testing.T) { + for _, test := range []struct { + String string + WantState DeviceState + WantName string + WantError error // Compared by Error() message. + }{ + {"", StateDisconnected, "StateDisconnected", nil}, + {"offline", StateOffline, "StateOffline", nil}, + {"device", StateOnline, "StateOnline", nil}, + {"bad", StateInvalid, "StateInvalid", errors.New(`ParseError: invalid device state: "StateInvalid"`)}, + } { + state, err := parseDeviceState(test.String) + if test.WantError == nil { + assert.NoError(t, err) + } else { + assert.EqualError(t, err, test.WantError.Error()) + } + assert.Equal(t, test.WantState, state) + assert.Equal(t, test.WantName, state.String()) + } +} diff --git a/device_watcher.go b/device_watcher.go index fe1866e..3ae4fc4 100644 --- a/device_watcher.go +++ b/device_watcher.go @@ -21,6 +21,8 @@ type DeviceWatcher struct { } // DeviceStateChangedEvent represents a device state transition. +// Contains the device’s old and new states, but also provides methods to query the +// type of state transition. type DeviceStateChangedEvent struct { Serial string OldState DeviceState @@ -37,27 +39,6 @@ func (s DeviceStateChangedEvent) WentOffline() bool { return s.OldState == StateOnline && s.NewState != StateOnline } -// DeviceState represents one of the 3 possible states adb will report devices. -// A device can be communicated with when it's in StateOnline. -// A USB device will transition from StateDisconnected->StateOffline->StateOnline when -// plugged in, and then StateOnline->StateDisconnected when unplugged. -// If code doesn't care about specific states, DeviceStateChangedEvent provides methods -// to query at a higher level. -//go:generate stringer -type=DeviceState -type DeviceState int8 - -const ( - StateDisconnected DeviceState = iota - StateOffline - StateOnline -) - -var deviceStateStrings = map[string]DeviceState{ - "": StateDisconnected, - "offline": StateOffline, - "device": StateOnline, -} - type deviceWatcherImpl struct { server server @@ -218,10 +199,8 @@ func parseDeviceStates(msg string) (states map[string]DeviceState, err error) { } serial, stateString := fields[0], fields[1] - state, ok := deviceStateStrings[stateString] - if !ok { - err = util.Errorf(util.ParseError, "invalid device state: %s", state) - } + var state DeviceState + state, err = parseDeviceState(stateString) states[serial] = state } diff --git a/devicestate_string.go b/devicestate_string.go index 77ac037..2cbe67d 100644 --- a/devicestate_string.go +++ b/devicestate_string.go @@ -4,9 +4,9 @@ package adb import "fmt" -const _DeviceState_name = "StateDisconnectedStateOfflineStateOnline" +const _DeviceState_name = "StateInvalidStateDisconnectedStateOfflineStateOnline" -var _DeviceState_index = [...]uint8{0, 17, 29, 40} +var _DeviceState_index = [...]uint8{0, 12, 29, 41, 52} func (i DeviceState) String() string { if i < 0 || i >= DeviceState(len(_DeviceState_index)-1) {