github.com/TimaSlipko/gomobile@v1.0.8/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 <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  }