diff options
Diffstat (limited to 'platform_tools/android/bin/android_run_app.go')
-rw-r--r-- | platform_tools/android/bin/android_run_app.go | 248 |
1 files changed, 0 insertions, 248 deletions
diff --git a/platform_tools/android/bin/android_run_app.go b/platform_tools/android/bin/android_run_app.go deleted file mode 100644 index 53ae0fd938..0000000000 --- a/platform_tools/android/bin/android_run_app.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* - Run a Skia app to completion, piping the log to stdout. -*/ - -package main - -import ( - "flag" - "fmt" - "io" - "os" - "os/exec" - "os/signal" - "strconv" - "strings" - "time" - - "github.com/skia-dev/glog" - "go.skia.org/infra/go/common" -) - -const ( - COM_SKIA = "com.skia" -) - -var ( - adbPath = flag.String("adb", "", "Path to the ADB executable.") - app = flag.String("app", "VisualBench", "Name of the app to run.") - serial = flag.String("s", "", "Serial number for the Android device to use.") -) - -// Struct used for running ADB commands. -type ADB struct { - path string - serial string -} - -// ADBFromFlags returns an ADB instance based on flags passed to the program. -func ADBFromFlags() *ADB { - rv := &ADB{ - path: *adbPath, - serial: *serial, - } - if rv.path == "" { - rv.path = "adb" - } - return rv -} - -// Cmd creates an exec.Cmd object for the given ADB command. -func (adb *ADB) Cmd(log bool, args ...string) *exec.Cmd { - cmd := []string{} - if adb.serial != "" { - cmd = append(cmd, "-s", adb.serial) - } - cmd = append(cmd, args...) - if log { - glog.Infof("Exec `%s %s`", adb.path, strings.Join(cmd, " ")) - } - return exec.Command(adb.path, cmd...) -} - -// KillSkia kills any running process. -func (adb *ADB) Kill(proc string) error { - return adb.Cmd(false, "shell", "am", "force-stop", proc).Run() -} - -// PollSkia checks to see if the given process is running. If so, return the pid, otherwise return -1. -func (adb *ADB) Poll(proc string) (int64, error) { - output, err := adb.Cmd(false, "shell", "ps").Output() - if err != nil { - return -1, fmt.Errorf("Failed to check the running processes on the device: %v", err) - } - for _, line := range strings.Split(string(output), "\n") { - if strings.Contains(line, proc) { - fields := strings.Fields(line) - pid, err := strconv.ParseInt(fields[1], 10, 32) - if err != nil { - return -1, fmt.Errorf("Failed to parse \"%s\" to an integer: %v", fields[1], err) - } - return pid, nil - } - } - return -1, nil -} - -// ReadLinesFromPipe reads from the given pipe and logs its output. -func ReadLinesFromPipe(pipe io.Reader, lines chan string) { - buf := []byte{} - - // writeLine recovers from a panic when writing to the channel. - writeLine := func(s string) { - defer func() { - if r := recover(); r != nil { - glog.Warningf("Panic writing to channel... are we exiting?") - } - }() - lines <- s - } - - // readLines reads output lines from the buffer and pushes them into the channel. - readlines := func() { - readIdx := 0 - // Read lines from buf. - for i, b := range buf { - if b == '\n' { - s := string(buf[readIdx:i]) - writeLine(s) - readIdx = i + 1 - } - } - // Remove the lines we read. - buf = buf[readIdx:] - } - - // Loop forever, reading bytes from the pipe. - readbuf := make([]byte, 4096) - for { - read, err := pipe.Read(readbuf) - if read > 0 { - buf = append(buf, readbuf[:read]...) - - // Read lines from the buffers. - readlines() - } - if err != nil { - if err == io.EOF { - break - } else { - glog.Error(err) - } - } else if read == 0 { - time.Sleep(20 * time.Millisecond) - } - } - // Read any remaining lines from the buffers. - readlines() - // "Flush" any incomplete lines from the buffers. - writeLine(string(buf)) -} - -// RunApp launches the given app on the device, pipes its log output to stdout, -// and returns when the app finishes running, with an error if the app did not -// complete successfully. -func RunApp(adb *ADB, appName string, args []string) error { - // Kill any running instances of the app. - if err := adb.Kill(COM_SKIA); err != nil { - return fmt.Errorf("Failed to kill app: %v", err) - } - - // Clear the ADB log. - if err := adb.Cmd(false, "logcat", "-c").Run(); err != nil { - return fmt.Errorf("Failed to clear ADB log: %v", err) - } - - // Prepare to read the subprocess output. - logProc := adb.Cmd(false, "logcat") - defer func() { - // Cleanup. - if err := logProc.Process.Kill(); err != nil { - glog.Errorf("Failed to kill logcat process: %v", err) - } - }() - - stdout, err := logProc.StdoutPipe() - if err != nil { - return fmt.Errorf("Failed to obtain stdout pipe: %v", err) - } - stdoutLines := make(chan string) - stderr, err := logProc.StderrPipe() - if err != nil { - return fmt.Errorf("Failed to obtain stderr pipe: %v", err) - } - stderrLines := make(chan string) - - go ReadLinesFromPipe(stdout, stdoutLines) - go ReadLinesFromPipe(stderr, stderrLines) - if err := logProc.Start(); err != nil { - return fmt.Errorf("Failed to start logcat process.") - } - - // Launch the app. - stop := make(chan bool, 1) - activity := fmt.Sprintf("%s.%s/%s.%sActivity", COM_SKIA, strings.ToLower(appName), COM_SKIA, appName) - flags := strings.Join(args, " ") - cmd := []string{"shell", "am", "start", "-S", "-n", activity, "--es", "cmdLineFlags", flags} - output, err := adb.Cmd(true, cmd...).Output() - if err != nil { - return fmt.Errorf("Failed to launch app: %v", err) - } - glog.Info(string(output)) - // Make a handler for SIGINT so that we can kill the app if this script is interrupted. - go func() { - interrupt := make(chan os.Signal, 1) - signal.Notify(interrupt, os.Interrupt) - for _ = range interrupt { - glog.Infof("Received SIGINT; killing app.") - stop <- true - close(stdoutLines) - close(stderrLines) - if err := adb.Kill(COM_SKIA); err != nil { - glog.Errorf("Failed to kill app: %v", err) - } - if err := logProc.Process.Kill(); err != nil { - glog.Errorf("Failed to kill logcat process: %v", err) - } - } - }() - - // Loop until the app finishes or we're interrupted, writing output as appropriate. - // TODO(borenet): VisualBench should print its exit code. This script should exit - // with that code, or a non-zero code if the process ended without printing any code. - second := time.Tick(time.Second) -PollLoop: - for { - select { - case <-second: - // Poll the Skia process every second to make sure it's still running. - pid, err := adb.Poll(COM_SKIA) - if err != nil { - glog.Errorf("Failed to poll Skia process: %v", err) - } else if pid < 0 { - glog.Infof("Skia process is no longer running!") - break PollLoop - } - case <-stop: - break PollLoop - case line := <-stdoutLines: - glog.Info(line) - case line := <-stderrLines: - glog.Error(line) - } - } - - return nil -} - -func main() { - common.Init() - args := flag.Args() - if err := RunApp(ADBFromFlags(), *app, args); err != nil { - glog.Fatal(err) - } -} |