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  }