goadb/host_client.go

150 lines
3.5 KiB
Go
Raw Normal View History

// TODO(z): Implement TrackDevices.
package goadb
import (
"os/exec"
"strconv"
"github.com/zach-klippenstein/goadb/wire"
)
/*
HostClient communicates with host services on the adb server.
Eg.
client := NewHostClient()
client.StartServer()
client.ListDevices()
client.GetAnyDevice() // see DeviceClient
See list of services at https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT.
*/
// TODO(z): Finish implementing host services.
type HostClient struct {
dialer nilSafeDialer
}
func NewHostClient() *HostClient {
return NewHostClientDialer(nil)
}
func NewHostClientPort(port int) *HostClient {
return NewHostClientDialer(wire.NewDialer("", port))
}
func NewHostClientDialer(d wire.Dialer) *HostClient {
return &HostClient{nilSafeDialer{d}}
}
// GetServerVersion asks the ADB server for its internal version number.
func (c *HostClient) GetServerVersion() (int, error) {
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:version")
if err != nil {
return 0, err
}
version, err := strconv.ParseInt(string(resp), 16, 32)
return int(version), err
}
/*
KillServer tells the server to quit immediately.
Corresponds to the command:
adb kill-server
*/
func (c *HostClient) KillServer() error {
conn, err := c.dialer.Dial()
if err != nil {
return err
}
defer conn.Close()
if err = wire.SendMessageString(conn, "host:kill"); err != nil {
return err
}
return nil
}
/*
StartServer ensures there is a server running.
Currently implemented by just running
adb start-server
*/
func (c *HostClient) StartServer() error {
cmd := exec.Command("adb", "start-server")
return cmd.Run()
}
/*
ListDeviceSerials returns the serial numbers of all attached devices.
Corresponds to the command:
adb devices
*/
func (c *HostClient) ListDeviceSerials() ([]string, error) {
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:devices")
if err != nil {
return nil, err
}
devices, err := parseDeviceList(string(resp), parseDeviceShort)
if err != nil {
return nil, err
}
serials := make([]string, len(devices))
for i, dev := range devices {
serials[i] = dev.Serial
}
return serials, nil
}
/*
ListDevices returns the list of connected devices.
Corresponds to the command:
adb devices -l
*/
func (c *HostClient) ListDevices() ([]*DeviceInfo, error) {
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:devices-l")
if err != nil {
return nil, err
}
return parseDeviceList(string(resp), parseDeviceLong)
}
func (c *HostClient) GetDevice(d *DeviceInfo) *DeviceClient {
return c.GetDeviceWithSerial(d.Serial)
}
// GetDeviceWithSerial returns a client for the device with the specified serial number.
// Will return a client even if there is no matching device connected.
func (c *HostClient) GetDeviceWithSerial(serial string) *DeviceClient {
return c.getDevice(deviceWithSerial(serial))
}
// GetAnyDevice returns a client for any one connected device.
func (c *HostClient) GetAnyDevice() *DeviceClient {
return c.getDevice(anyDevice())
}
// GetUsbDevice returns a client for the USB device.
// Will return a client even if there is no device connected.
func (c *HostClient) GetUsbDevice() *DeviceClient {
return c.getDevice(anyUsbDevice())
}
// GetLocalDevice returns a client for the local device.
// Will return a client even if there is no device connected.
func (c *HostClient) GetLocalDevice() *DeviceClient {
return c.getDevice(anyLocalDevice())
}
func (c *HostClient) getDevice(descriptor *DeviceDescriptor) *DeviceClient {
return &DeviceClient{c.dialer, descriptor}
}