-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathclient.go
146 lines (129 loc) · 3.03 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"fmt"
"log"
"net"
"os/exec"
"strconv"
"strings"
)
type AdbClient struct {
Addr string
}
func NewAdbClient() *AdbClient {
return &AdbClient{
Addr: defaultHost + ":" + strconv.Itoa(defaultPort),
}
}
var DefaultAdbClient = &AdbClient{
Addr: "127.0.0.1:5037",
}
func (c *AdbClient) newConnection() (conn *AdbConnection, err error) {
netConn, err := net.Dial("tcp", c.Addr)
if err != nil {
return nil, err
}
return &AdbConnection{netConn}, nil
}
// Version return 4 size string
func (c *AdbClient) Version() (string, error) {
ver, err := c.rawVersion()
if err == nil {
return ver, nil
}
exec.Command(adbPath(), "start-server").Run()
return c.rawVersion()
}
// Plugged in: StateDisconnected->StateOffline->StateOnline
// Unplugged: StateOnline->StateDisconnected
type DeviceState string
const (
StateInvalid = ""
StateDisconnected = "disconnected"
StateOffline = "offline"
StateOnline = "device"
StateUnauthorized = "unauthorized"
)
func newDeviceState(s string) DeviceState {
switch s {
case "device":
return StateOnline
case "offline":
return StateOffline
case "disconnected":
return StateDisconnected
case "unauthorized":
return StateUnauthorized
default:
return StateInvalid
}
}
type DeviceStateChangedEvent struct {
Serial string
OldState DeviceState
NewState DeviceState
}
func (s DeviceStateChangedEvent) String() string {
return fmt.Sprintf("%s: %s->%s", s.Serial, s.OldState, s.NewState)
}
// CameOnline returns true if this event represents a device coming online.
func (s DeviceStateChangedEvent) CameOnline() bool {
return s.OldState != StateOnline && s.NewState == StateOnline
}
// WentOffline returns true if this event represents a device going offline.
func (s DeviceStateChangedEvent) WentOffline() bool {
return s.OldState == StateOnline && s.NewState != StateOnline
}
func (c *AdbClient) Watch() (C chan DeviceStateChangedEvent, err error) {
C = make(chan DeviceStateChangedEvent, 0)
conn, err := c.newConnection()
if err != nil {
return
}
conn.WritePacket("host:track-devices")
go func() {
defer close(C)
var lastKnownStates = make(map[string]DeviceState)
for {
line, err := conn.readString()
if err != nil {
break
}
line = strings.TrimSpace(line)
log.Println("TRACK", strconv.Quote(line))
if line == "" {
continue
}
parts := strings.Split(line, "\t")
if len(parts) != 2 {
continue
}
serial, state := parts[0], newDeviceState(parts[1])
C <- DeviceStateChangedEvent{
Serial: serial,
OldState: lastKnownStates[serial],
NewState: state,
}
lastKnownStates[serial] = state
}
}()
return
}
// Version returns adb server version
func (c *AdbClient) rawVersion() (string, error) {
conn, err := c.newConnection()
if err != nil {
return "", err
}
defer conn.Close()
if err := conn.WritePacket("host:version"); err != nil {
return "", err
}
return conn.readString()
}
func (c *AdbClient) DeviceWithSerial(serial string) *AdbDevice {
return &AdbDevice{
AdbClient: c,
Serial: serial,
}
}