mobileinit_android.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package mobileinit
  5. /*
  6. To view the log output run:
  7. adb logcat GoLog:I *:S
  8. */
  9. // Android redirects stdout and stderr to /dev/null.
  10. // As these are common debugging utilities in Go,
  11. // we redirect them to logcat.
  12. //
  13. // Unfortunately, logcat is line oriented, so we must buffer.
  14. /*
  15. #cgo LDFLAGS: -landroid -llog
  16. #include <android/log.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. */
  20. import "C"
  21. import (
  22. "bufio"
  23. "log"
  24. "os"
  25. "syscall"
  26. "unsafe"
  27. )
  28. var (
  29. ctag = C.CString("GoLog")
  30. // Store the writer end of the redirected stderr and stdout
  31. // so that they are not garbage collected and closed.
  32. stderr, stdout *os.File
  33. )
  34. type infoWriter struct{}
  35. func (infoWriter) Write(p []byte) (n int, err error) {
  36. cstr := C.CString(string(p))
  37. C.__android_log_write(C.ANDROID_LOG_INFO, ctag, cstr)
  38. C.free(unsafe.Pointer(cstr))
  39. return len(p), nil
  40. }
  41. func lineLog(f *os.File, priority C.int) {
  42. const logSize = 1024 // matches android/log.h.
  43. r := bufio.NewReaderSize(f, logSize)
  44. for {
  45. line, _, err := r.ReadLine()
  46. str := string(line)
  47. if err != nil {
  48. str += " " + err.Error()
  49. }
  50. cstr := C.CString(str)
  51. C.__android_log_write(priority, ctag, cstr)
  52. C.free(unsafe.Pointer(cstr))
  53. if err != nil {
  54. break
  55. }
  56. }
  57. }
  58. func init() {
  59. log.SetOutput(infoWriter{})
  60. // android logcat includes all of log.LstdFlags
  61. log.SetFlags(log.Flags() &^ log.LstdFlags)
  62. r, w, err := os.Pipe()
  63. if err != nil {
  64. panic(err)
  65. }
  66. stderr = w
  67. if err := syscall.Dup3(int(w.Fd()), int(os.Stderr.Fd()), 0); err != nil {
  68. panic(err)
  69. }
  70. go lineLog(r, C.ANDROID_LOG_ERROR)
  71. r, w, err = os.Pipe()
  72. if err != nil {
  73. panic(err)
  74. }
  75. stdout = w
  76. if err := syscall.Dup3(int(w.Fd()), int(os.Stdout.Fd()), 0); err != nil {
  77. panic(err)
  78. }
  79. go lineLog(r, C.ANDROID_LOG_INFO)
  80. }