Merge pull request #17 from zach-klippenstein/more-renames

Renamed: HostClient -> Adb, DeviceClient -> Device, Server -> server.
This commit is contained in:
Zach Klippenstein 2016-05-22 08:03:18 -07:00
commit 02ccca28d2
12 changed files with 134 additions and 118 deletions

View file

@ -8,26 +8,56 @@ import (
)
/*
HostClient communicates with host services on the adb server.
Adb communicates with host services on the adb server.
Eg.
StartServer()
client := NewHostClient()
client := adb.New()
client.ListDevices()
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 {
server Server
type Adb struct {
server server
}
func NewHostClient(server Server) *HostClient {
return &HostClient{server}
// New creates a new Adb client that uses the default ServerConfig.
func New() (*Adb, error) {
return NewWithConfig(ServerConfig{})
}
// GetServerVersion asks the ADB server for its internal version number.
func (c *HostClient) GetServerVersion() (int, error) {
func NewWithConfig(config ServerConfig) (*Adb, error) {
server, err := newServer(config)
if err != nil {
return nil, err
}
return &Adb{server}, nil
}
// Dial establishes a connection with the adb server.
func (c *Adb) Dial() (*wire.Conn, error) {
return c.server.Dial()
}
// Starts the adb server if its not running.
func (c *Adb) StartServer() error {
return c.server.Start()
}
func (c *Adb) Device(descriptor DeviceDescriptor) *Device {
return &Device{
server: c.server,
descriptor: descriptor,
deviceListFunc: c.ListDevices,
}
}
func (c *Adb) NewDeviceWatcher() *DeviceWatcher {
return newDeviceWatcher(c.server)
}
// ServerVersion asks the ADB server for its internal version number.
func (c *Adb) ServerVersion() (int, error) {
resp, err := roundTripSingleResponse(c.server, "host:version")
if err != nil {
return 0, wrapClientError(err, c, "GetServerVersion")
@ -46,7 +76,7 @@ KillServer tells the server to quit immediately.
Corresponds to the command:
adb kill-server
*/
func (c *HostClient) KillServer() error {
func (c *Adb) KillServer() error {
conn, err := c.server.Dial()
if err != nil {
return wrapClientError(err, c, "KillServer")
@ -66,7 +96,7 @@ ListDeviceSerials returns the serial numbers of all attached devices.
Corresponds to the command:
adb devices
*/
func (c *HostClient) ListDeviceSerials() ([]string, error) {
func (c *Adb) ListDeviceSerials() ([]string, error) {
resp, err := roundTripSingleResponse(c.server, "host:devices")
if err != nil {
return nil, wrapClientError(err, c, "ListDeviceSerials")
@ -90,7 +120,7 @@ ListDevices returns the list of connected devices.
Corresponds to the command:
adb devices -l
*/
func (c *HostClient) ListDevices() ([]*DeviceInfo, error) {
func (c *Adb) ListDevices() ([]*DeviceInfo, error) {
resp, err := roundTripSingleResponse(c.server, "host:devices-l")
if err != nil {
return nil, wrapClientError(err, c, "ListDevices")
@ -103,7 +133,7 @@ func (c *HostClient) ListDevices() ([]*DeviceInfo, error) {
return devices, nil
}
func (c *HostClient) parseServerVersion(versionRaw []byte) (int, error) {
func (c *Adb) parseServerVersion(versionRaw []byte) (int, error) {
versionStr := string(versionRaw)
version, err := strconv.ParseInt(versionStr, 16, 32)
if err != nil {

View file

@ -12,9 +12,9 @@ func TestGetServerVersion(t *testing.T) {
Status: wire.StatusSuccess,
Messages: []string{"000a"},
}
client := NewHostClient(s)
client := &Adb{s}
v, err := client.GetServerVersion()
v, err := client.ServerVersion()
assert.Equal(t, "host:version", s.Requests[0])
assert.NoError(t, err)
assert.Equal(t, 10, v)

View file

@ -65,13 +65,13 @@ var (
String()
)
var server adb.Server
var client *adb.Adb
func main() {
var exitCode int
var err error
server, err = adb.NewServer(adb.ServerConfig{})
client, err = adb.NewWithConfig(adb.ServerConfig{})
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
@ -100,7 +100,7 @@ func parseDevice() adb.DeviceDescriptor {
}
func listDevices(long bool) int {
client := adb.NewHostClient(server)
//client := adb.New(server)
devices, err := client.ListDevices()
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
@ -137,7 +137,7 @@ func runShellCommand(commandAndArgs []string, device adb.DeviceDescriptor) int {
args = commandAndArgs[1:]
}
client := adb.NewDeviceClient(server, device)
client := client.Device(device)
output, err := client.RunCommand(command, args...)
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
@ -159,7 +159,7 @@ func pull(showProgress bool, remotePath, localPath string, device adb.DeviceDesc
localPath = filepath.Base(remotePath)
}
client := adb.NewDeviceClient(server, device)
client := client.Device(device)
info, err := client.Stat(remotePath)
if util.HasErrCode(err, util.FileNoExistError) {
@ -232,7 +232,7 @@ func push(showProgress bool, localPath, remotePath string, device adb.DeviceDesc
}
defer localFile.Close()
client := adb.NewDeviceClient(server, device)
client := client.Device(device)
writer, err := client.OpenWrite(remotePath, perms, mtime)
if err != nil {
fmt.Fprintf(os.Stderr, "error opening remote file %s: %s\n", remotePath, err)

View file

@ -15,25 +15,23 @@ import (
var (
port = flag.Int("p", adb.AdbPort, "")
server adb.Server
client *adb.Adb
)
func main() {
flag.Parse()
var err error
server, err = adb.NewServer(adb.ServerConfig{
client, err = adb.NewWithConfig(adb.ServerConfig{
Port: *port,
})
if err != nil {
log.Fatal(err)
}
fmt.Println("Starting server…")
server.Start()
client.StartServer()
client := adb.NewHostClient(server)
serverVersion, err := client.GetServerVersion()
serverVersion, err := client.ServerVersion()
if err != nil {
log.Fatal(err)
}
@ -62,7 +60,7 @@ func main() {
fmt.Println()
fmt.Println("Watching for device state changes.")
watcher := adb.NewDeviceWatcher(server)
watcher := client.NewDeviceWatcher()
for event := range watcher.C() {
fmt.Printf("\t[%s]%+v\n", time.Now(), event)
}
@ -88,22 +86,22 @@ func printErr(err error) {
}
func PrintDeviceInfoAndError(descriptor adb.DeviceDescriptor) {
device := adb.NewDeviceClient(server, descriptor)
device := client.Device(descriptor)
if err := PrintDeviceInfo(device); err != nil {
log.Println(err)
}
}
func PrintDeviceInfo(device *adb.DeviceClient) error {
serialNo, err := device.GetSerial()
func PrintDeviceInfo(device *adb.Device) error {
serialNo, err := device.Serial()
if err != nil {
return err
}
devPath, err := device.GetDevicePath()
devPath, err := device.DevicePath()
if err != nil {
return err
}
state, err := device.GetState()
state, err := device.State()
if err != nil {
return err
}

View file

@ -14,7 +14,7 @@ import (
"github.com/zach-klippenstein/goadb/wire"
)
var port = flag.Int("p", adb.AdbPort, "port the adb server is listening on")
var port = flag.Int("p", adb.AdbPort, "`port` the adb server is listening on")
func main() {
flag.Parse()
@ -49,7 +49,7 @@ func readLine() string {
}
func doCommand(cmd string) error {
server, err := adb.NewServer(adb.ServerConfig{
server, err := adb.NewWithConfig(adb.ServerConfig{
Port: *port,
})
if err != nil {

View file

@ -15,61 +15,55 @@ import (
// method is called.
var MtimeOfClose = time.Time{}
// DeviceClient communicates with a specific Android device.
type DeviceClient struct {
server Server
// Device communicates with a specific Android device.
// To get an instance, call Device() on an Adb.
type Device struct {
server server
descriptor DeviceDescriptor
// Used to get device info.
deviceListFunc func() ([]*DeviceInfo, error)
}
func NewDeviceClient(server Server, descriptor DeviceDescriptor) *DeviceClient {
return &DeviceClient{
server: server,
descriptor: descriptor,
deviceListFunc: NewHostClient(server).ListDevices,
}
}
func (c *DeviceClient) String() string {
func (c *Device) String() string {
return c.descriptor.String()
}
// get-product is documented, but not implemented in the server.
// TODO(z): Make getProduct exported if get-product is ever implemented in adb.
func (c *DeviceClient) getProduct() (string, error) {
// get-product is documented, but not implemented, in the server.
// TODO(z): Make product exported if get-product is ever implemented in adb.
func (c *Device) product() (string, error) {
attr, err := c.getAttribute("get-product")
return attr, wrapClientError(err, c, "GetProduct")
return attr, wrapClientError(err, c, "Product")
}
func (c *DeviceClient) GetSerial() (string, error) {
func (c *Device) Serial() (string, error) {
attr, err := c.getAttribute("get-serialno")
return attr, wrapClientError(err, c, "GetSerial")
return attr, wrapClientError(err, c, "Serial")
}
func (c *DeviceClient) GetDevicePath() (string, error) {
func (c *Device) DevicePath() (string, error) {
attr, err := c.getAttribute("get-devpath")
return attr, wrapClientError(err, c, "GetDevicePath")
return attr, wrapClientError(err, c, "DevicePath")
}
func (c *DeviceClient) GetState() (string, error) {
// State returns the connection state of the device (e.g. "device").
func (c *Device) State() (string, error) {
attr, err := c.getAttribute("get-state")
return attr, wrapClientError(err, c, "GetState")
return attr, wrapClientError(err, c, "State")
}
func (c *DeviceClient) GetDeviceInfo() (*DeviceInfo, error) {
func (c *Device) DeviceInfo() (*DeviceInfo, error) {
// Adb doesn't actually provide a way to get this for an individual device,
// so we have to just list devices and find ourselves.
serial, err := c.GetSerial()
serial, err := c.Serial()
if err != nil {
return nil, wrapClientError(err, c, "GetDeviceInfo(GetSerial)")
}
devices, err := c.deviceListFunc()
if err != nil {
return nil, wrapClientError(err, c, "GetDeviceInfo(ListDevices)")
return nil, wrapClientError(err, c, "DeviceInfo(ListDevices)")
}
for _, deviceInfo := range devices {
@ -79,7 +73,7 @@ func (c *DeviceClient) GetDeviceInfo() (*DeviceInfo, error) {
}
err = util.Errorf(util.DeviceNotFound, "device list doesn't contain serial %s", serial)
return nil, wrapClientError(err, c, "GetDeviceInfo")
return nil, wrapClientError(err, c, "DeviceInfo")
}
/*
@ -98,7 +92,7 @@ Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVI
This method quotes the arguments for you, and will return an error if any of them
contain double quotes.
*/
func (c *DeviceClient) RunCommand(cmd string, args ...string) (string, error) {
func (c *Device) RunCommand(cmd string, args ...string) (string, error) {
cmd, err := prepareCommandLine(cmd, args...)
if err != nil {
return "", wrapClientError(err, c, "RunCommand")
@ -127,7 +121,7 @@ func (c *DeviceClient) RunCommand(cmd string, args ...string) (string, error) {
}
/*
Remount, from the docs,
Remount, from the official adb commands docs:
Ask adbd to remount the device's filesystem in read-write mode,
instead of read-only. This is usually necessary before performing
an "adb sync" or "adb push" request.
@ -135,7 +129,7 @@ Remount, from the docs,
that.
Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT
*/
func (c *DeviceClient) Remount() (string, error) {
func (c *Device) Remount() (string, error) {
conn, err := c.dialDevice()
if err != nil {
return "", wrapClientError(err, c, "Remount")
@ -146,7 +140,7 @@ func (c *DeviceClient) Remount() (string, error) {
return string(resp), wrapClientError(err, c, "Remount")
}
func (c *DeviceClient) ListDirEntries(path string) (*DirEntries, error) {
func (c *Device) ListDirEntries(path string) (*DirEntries, error) {
conn, err := c.getSyncConn()
if err != nil {
return nil, wrapClientError(err, c, "ListDirEntries(%s)", path)
@ -156,7 +150,7 @@ func (c *DeviceClient) ListDirEntries(path string) (*DirEntries, error) {
return entries, wrapClientError(err, c, "ListDirEntries(%s)", path)
}
func (c *DeviceClient) Stat(path string) (*DirEntry, error) {
func (c *Device) Stat(path string) (*DirEntry, error) {
conn, err := c.getSyncConn()
if err != nil {
return nil, wrapClientError(err, c, "Stat(%s)", path)
@ -167,7 +161,7 @@ func (c *DeviceClient) Stat(path string) (*DirEntry, error) {
return entry, wrapClientError(err, c, "Stat(%s)", path)
}
func (c *DeviceClient) OpenRead(path string) (io.ReadCloser, error) {
func (c *Device) OpenRead(path string) (io.ReadCloser, error) {
conn, err := c.getSyncConn()
if err != nil {
return nil, wrapClientError(err, c, "OpenRead(%s)", path)
@ -181,7 +175,7 @@ func (c *DeviceClient) OpenRead(path string) (io.ReadCloser, error) {
// by perms if necessary, and returns a writer that writes to the file.
// The files modification time will be set to mtime when the WriterCloser is closed. The zero value
// is TimeOfClose, which will use the time the Close method is called as the modification time.
func (c *DeviceClient) OpenWrite(path string, perms os.FileMode, mtime time.Time) (io.WriteCloser, error) {
func (c *Device) OpenWrite(path string, perms os.FileMode, mtime time.Time) (io.WriteCloser, error) {
conn, err := c.getSyncConn()
if err != nil {
return nil, wrapClientError(err, c, "OpenWrite(%s)", path)
@ -193,7 +187,7 @@ func (c *DeviceClient) OpenWrite(path string, perms os.FileMode, mtime time.Time
// getAttribute returns the first message returned by the server by running
// <host-prefix>:<attr>, where host-prefix is determined from the DeviceDescriptor.
func (c *DeviceClient) getAttribute(attr string) (string, error) {
func (c *Device) getAttribute(attr string) (string, error) {
resp, err := roundTripSingleResponse(c.server,
fmt.Sprintf("%s:%s", c.descriptor.getHostPrefix(), attr))
if err != nil {
@ -202,7 +196,7 @@ func (c *DeviceClient) getAttribute(attr string) (string, error) {
return string(resp), nil
}
func (c *DeviceClient) getSyncConn() (*wire.SyncConn, error) {
func (c *Device) getSyncConn() (*wire.SyncConn, error) {
conn, err := c.dialDevice()
if err != nil {
return nil, err
@ -221,7 +215,7 @@ func (c *DeviceClient) getSyncConn() (*wire.SyncConn, error) {
// dialDevice switches the connection to communicate directly with the device
// by requesting the transport defined by the DeviceDescriptor.
func (c *DeviceClient) dialDevice() (*wire.Conn, error) {
func (c *Device) dialDevice() (*wire.Conn, error) {
conn, err := c.server.Dial()
if err != nil {
return nil, err

View file

@ -13,7 +13,7 @@ func TestGetAttribute(t *testing.T) {
Status: wire.StatusSuccess,
Messages: []string{"value"},
}
client := NewDeviceClient(s, DeviceWithSerial("serial"))
client := (&Adb{s}).Device(DeviceWithSerial("serial"))
v, err := client.getAttribute("attr")
assert.Equal(t, "host-serial:serial:attr", s.Requests[0])
@ -36,31 +36,28 @@ func TestGetDeviceInfo(t *testing.T) {
}
client := newDeviceClientWithDeviceLister("abc", deviceLister)
device, err := client.GetDeviceInfo()
device, err := client.DeviceInfo()
assert.NoError(t, err)
assert.Equal(t, "Foo", device.Product)
client = newDeviceClientWithDeviceLister("def", deviceLister)
device, err = client.GetDeviceInfo()
device, err = client.DeviceInfo()
assert.NoError(t, err)
assert.Equal(t, "Bar", device.Product)
client = newDeviceClientWithDeviceLister("serial", deviceLister)
device, err = client.GetDeviceInfo()
device, err = client.DeviceInfo()
assert.True(t, util.HasErrCode(err, util.DeviceNotFound))
assert.EqualError(t, err.(*util.Err).Cause,
"DeviceNotFound: device list doesn't contain serial serial")
assert.Nil(t, device)
}
func newDeviceClientWithDeviceLister(serial string, deviceLister func() ([]*DeviceInfo, error)) *DeviceClient {
client := NewDeviceClient(
&MockServer{
Status: wire.StatusSuccess,
Messages: []string{serial},
},
DeviceWithSerial(serial),
)
func newDeviceClientWithDeviceLister(serial string, deviceLister func() ([]*DeviceInfo, error)) *Device {
client := (&Adb{&MockServer{
Status: wire.StatusSuccess,
Messages: []string{serial},
}}).Device(DeviceWithSerial(serial))
client.deviceListFunc = deviceLister
return client
}
@ -70,7 +67,7 @@ func TestRunCommandNoArgs(t *testing.T) {
Status: wire.StatusSuccess,
Messages: []string{"output"},
}
client := NewDeviceClient(s, AnyDevice())
client := (&Adb{s}).Device(AnyDevice())
v, err := client.RunCommand("cmd")
assert.Equal(t, "host:transport-any", s.Requests[0])

View file

@ -59,7 +59,7 @@ var deviceStateStrings = map[string]DeviceState{
}
type deviceWatcherImpl struct {
server Server
server server
// If an error occurs, it is stored here and eventChan is close immediately after.
err atomic.Value
@ -67,7 +67,7 @@ type deviceWatcherImpl struct {
eventChan chan DeviceStateChangedEvent
}
func NewDeviceWatcher(server Server) *DeviceWatcher {
func newDeviceWatcher(server server) *DeviceWatcher {
watcher := &DeviceWatcher{&deviceWatcherImpl{
server: server,
eventChan: make(chan DeviceStateChangedEvent),
@ -165,7 +165,7 @@ func publishDevices(watcher *deviceWatcherImpl) {
}
}
func connectToTrackDevices(server Server) (wire.Scanner, error) {
func connectToTrackDevices(server server) (wire.Scanner, error) {
conn, err := server.Dial()
if err != nil {
return nil, err

View file

@ -30,15 +30,17 @@ type ServerConfig struct {
// Dialer used to connect to the adb server.
Dialer
fs *filesystem
}
// Server knows how to start the adb server and connect to it.
type Server interface {
type server interface {
Start() error
Dial() (*wire.Conn, error)
}
func roundTripSingleResponse(s Server, req string) ([]byte, error) {
func roundTripSingleResponse(s server, req string) ([]byte, error) {
conn, err := s.Dial()
if err != nil {
return nil, err
@ -50,18 +52,12 @@ func roundTripSingleResponse(s Server, req string) ([]byte, error) {
type realServer struct {
config ServerConfig
fs *filesystem
// Caches Host:Port so they don't have to be concatenated for every dial.
address string
}
// NewServer creates a new Server instance.
func NewServer(config ServerConfig) (Server, error) {
return newServer(config, localFilesystem)
}
func newServer(config ServerConfig, fs *filesystem) (Server, error) {
func newServer(config ServerConfig) (server, error) {
if config.Dialer == nil {
config.Dialer = tcpDialer{}
}
@ -73,20 +69,23 @@ func newServer(config ServerConfig, fs *filesystem) (Server, error) {
config.Port = AdbPort
}
if config.fs == nil {
config.fs = localFilesystem
}
if config.PathToAdb == "" {
path, err := fs.LookPath(AdbExecutableName)
path, err := config.fs.LookPath(AdbExecutableName)
if err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "could not find %s in PATH", AdbExecutableName)
}
config.PathToAdb = path
}
if err := fs.IsExecutableFile(config.PathToAdb); err != nil {
if err := config.fs.IsExecutableFile(config.PathToAdb); err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "invalid adb executable: %s", config.PathToAdb)
}
return &realServer{
config: config,
fs: fs,
address: fmt.Sprintf("%s:%d", config.Host, config.Port),
}, nil
}
@ -111,7 +110,7 @@ func (s *realServer) Dial() (*wire.Conn, error) {
// StartServer ensures there is a server running.
func (s *realServer) Start() error {
output, err := s.fs.CmdCombinedOutput(s.config.PathToAdb, "start-server")
output, err := s.config.fs.CmdCombinedOutput(s.config.PathToAdb, "start-server")
outputStr := strings.TrimSpace(string(output))
return util.WrapErrorf(err, util.ServerNotAvailable, "error starting server: %s\noutput:\n%s", err, outputStr)
}

View file

@ -28,7 +28,7 @@ type MockServer struct {
Trace []string
}
var _ Server = &MockServer{}
var _ server = &MockServer{}
func (s *MockServer) Dial() (*wire.Conn, error) {
s.logMethod("Dial")

View file

@ -9,8 +9,7 @@ import (
)
func TestNewServer_ZeroConfig(t *testing.T) {
config := ServerConfig{}
fs := &filesystem{
config := ServerConfig{fs: &filesystem{
LookPath: func(name string) (string, error) {
if name == AdbExecutableName {
return "/bin/adb", nil
@ -23,9 +22,9 @@ func TestNewServer_ZeroConfig(t *testing.T) {
}
return fmt.Errorf("wrong path: %s", path)
},
}
}}
serverIf, err := newServer(config, fs)
serverIf, err := newServer(config)
server := serverIf.(*realServer)
assert.NoError(t, err)
assert.IsType(t, tcpDialer{}, server.config.Dialer)
@ -47,17 +46,17 @@ func TestNewServer_CustomConfig(t *testing.T) {
Host: "foobar",
Port: 1,
PathToAdb: "/bin/adb",
}
fs := &filesystem{
IsExecutableFile: func(path string) error {
if path == "/bin/adb" {
return nil
}
return fmt.Errorf("wrong path: %s", path)
fs: &filesystem{
IsExecutableFile: func(path string) error {
if path == "/bin/adb" {
return nil
}
return fmt.Errorf("wrong path: %s", path)
},
},
}
serverIf, err := newServer(config, fs)
serverIf, err := newServer(config)
server := serverIf.(*realServer)
assert.NoError(t, err)
assert.IsType(t, MockDialer{}, server.config.Dialer)
@ -68,13 +67,12 @@ func TestNewServer_CustomConfig(t *testing.T) {
}
func TestNewServer_AdbNotFound(t *testing.T) {
config := ServerConfig{}
fs := &filesystem{
config := ServerConfig{fs: &filesystem{
LookPath: func(name string) (string, error) {
return "", fmt.Errorf("executable not found: %s", name)
},
}
}}
_, err := newServer(config, fs)
_, err := newServer(config)
assert.EqualError(t, err, "ServerNotAvailable: could not find adb in PATH")
}

View file

@ -2,7 +2,7 @@
Package wire implements the low-level part of the client/server wire protocol.
It also implements the "sync" wire format for file transfers.
This package is not intended to be used directly. adb.HostClient and adb.DeviceClient
This package is not intended to be used directly. adb.Adb and adb.Device
use it to abstract away the bit-twiddling details of the protocol. You should only ever
need to work with the goadb package. Also, this package's API may change more frequently
than goadb's.