diff --git a/app/internal/log/log_android.go b/app/internal/log/log_android.go index 3c2f79c2..3f7d2cc1 100644 --- a/app/internal/log/log_android.go +++ b/app/internal/log/log_android.go @@ -19,13 +19,39 @@ import ( "unsafe" ) +// 1024 is the truncation limit from android/log.h, plus a \n. +const logLineLimit = 1024 + +var logTag = C.CString("gio") + func init() { // Android's logcat already includes timestamps. log.SetFlags(log.Flags() &^ log.LstdFlags) + log.SetOutput(new(androidLogWriter)) + + // Redirect stdout and stderr to the Android logger. logFd(os.Stdout.Fd()) logFd(os.Stderr.Fd()) } +type androidLogWriter struct { + // buf has room for the maximum log line, plus a terminating '\0'. + buf [logLineLimit + 1]byte +} + +func (w *androidLogWriter) Write(data []byte) (int, error) { + // Truncate the buffer, leaving space for the '\0'. + if max := len(w.buf) - 1; len(data) > max { + data = data[:max] + } + buf := w.buf[:len(data)+1] + copy(buf, data) + // Terminating '\0'. + buf[len(data)] = 0 + C.__android_log_write(C.ANDROID_LOG_INFO, logTag, (*C.char)(unsafe.Pointer(&buf[0]))) + return len(data), nil +} + func logFd(fd uintptr) { r, w, err := os.Pipe() if err != nil { @@ -35,10 +61,7 @@ func logFd(fd uintptr) { panic(err) } go func() { - tag := C.CString("gio") - defer C.free(unsafe.Pointer(tag)) - // 1024 is the truncation limit from android/log.h, plus a \n. - lineBuf := bufio.NewReaderSize(r, 1024) + lineBuf := bufio.NewReaderSize(r, logLineLimit) // The buffer to pass to C, including the terminating '\0'. buf := make([]byte, lineBuf.Size()+1) cbuf := (*C.char)(unsafe.Pointer(&buf[0])) @@ -49,7 +72,7 @@ func logFd(fd uintptr) { } copy(buf, line) buf[len(line)] = 0 - C.__android_log_write(C.ANDROID_LOG_INFO, tag, cbuf) + C.__android_log_write(C.ANDROID_LOG_INFO, logTag, cbuf) } // The garbage collector doesn't know that w's fd was dup'ed. // Avoid finalizing w, and thereby avoid its finalizer closing its fd.