main.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/pkg/errors"
  10. goadb "github.com/yosemite-open/go-adb"
  11. )
  12. var adb *goadb.Adb
  13. const stfBinariesDir = "vendor/stf-binaries-master/node_modules"
  14. func init() {
  15. var err error
  16. adb, err = goadb.New()
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. serverVersion, err := adb.ServerVersion()
  21. if err != nil {
  22. log.Fatal(err)
  23. }
  24. fmt.Printf("adb server version: %d\n", serverVersion)
  25. }
  26. func initUiAutomator2(device *goadb.Device, serverAddr string) error {
  27. props, err := device.Properties()
  28. if err != nil {
  29. return err
  30. }
  31. sdk := props["ro.build.version.sdk"]
  32. abi := props["ro.product.cpu.abi"]
  33. pre := props["ro.build.version.preview_sdk"]
  34. // arch := props["ro.arch"]
  35. log.Printf("product model: %s\n", props["ro.product.model"])
  36. if pre != "" && pre != "0" {
  37. sdk += pre
  38. }
  39. log.Println("Install minicap and minitouch")
  40. if err := initSTFMiniTools(device, abi, sdk); err != nil {
  41. return errors.Wrap(err, "mini(cap|touch)")
  42. }
  43. log.Println("Install app-uiautomator[-test].apk")
  44. if err := initUiAutomatorAPK(device); err != nil {
  45. return errors.Wrap(err, "app-uiautomator[-test].apk")
  46. }
  47. log.Println("Install atx-agent")
  48. atxAgentPath := "vendor/atx-agent"
  49. if err := writeFileToDevice(device, atxAgentPath, "/data/local/tmp/atx-agent", 0755); err != nil {
  50. return errors.Wrap(err, "atx-agent")
  51. }
  52. args := []string{"-d"}
  53. if serverAddr != "" {
  54. args = append(args, "-t", serverAddr)
  55. }
  56. output, err := device.RunCommand("/data/local/tmp/atx-agent", args...)
  57. output = strings.TrimSpace(output)
  58. if err != nil {
  59. return errors.Wrap(err, "start atx-agent")
  60. }
  61. serial, _ := device.Serial()
  62. fmt.Println(serial, output)
  63. return nil
  64. }
  65. func writeFileToDevice(device *goadb.Device, src, dst string, mode os.FileMode) error {
  66. f, err := os.Open(src)
  67. if err != nil {
  68. return err
  69. }
  70. defer f.Close()
  71. dstTemp := dst + ".tmp-magic1231x"
  72. _, err = device.WriteToFile(dstTemp, f, mode)
  73. if err != nil {
  74. device.RunCommand("rm", dstTemp)
  75. return err
  76. }
  77. // use mv to prevent "text busy" error
  78. _, err = device.RunCommand("mv", dstTemp, dst)
  79. return err
  80. }
  81. func initMiniTouch(device *goadb.Device, abi string) error {
  82. srcPath := fmt.Sprintf(stfBinariesDir+"/minitouch-prebuilt/prebuilt/%s/bin/minitouch", abi)
  83. return writeFileToDevice(device, srcPath, "/data/local/tmp/minitouch", 0755)
  84. }
  85. func initSTFMiniTools(device *goadb.Device, abi, sdk string) error {
  86. soSrcPath := fmt.Sprintf(stfBinariesDir+"/minicap-prebuilt/prebuilt/%s/lib/android-%s/minicap.so", abi, sdk)
  87. err := writeFileToDevice(device, soSrcPath, "/data/local/tmp/minicap.so", 0644)
  88. if err != nil {
  89. return err
  90. }
  91. binSrcPath := fmt.Sprintf(stfBinariesDir+"/minicap-prebuilt/prebuilt/%s/bin/minicap", abi)
  92. err = writeFileToDevice(device, binSrcPath, "/data/local/tmp/minicap", 0755)
  93. if err != nil {
  94. return err
  95. }
  96. touchSrcPath := fmt.Sprintf(stfBinariesDir+"/minitouch-prebuilt/prebuilt/%s/bin/minitouch", abi)
  97. return writeFileToDevice(device, touchSrcPath, "/data/local/tmp/minitouch", 0755)
  98. }
  99. func installAPK(device *goadb.Device, localPath string) error {
  100. dstPath := "/data/local/tmp/" + filepath.Base(localPath)
  101. if err := writeFileToDevice(device, localPath, dstPath, 0644); err != nil {
  102. return err
  103. }
  104. defer device.RunCommand("rm", dstPath)
  105. output, err := device.RunCommand("pm", "install", "-r", "-t", dstPath)
  106. if err != nil {
  107. return err
  108. }
  109. if !strings.Contains(output, "Success") {
  110. return errors.Wrap(errors.New(output), "apk-install")
  111. }
  112. return nil
  113. }
  114. func initUiAutomatorAPK(device *goadb.Device) (err error) {
  115. _, er1 := device.StatPackage("com.github.uiautomator")
  116. _, er2 := device.StatPackage("com.github.uiautomator.test")
  117. if er1 == nil && er2 == nil {
  118. log.Println("APK already installed, Skip. Uninstall apk manually if you want to reinstall apk")
  119. return
  120. }
  121. err = installAPK(device, "vendor/app-uiautomator.apk")
  122. if err != nil {
  123. return
  124. }
  125. return installAPK(device, "vendor/app-uiautomator-test.apk")
  126. }
  127. func startService(device *goadb.Device) (err error) {
  128. _, err = device.RunCommand("am", "startservice", "-n", "com.github.uiautomator/.Service")
  129. return err
  130. }
  131. func watchAndInit(serverAddr string) {
  132. watcher := adb.NewDeviceWatcher()
  133. for event := range watcher.C() {
  134. if event.CameOnline() {
  135. log.Printf("Device %s came online", event.Serial)
  136. device := adb.Device(goadb.DeviceWithSerial(event.Serial))
  137. log.Printf("Init device")
  138. if err := initUiAutomator2(device, serverAddr); err != nil {
  139. log.Printf("Init error: %v", err)
  140. continue
  141. } else {
  142. log.Printf("Init Success")
  143. startService(device)
  144. }
  145. }
  146. if event.WentOffline() {
  147. log.Printf("Device %s went offline", event.Serial)
  148. }
  149. }
  150. if watcher.Err() != nil {
  151. log.Fatal(watcher.Err())
  152. }
  153. }
  154. func main() {
  155. serverAddr := flag.String("server", "", "atx-server address(must be ip:port) eg: 10.0.0.1:7700")
  156. flag.Parse()
  157. fmt.Println("u2init version 20180330")
  158. wd, _ := os.Getwd()
  159. log.Println("Add adb.exe to PATH +=", filepath.Join(wd, "vendor"))
  160. newPath := fmt.Sprintf("%s%s%s", os.Getenv("PATH"), string(os.PathListSeparator), filepath.Join(wd, "vendor"))
  161. os.Setenv("PATH", newPath)
  162. watchAndInit(*serverAddr)
  163. }