Compare commits

...

10 commits

38 changed files with 206 additions and 56 deletions

View file

@ -1,7 +1,5 @@
#goadb #goadb
[![GoDoc](https://pkg.go.dev/github.com/timoxa0/goadb?status.svg)](https://pkg.go.dev/github.com/timoxa0/goadb)
[![Build Status](https://travis-ci.org/zach-klippenstein/goadb.svg?branch=master)](https://travis-ci.org/zach-klippenstein/goadb)
[![GoDoc](https://godoc.org/goadb?status.svg)](https://godoc.org/goadb)
A Golang library for interacting with the Android Debug Bridge (adb). A Golang library for interacting with the Android Debug Bridge (adb).

View file

@ -3,8 +3,8 @@ package adb
import ( import (
"strconv" "strconv"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
/* /*

View file

@ -3,7 +3,7 @@ package adb
import ( import (
"testing" "testing"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -7,8 +7,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// MtimeOfClose should be passed to OpenWrite to set the file modification time to the time the Close // MtimeOfClose should be passed to OpenWrite to set the file modification time to the time the Close
@ -80,6 +80,7 @@ func (c *Device) DeviceInfo() (*DeviceInfo, error) {
RunCommand runs the specified commands on a shell on the device. RunCommand runs the specified commands on a shell on the device.
From the Android docs: From the Android docs:
Run 'command arg1 arg2 ...' in a shell on the device, and return Run 'command arg1 arg2 ...' in a shell on the device, and return
its output and error streams. Note that arguments must be separated its output and error streams. Note that arguments must be separated
by spaces. If an argument contains a space, it must be quoted with by spaces. If an argument contains a space, it must be quoted with
@ -87,6 +88,7 @@ From the Android docs:
will go very wrong. will go very wrong.
Note that this is the non-interactive version of "adb shell" Note that this is the non-interactive version of "adb shell"
Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT
This method quotes the arguments for you, and will return an error if any of them This method quotes the arguments for you, and will return an error if any of them
@ -120,13 +122,84 @@ func (c *Device) RunCommand(cmd string, args ...string) (string, error) {
return string(resp), wrapClientError(err, c, "RunCommand") return string(resp), wrapClientError(err, c, "RunCommand")
} }
/*
Forward, from the official adb command's docs:
Asks the ADB server to forward local connections from <local>
to the <remote> address on a given device.
There, <host-prefix> can be one of the
host-serial/host-usb/host-local/host prefixes as described previously
and indicates which device/emulator to target.
the format of <local> is one of:
tcp:<port> -> TCP connection on localhost:<port>
local:<path> -> Unix local domain socket on <path>
the format of <remote> is one of:
tcp:<port> -> TCP localhost:<port> on device
local:<path> -> Unix local domain socket on device
jdwp:<pid> -> JDWP thread on VM process <pid>
vsock:<CID>:<port> -> vsock on the given CID and port
or even any one of the local services described below.
Source: https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/SERVICES.TXT
*/
func (c *Device) Forward(local string, remote string) error {
req := fmt.Sprintf("forward:%s;%s", local, remote)
_, err := c.getAttribute(req)
return wrapClientError(err, c, "Forward")
}
/*
KillForward, from the official adb command's docs:
Remove any existing forward local connection from <local>.
Source: https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/SERVICES.TXT
*/
func (c *Device) KillForward(local string) error {
req := fmt.Sprintf("killforward:%s", local)
_, err := c.getAttribute(req)
return wrapClientError(err, c, "KillForward")
}
/*
KillForwardAll, from the official adb command's docs:
Remove all forward network connections.
Source: https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/SERVICES.TXT
*/
func (c *Device) KillForwardAll() error {
req := "killforward-all"
_, err := c.getAttribute(req)
return wrapClientError(err, c, "KillForward")
}
/*
ListForwards, from the official adb command's docs:
List all existing forward connections from this server.
Source: https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/SERVICES.TXT
*/
func (c *Device) ListForwards() ([]Forward, error) {
req := "list-forward"
resp, err := c.getAttribute(req)
if err != nil {
return nil, wrapClientError(err, c, "ListForwards")
}
forwards, err := parseForward(resp, c.descriptor.serial)
return forwards, wrapClientError(err, c, "ListForwards")
}
/* /*
Remount, from the official adb commands docs: Remount, from the official adb commands docs:
Ask adbd to remount the device's filesystem in read-write mode, Ask adbd to remount the device's filesystem in read-write mode,
instead of read-only. This is usually necessary before performing instead of read-only. This is usually necessary before performing
an "adb sync" or "adb push" request. an "adb sync" or "adb push" request.
This request may not succeed on certain builds which do not allow This request may not succeed on certain builds which do not allow
that. that.
Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT
*/ */
func (c *Device) Remount() (string, error) { func (c *Device) Remount() (string, error) {

61
adb/device_forward.go Normal file
View file

@ -0,0 +1,61 @@
package adb
import (
"strings"
)
type ForwardType int8
const (
TypeInvalid ForwardType = iota
ForwardTCP
ForwardLOCAL
)
var forwardTypeStrings = map[string]ForwardType{
"tcp": ForwardTCP,
"local": ForwardLOCAL,
}
type ForwardTarget string
type ForwardLocal struct {
FType ForwardType
FTarget ForwardTarget
}
type ForwardRemote struct {
FType ForwardType
FTarget ForwardTarget
}
type Forward struct {
Local ForwardLocal
Remote ForwardRemote
}
func parseForward(str string, deviceSerial string) ([]Forward, error) {
var forwards []Forward
for _, forwardStr := range strings.Split(str, "\n") {
if strings.Trim(forwardStr, "\n\t ") == "" {
continue
}
raw_forward := strings.Split(forwardStr, " ")
serial, local, remote := raw_forward[0], raw_forward[1], raw_forward[2]
if serial == deviceSerial {
raw_local := strings.Split(local, ":")
raw_remote := strings.Split(remote, ":")
forwards = append(forwards, Forward{
Local: ForwardLocal{
FType: forwardTypeStrings[raw_local[0]],
FTarget: ForwardTarget(raw_local[1]),
},
Remote: ForwardRemote{
FType: forwardTypeStrings[raw_remote[0]],
FTarget: ForwardTarget(raw_remote[1]),
},
})
}
}
return forwards, nil
}

View file

@ -4,7 +4,7 @@ import (
"bufio" "bufio"
"strings" "strings"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
type DeviceInfo struct { type DeviceInfo struct {
@ -87,5 +87,8 @@ func parseDeviceAttributes(fields []string) map[string]string {
// Parses a key:val pair and returns key, val. // Parses a key:val pair and returns key, val.
func parseKeyVal(pair string) (string, string) { func parseKeyVal(pair string) (string, string) {
split := strings.Split(pair, ":") split := strings.Split(pair, ":")
if len(split) == 1 {
return split[0], ""
}
return split[0], split[1] return split[0], split[1]
} }

View file

@ -1,14 +1,13 @@
package adb package adb
import ( import "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/internal/errors"
)
// DeviceState represents one of the 3 possible states adb will report devices. // DeviceState represents one of the 3 possible states adb will report devices.
// A device can be communicated with when it's in StateOnline. // A device can be communicated with when it's in StateOnline.
// A USB device will make the following state transitions: // A USB device will make the following state transitions:
// //
// Plugged in: StateDisconnected->StateOffline->StateOnline // Plugged in: StateDisconnected->StateOffline->StateOnline
// Plugged in (Recoveory): StateDisconnected->StateOnline
// Unplugged: StateOnline->StateDisconnected // Unplugged: StateOnline->StateDisconnected
// //
//go:generate stringer -type=DeviceState //go:generate stringer -type=DeviceState

View file

@ -3,8 +3,8 @@ package adb
import ( import (
"testing" "testing"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -8,8 +8,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
/* /*

View file

@ -3,8 +3,8 @@ package adb
import ( import (
"testing" "testing"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -5,8 +5,8 @@ import (
"net" "net"
"runtime" "runtime"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// Dialer knows how to create connections to an adb server. // Dialer knows how to create connections to an adb server.

View file

@ -5,7 +5,7 @@ import (
"os" "os"
"time" "time"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// DirEntry holds information about a directory entry on a device. // DirEntry holds information about a directory entry on a device.

View file

@ -1,6 +1,6 @@
package adb package adb
import "github.com/evrins/goadb/internal/errors" import "github.com/timoxa0/goadb/internal/errors"
type ErrCode errors.ErrCode type ErrCode errors.ErrCode

16
adb/forward_string.go Normal file
View file

@ -0,0 +1,16 @@
// Code generated by "stringer -type=ForwardType"; DO NOT EDIT
package adb
import "fmt"
const _ForwardType_name = "InvalidTCPLocal"
var _ForwardType_index = [...]uint8{0, 7, 10, 15}
func (i ForwardType) String() string {
if i < 0 || i >= ForwardType(len(_ForwardType_index)-1) {
return fmt.Sprintf("ForwardType(%d)", i)
}
return _ForwardType_name[_ForwardType_index[i]:_ForwardType_index[i+1]]
}

View file

@ -7,8 +7,8 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
const ( const (

View file

@ -4,8 +4,8 @@ import (
"io" "io"
"strings" "strings"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// MockServer implements Server, Scanner, and Sender. // MockServer implements Server, Scanner, and Sender.

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -5,8 +5,8 @@ import (
"os" "os"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
var zeroTime = time.Unix(0, 0).UTC() var zeroTime = time.Unix(0, 0).UTC()

View file

@ -7,8 +7,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

View file

@ -3,8 +3,8 @@ package adb
import ( import (
"io" "io"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// syncFileReader wraps a SyncConn that has requested to receive a file. // syncFileReader wraps a SyncConn that has requested to receive a file.

View file

@ -6,7 +6,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -6,8 +6,8 @@ import (
"os" "os"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
) )
// syncFileWriter wraps a SyncConn that has requested to send a file. // syncFileWriter wraps a SyncConn that has requested to send a file.

View file

@ -8,7 +8,7 @@ import (
"encoding/binary" "encoding/binary"
"strings" "strings"
"github.com/evrins/goadb/wire" "github.com/timoxa0/goadb/wire"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -6,7 +6,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
var ( var (

View file

@ -2,7 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/evrins/goadb/adb" "github.com/timoxa0/goadb/adb"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"

View file

@ -4,12 +4,12 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/evrins/goadb/adb" "github.com/timoxa0/goadb/adb"
"io/ioutil" "io/ioutil"
"log" "log"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
var ( var (

View file

@ -5,13 +5,13 @@ import (
"bufio" "bufio"
"flag" "flag"
"fmt" "fmt"
"github.com/evrins/goadb/adb" "github.com/timoxa0/goadb/adb"
"io" "io"
"log" "log"
"os" "os"
"strings" "strings"
"github.com/evrins/goadb/wire" "github.com/timoxa0/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")

2
go.mod
View file

@ -1,4 +1,4 @@
module github.com/evrins/goadb module github.com/timoxa0/goadb
go 1.14 go 1.14

View file

@ -1,6 +1,6 @@
package wire package wire
import "github.com/evrins/goadb/internal/errors" import "github.com/timoxa0/goadb/internal/errors"
const ( const (
// The official implementation of adb imposes an undocumented 255-byte limit // The official implementation of adb imposes an undocumented 255-byte limit

View file

@ -6,7 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
// TODO(zach): All EOF errors returned from networoking calls should use ConnectionResetError. // TODO(zach): All EOF errors returned from networoking calls should use ConnectionResetError.

View file

@ -7,7 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"testing" "testing"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
// Sender sends messages to the server. // Sender sends messages to the server.

View file

@ -1,6 +1,6 @@
package wire package wire
import "github.com/evrins/goadb/internal/errors" import "github.com/timoxa0/goadb/internal/errors"
const ( const (
// Chunks cannot be longer than 64k. // Chunks cannot be longer than 64k.

View file

@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
type SyncScanner interface { type SyncScanner interface {

View file

@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
type SyncSender interface { type SyncSender interface {

View file

@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View file

@ -6,7 +6,7 @@ import (
"regexp" "regexp"
"sync" "sync"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
) )
// ErrorResponseDetails is an error message returned by the server for a particular request. // ErrorResponseDetails is an error message returned by the server for a particular request.

View file

@ -3,7 +3,7 @@ package wire
import ( import (
"testing" "testing"
"github.com/evrins/goadb/internal/errors" "github.com/timoxa0/goadb/internal/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )