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