blob: d12a2313f903305c37a7ee2790216c27d30a8a36 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package adb
import (
"errors"
"fmt"
"strings"
)
// DeviceState represents the last queried state of an Android device.
type DeviceState int
// binary: DeviceState#Offline = offline
// binary: DeviceState#Online = device
// binary: DeviceState#Unauthorized = unauthorized
const (
Offline DeviceState = iota
Online
Unauthorized
)
// Device represents an attached Android device.
type Device struct {
Serial string
State DeviceState
}
// Command returns a new Cmd that will run the command with the specified name
// and arguments on this device.
func (d *Device) Command(path string, args ...string) *Cmd {
return &Cmd{
Path: path,
Args: args,
Device: d,
}
}
// SELinuxEnforcing returns true if the device is currently in a
// SELinux enforcing mode, or false if the device is currently in a SELinux
// permissive mode.
func (d *Device) SELinuxEnforcing() (bool, error) {
res, err := d.Command("getenforce").Call()
return strings.Contains(strings.ToLower(res), "enforcing"), err
}
// SetSELinuxEnforcing changes the SELinux-enforcing mode.
func (d *Device) SetSELinuxEnforcing(enforce bool) error {
if enforce {
return d.Command("setenforce", "1").Run()
} else {
return d.Command("setenforce", "0").Run()
}
}
// StartActivity launches the specified action.
func (d *Device) StartActivity(a Action) error {
return d.Command("am", "start",
// "-W", // Wait for launch to complete
"-S", // Force-stop the target app before starting the activity
"-a", a.Name,
"-n", a.Component).Run()
}
// String returns a string representing the device.
func (d *Device) String() string {
return fmt.Sprintf("Device<%s>", d.Serial)
}
// Devices returns the list of serial numbers of all the attached Android
// devices.
func Devices() ([]*Device, error) {
if adb == "" {
return nil, ErrADBNotFound
}
if out, err := run("devices"); err == nil {
return parseDevices(out)
} else {
return nil, err
}
}
func parseDevices(out string) ([]*Device, error) {
a := strings.SplitAfter(out, "List of devices attached")
if len(a) != 2 {
return nil, errors.New("Device list not returned")
}
lines := strings.Split(a[1], "\n")
devices := make([]*Device, 0, len(lines))
for _, line := range lines {
fields := strings.Fields(line)
switch len(fields) {
case 0:
continue
case 2:
state := DeviceState(0)
if err := state.Parse(fields[1]); err != nil {
return nil, err
}
device := &Device{
Serial: fields[0],
State: state,
}
devices = append(devices, device)
default:
return nil, errors.New("Could not parse device list")
}
}
return devices, nil
}