github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/internal/mobileinit/mobileinit_android.go (about)

     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 <string.h>
    23  */
    24  import "C"
    25  
    26  import (
    27  	"bufio"
    28  	"log"
    29  	"os"
    30  	"unsafe"
    31  )
    32  
    33  var (
    34  	ctag = C.CString("GoLog")
    35  )
    36  
    37  type infoWriter struct{}
    38  
    39  func (infoWriter) Write(p []byte) (n int, err error) {
    40  	cstr := C.CString(string(p))
    41  	C.__android_log_write(C.ANDROID_LOG_INFO, ctag, cstr)
    42  	C.free(unsafe.Pointer(cstr))
    43  	return len(p), nil
    44  }
    45  
    46  func lineLog(f *os.File, priority C.int) {
    47  	const logSize = 1024 // matches android/log.h.
    48  	r := bufio.NewReaderSize(f, logSize)
    49  	for {
    50  		line, _, err := r.ReadLine()
    51  		str := string(line)
    52  		if err != nil {
    53  			str += " " + err.Error()
    54  		}
    55  		cstr := C.CString(str)
    56  		C.__android_log_write(priority, ctag, cstr)
    57  		C.free(unsafe.Pointer(cstr))
    58  		if err != nil {
    59  			break
    60  		}
    61  	}
    62  }
    63  
    64  func init() {
    65  	log.SetOutput(infoWriter{})
    66  	// android logcat includes all of log.LstdFlags
    67  	log.SetFlags(log.Flags() &^ log.LstdFlags)
    68  
    69  	r, w, err := os.Pipe()
    70  	if err != nil {
    71  		panic(err)
    72  	}
    73  	os.Stderr = w
    74  	go lineLog(r, C.ANDROID_LOG_ERROR)
    75  
    76  	r, w, err = os.Pipe()
    77  	if err != nil {
    78  		panic(err)
    79  	}
    80  	os.Stdout = w
    81  	go lineLog(r, C.ANDROID_LOG_INFO)
    82  }