gioui.org/ui@v0.0.0-20190926171558-ce74bc0cbaea/app/log_android.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package app
     4  
     5  /*
     6  #cgo LDFLAGS: -llog
     7  
     8  #include <stdlib.h>
     9  #include <android/log.h>
    10  */
    11  import "C"
    12  
    13  import (
    14  	"bufio"
    15  	"log"
    16  	"os"
    17  	"runtime"
    18  	"syscall"
    19  	"unsafe"
    20  )
    21  
    22  func init() {
    23  	// Android's logcat already includes timestamps.
    24  	log.SetFlags(log.Flags() &^ log.LstdFlags)
    25  	logFd(os.Stdout.Fd())
    26  	logFd(os.Stderr.Fd())
    27  }
    28  
    29  func logFd(fd uintptr) {
    30  	r, w, err := os.Pipe()
    31  	if err != nil {
    32  		panic(err)
    33  	}
    34  	if err := syscall.Dup3(int(w.Fd()), int(fd), syscall.O_CLOEXEC); err != nil {
    35  		panic(err)
    36  	}
    37  	go func() {
    38  		tag := C.CString("gio")
    39  		defer C.free(unsafe.Pointer(tag))
    40  		// 1024 is the truncation limit from android/log.h, plus a \n.
    41  		lineBuf := bufio.NewReaderSize(r, 1024)
    42  		// The buffer to pass to C, including the terminating '\0'.
    43  		buf := make([]byte, lineBuf.Size()+1)
    44  		cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
    45  		for {
    46  			line, _, err := lineBuf.ReadLine()
    47  			if err != nil {
    48  				break
    49  			}
    50  			copy(buf, line)
    51  			buf[len(line)] = 0
    52  			C.__android_log_write(C.ANDROID_LOG_INFO, tag, cbuf)
    53  		}
    54  		// The garbage collector doesn't know that w's fd was dup'ed.
    55  		// Avoid finalizing w, and thereby avoid its finalizer closing its fd.
    56  		runtime.KeepAlive(w)
    57  	}()
    58  }