AndroidLog.sys.mjs (3176B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /** 7 * Native Android logging for JavaScript, wrapped for use by Log.sys.mjs. 8 * 9 * // Import it as a ESM: 10 * import { AndroidAppender } from "resource://gre/modules/AndroidLog.sys.mjs"; 11 * 12 * // Add the appender to a Log.sys.mjs appender: 13 * import { Log } from "resource://gre/modules/Log.sys.mjs"; 14 * let logger = Log.repository.getLogger("Example"); 15 * logger.addAppender(new AndroidAppender()); 16 * 17 * // Log with the normal Log.sys.mjs API: 18 * logger.info("This is an info message."); 19 * 20 * Note: Logger names will automatically be prepended with "Gecko" before being 21 * logged to the system logger, if they do not already have a "Gecko" prefix. 22 */ 23 24 import { ctypes } from "resource://gre/modules/ctypes.sys.mjs"; 25 import { Log } from "resource://gre/modules/Log.sys.mjs"; 26 27 // From <https://android.googlesource.com/platform/system/core/+/master/include/android/log.h>. 28 const ANDROID_LOG_VERBOSE = 2; 29 const ANDROID_LOG_DEBUG = 3; 30 const ANDROID_LOG_INFO = 4; 31 const ANDROID_LOG_WARN = 5; 32 const ANDROID_LOG_ERROR = 6; 33 34 var liblog = ctypes.open("liblog.so"); // /system/lib/liblog.so 35 var __android_log_write = liblog.declare( 36 "__android_log_write", 37 ctypes.default_abi, 38 ctypes.int, // return value: num bytes logged 39 ctypes.int, // priority (ANDROID_LOG_* constant) 40 ctypes.char.ptr, // tag 41 ctypes.char.ptr 42 ); // message 43 44 /** 45 * A formatter that does not prepend time/name/level information to messages, 46 * because those fields are logged separately when using the Android logger. 47 */ 48 class AndroidFormatter extends Log.BasicFormatter { 49 format(message) { 50 return this.formatText(message); 51 } 52 } 53 54 /* 55 * AndroidAppender 56 * Logs to Android logcat using __android_log_write 57 */ 58 export class AndroidAppender extends Log.Appender { 59 constructor(aFormatter) { 60 super(aFormatter || new AndroidFormatter()); 61 this._name = "AndroidAppender"; 62 63 // Map log level to __android_log_write priority 64 this._mapping = { 65 [Log.Level.Fatal]: ANDROID_LOG_ERROR, 66 [Log.Level.Error]: ANDROID_LOG_ERROR, 67 [Log.Level.Warn]: ANDROID_LOG_WARN, 68 [Log.Level.Info]: ANDROID_LOG_INFO, 69 [Log.Level.Config]: ANDROID_LOG_DEBUG, 70 [Log.Level.Debug]: ANDROID_LOG_DEBUG, 71 [Log.Level.Trace]: ANDROID_LOG_VERBOSE, 72 }; 73 } 74 75 append(aMessage) { 76 if (!aMessage) { 77 return; 78 } 79 80 // We'll prepend "Gecko" to the tag, so we strip any leading "Gecko" here. 81 // Also strip dots to save space. 82 const tag = aMessage.loggerName.replace(/^Gecko|\./g, ""); 83 const msg = this._formatter.format(aMessage); 84 85 // NOTE: android.util.Log.isLoggable throws IllegalArgumentException if a 86 // tag length exceeds 23 characters, and we prepend five characters 87 // ("Gecko") to every tag. However, __android_log_write itself and other 88 // android.util.Log methods don't seem to mind longer tags. 89 __android_log_write(this._mapping[aMessage.level], "Gecko" + tag, msg); 90 } 91 }