/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * Native Android logging for JavaScript, wrapped for use by Log.sys.mjs. * * // Import it as a ESM: * import { AndroidAppender } from "resource://gre/modules/AndroidLog.sys.mjs"; * * // Add the appender to a Log.sys.mjs appender: * import { Log } from "resource://gre/modules/Log.sys.mjs"; * let logger = Log.repository.getLogger("Example"); * logger.addAppender(new AndroidAppender()); * * // Log with the normal Log.sys.mjs API: * logger.info("This is an info message."); * * Note: Logger names will automatically be prepended with "Gecko" before being * logged to the system logger, if they do not already have a "Gecko" prefix. */ import { ctypes } from "resource://gre/modules/ctypes.sys.mjs"; import { Log } from "resource://gre/modules/Log.sys.mjs"; // From . const ANDROID_LOG_VERBOSE = 2; const ANDROID_LOG_DEBUG = 3; const ANDROID_LOG_INFO = 4; const ANDROID_LOG_WARN = 5; const ANDROID_LOG_ERROR = 6; var liblog = ctypes.open("liblog.so"); // /system/lib/liblog.so var __android_log_write = liblog.declare( "__android_log_write", ctypes.default_abi, ctypes.int, // return value: num bytes logged ctypes.int, // priority (ANDROID_LOG_* constant) ctypes.char.ptr, // tag ctypes.char.ptr ); // message /** * A formatter that does not prepend time/name/level information to messages, * because those fields are logged separately when using the Android logger. */ class AndroidFormatter extends Log.BasicFormatter { format(message) { return this.formatText(message); } } /* * AndroidAppender * Logs to Android logcat using __android_log_write */ export class AndroidAppender extends Log.Appender { constructor(aFormatter) { super(aFormatter || new AndroidFormatter()); this._name = "AndroidAppender"; // Map log level to __android_log_write priority this._mapping = { [Log.Level.Fatal]: ANDROID_LOG_ERROR, [Log.Level.Error]: ANDROID_LOG_ERROR, [Log.Level.Warn]: ANDROID_LOG_WARN, [Log.Level.Info]: ANDROID_LOG_INFO, [Log.Level.Config]: ANDROID_LOG_DEBUG, [Log.Level.Debug]: ANDROID_LOG_DEBUG, [Log.Level.Trace]: ANDROID_LOG_VERBOSE, }; } append(aMessage) { if (!aMessage) { return; } // We'll prepend "Gecko" to the tag, so we strip any leading "Gecko" here. // Also strip dots to save space. const tag = aMessage.loggerName.replace(/^Gecko|\./g, ""); const msg = this._formatter.format(aMessage); // NOTE: android.util.Log.isLoggable throws IllegalArgumentException if a // tag length exceeds 23 characters, and we prepend five characters // ("Gecko") to every tag. However, __android_log_write itself and other // android.util.Log methods don't seem to mind longer tags. __android_log_write(this._mapping[aMessage.level], "Gecko" + tag, msg); } }