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