2015-04-12 20:34:20 +00:00
|
|
|
// TODO(z): Implement TrackDevices.
|
2015-04-11 21:45:29 +00:00
|
|
|
package goadb
|
|
|
|
|
|
|
|
import (
|
2015-05-03 13:11:09 +00:00
|
|
|
"errors"
|
2015-04-11 21:45:29 +00:00
|
|
|
"os/exec"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/zach-klippenstein/goadb/wire"
|
|
|
|
)
|
|
|
|
|
2015-04-29 17:23:51 +00:00
|
|
|
const (
|
|
|
|
// Default port the adb server listens on.
|
|
|
|
AdbPort = 5037
|
|
|
|
)
|
|
|
|
|
2015-04-11 21:45:29 +00:00
|
|
|
/*
|
2015-04-12 20:34:20 +00:00
|
|
|
HostClient communicates with host services on the adb server.
|
2015-04-11 21:45:29 +00:00
|
|
|
|
|
|
|
Eg.
|
2015-04-12 20:34:20 +00:00
|
|
|
client := NewHostClient()
|
|
|
|
client.StartServer()
|
|
|
|
client.ListDevices()
|
|
|
|
client.GetAnyDevice() // see DeviceClient
|
2015-04-11 21:45:29 +00:00
|
|
|
|
|
|
|
See list of services at https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT.
|
|
|
|
*/
|
2015-04-12 20:34:20 +00:00
|
|
|
// TODO(z): Finish implementing host services.
|
2015-04-11 21:45:29 +00:00
|
|
|
type HostClient struct {
|
2015-05-03 13:11:09 +00:00
|
|
|
dialer wire.Dialer
|
2015-04-12 20:34:20 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 13:11:09 +00:00
|
|
|
func NewHostClient() (*HostClient, error) {
|
|
|
|
return NewHostClientPort(AdbPort)
|
2015-04-12 20:34:20 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 13:11:09 +00:00
|
|
|
func NewHostClientPort(port int) (*HostClient, error) {
|
|
|
|
return NewHostClientDialer(wire.NewDialer("localhost", port))
|
2015-04-24 13:20:47 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 13:11:09 +00:00
|
|
|
func NewHostClientDialer(d wire.Dialer) (*HostClient, error) {
|
|
|
|
if d == nil {
|
|
|
|
return nil, errors.New("dialer cannot be nil.")
|
|
|
|
}
|
|
|
|
return &HostClient{d}, nil
|
2015-04-11 21:45:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetServerVersion asks the ADB server for its internal version number.
|
|
|
|
func (c *HostClient) GetServerVersion() (int, error) {
|
2015-04-12 20:34:20 +00:00
|
|
|
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:version")
|
2015-04-11 21:45:29 +00:00
|
|
|
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 {
|
2015-04-12 20:34:20 +00:00
|
|
|
conn, err := c.dialer.Dial()
|
2015-04-11 21:45:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
if err = wire.SendMessageString(conn, "host:kill"); err != nil {
|
2015-04-11 21:45:29 +00:00
|
|
|
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) {
|
2015-04-12 20:34:20 +00:00
|
|
|
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:devices")
|
2015-04-11 21:45:29 +00:00
|
|
|
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
|
|
|
|
*/
|
2015-04-12 20:34:20 +00:00
|
|
|
func (c *HostClient) ListDevices() ([]*DeviceInfo, error) {
|
|
|
|
resp, err := wire.RoundTripSingleResponse(c.dialer, "host:devices-l")
|
2015-04-11 21:45:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return parseDeviceList(string(resp), parseDeviceLong)
|
|
|
|
}
|
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
func (c *HostClient) GetDevice(d *DeviceInfo) *DeviceClient {
|
|
|
|
return c.GetDeviceWithSerial(d.Serial)
|
|
|
|
}
|
2015-04-11 21:45:29 +00:00
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
// 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))
|
2015-04-11 21:45:29 +00:00
|
|
|
}
|
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
// GetAnyDevice returns a client for any one connected device.
|
|
|
|
func (c *HostClient) GetAnyDevice() *DeviceClient {
|
|
|
|
return c.getDevice(anyDevice())
|
|
|
|
}
|
2015-04-11 21:45:29 +00:00
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
// 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())
|
|
|
|
}
|
2015-04-11 21:45:29 +00:00
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
// 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())
|
|
|
|
}
|
2015-04-11 21:45:29 +00:00
|
|
|
|
2015-04-12 20:34:20 +00:00
|
|
|
func (c *HostClient) getDevice(descriptor *DeviceDescriptor) *DeviceClient {
|
|
|
|
return &DeviceClient{c.dialer, descriptor}
|
2015-04-11 21:45:29 +00:00
|
|
|
}
|