github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/app/stdio_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 app
     6  
     7  // Android redirects stdout and stderr to /dev/null.
     8  // As these are common debugging utilities in Go,
     9  // we redirect them to logcat.
    10  //
    11  // Unfortunately, logcat is line oriented, so we must buffer.
    12  
    13  /*
    14  #cgo LDFLAGS: -llog
    15  #include <android/log.h>
    16  #include <string.h>
    17  */
    18  import "C"
    19  
    20  import (
    21  	"bufio"
    22  	"log"
    23  	"os"
    24  	"unsafe"
    25  )
    26  
    27  var (
    28  	ctag    = C.CString("GoStdio")
    29  	ctagLog = C.CString("GoLog")
    30  )
    31  
    32  type infoWriter struct{}
    33  
    34  func (infoWriter) Write(p []byte) (n int, err error) {
    35  	cstr := C.CString(string(p))
    36  	C.__android_log_write(C.ANDROID_LOG_INFO, ctagLog, cstr)
    37  	C.free(unsafe.Pointer(cstr))
    38  	return len(p), nil
    39  }
    40  
    41  func lineLog(f *os.File, priority C.int) {
    42  	const logSize = 1024 // matches android/log.h.
    43  	r := bufio.NewReaderSize(f, logSize)
    44  	for {
    45  		line, _, err := r.ReadLine()
    46  		str := string(line)
    47  		if err != nil {
    48  			str += " " + err.Error()
    49  		}
    50  		cstr := C.CString(str)
    51  		C.__android_log_write(priority, ctag, cstr)
    52  		C.free(unsafe.Pointer(cstr))
    53  		if err != nil {
    54  			break
    55  		}
    56  	}
    57  }
    58  
    59  func init() {
    60  	log.SetOutput(infoWriter{})
    61  	// android logcat includes all of log.LstdFlags
    62  	log.SetFlags(log.Flags() &^ log.LstdFlags)
    63  
    64  	r, w, err := os.Pipe()
    65  	if err != nil {
    66  		panic(err)
    67  	}
    68  	os.Stderr = w
    69  	go lineLog(r, C.ANDROID_LOG_ERROR)
    70  
    71  	r, w, err = os.Pipe()
    72  	if err != nil {
    73  		panic(err)
    74  	}
    75  	os.Stdout = w
    76  	go lineLog(r, C.ANDROID_LOG_INFO)
    77  }