All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.ddmlib.Log Maven / Gradle / Ivy

There is a newer version: 25.3.0
Show newest version
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ddmlib;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.google.common.collect.Sets;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Set;

/**
 * Log class that mirrors the API in main Android sources.
 * 

Default behavior outputs the log to {@link System#out}. Use * {@link #addLogger(ILogOutput)} to redirect the log somewhere else. */ public final class Log { /** * Log Level enum. */ public enum LogLevel { VERBOSE(2, "verbose", 'V'), //$NON-NLS-1$ DEBUG(3, "debug", 'D'), //$NON-NLS-1$ INFO(4, "info", 'I'), //$NON-NLS-1$ WARN(5, "warn", 'W'), //$NON-NLS-1$ ERROR(6, "error", 'E'), //$NON-NLS-1$ ASSERT(7, "assert", 'A'); //$NON-NLS-1$ private int mPriorityLevel; private String mStringValue; private char mPriorityLetter; LogLevel(int intPriority, String stringValue, char priorityChar) { mPriorityLevel = intPriority; mStringValue = stringValue; mPriorityLetter = priorityChar; } public static LogLevel getByString(String value) { for (LogLevel mode : values()) { if (mode.mStringValue.equals(value)) { return mode; } } return null; } /** * Returns the {@link LogLevel} enum matching the specified letter. * @param letter the letter matching a LogLevel enum * @return a LogLevel object or null if no match were found. */ public static LogLevel getByLetter(char letter) { for (LogLevel mode : values()) { if (mode.mPriorityLetter == letter) { return mode; } } return null; } /** * Returns the {@link LogLevel} enum matching the specified letter. *

* The letter is passed as a {@link String} argument, but only the first character * is used. * @param letter the letter matching a LogLevel enum * @return a LogLevel object or null if no match were found. */ public static LogLevel getByLetterString(String letter) { if (!letter.isEmpty()) { return getByLetter(letter.charAt(0)); } return null; } /** * Returns the letter identifying the priority of the {@link LogLevel}. */ public char getPriorityLetter() { return mPriorityLetter; } /** * Returns the numerical value of the priority. */ public int getPriority() { return mPriorityLevel; } /** * Returns a non translated string representing the LogLevel. */ public String getStringValue() { return mStringValue; } } /** * Classes which implement this interface provides methods that deal with outputting log * messages. */ public interface ILogOutput { /** * Sent when a log message needs to be printed. * @param logLevel The {@link LogLevel} enum representing the priority of the message. * @param tag The tag associated with the message. * @param message The message to display. */ void printLog(LogLevel logLevel, String tag, String message); /** * Sent when a log message needs to be printed, and, if possible, displayed to the user * in a dialog box. * @param logLevel The {@link LogLevel} enum representing the priority of the message. * @param tag The tag associated with the message. * @param message The message to display. */ void printAndPromptLog(LogLevel logLevel, String tag, String message); } private static LogLevel sLevel = DdmPreferences.getLogLevel(); @Nullable private static ILogOutput sLogOutput; @NonNull private static final Set sOutputLoggers = Sets.newCopyOnWriteArraySet(); private static final char[] mSpaceLine = new char[72]; private static final char[] mHexDigit = new char[] { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; static { /* prep for hex dump */ int i = mSpaceLine.length-1; while (i >= 0) mSpaceLine[i--] = ' '; mSpaceLine[0] = mSpaceLine[1] = mSpaceLine[2] = mSpaceLine[3] = '0'; mSpaceLine[4] = '-'; } static final class Config { static final boolean LOGV = true; static final boolean LOGD = true; } private Log() {} /** * Outputs a {@link LogLevel#VERBOSE} level message. * @param tag The tag associated with the message. * @param message The message to output. */ public static void v(String tag, String message) { println(LogLevel.VERBOSE, tag, message); } /** * Outputs a {@link LogLevel#DEBUG} level message. * @param tag The tag associated with the message. * @param message The message to output. */ public static void d(String tag, String message) { println(LogLevel.DEBUG, tag, message); } /** * Outputs a {@link LogLevel#INFO} level message. * @param tag The tag associated with the message. * @param message The message to output. */ public static void i(String tag, String message) { println(LogLevel.INFO, tag, message); } /** * Outputs a {@link LogLevel#WARN} level message. * @param tag The tag associated with the message. * @param message The message to output. */ public static void w(String tag, String message) { println(LogLevel.WARN, tag, message); } /** * Outputs a {@link LogLevel#ERROR} level message. * @param tag The tag associated with the message. * @param message The message to output. */ public static void e(String tag, String message) { println(LogLevel.ERROR, tag, message); } /** * Outputs a log message and attempts to display it in a dialog. * @param tag The tag associated with the message. * @param message The message to output. */ public static void logAndDisplay(LogLevel logLevel, String tag, String message) { if (!sOutputLoggers.isEmpty()) { for (ILogOutput logger : sOutputLoggers) { logger.printAndPromptLog(logLevel, tag, message); } } if (sLogOutput != null) { sLogOutput.printAndPromptLog(logLevel, tag, message); } else if (sOutputLoggers.isEmpty()) { println(logLevel, tag, message); } } /** * Outputs a {@link LogLevel#ERROR} level {@link Throwable} information. * @param tag The tag associated with the message. * @param throwable The {@link Throwable} to output. */ public static void e(String tag, Throwable throwable) { if (throwable != null) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(pw); println(LogLevel.ERROR, tag, throwable.getMessage() + '\n' + sw.toString()); } } static void setLevel(LogLevel logLevel) { sLevel = logLevel; } /** * @deprecated Use {@link #addLogger(ILogOutput)} instead.

* Sets the {@link ILogOutput} to use to print the logs. If not set, {@link System#out} * will be used. * @param logOutput The {@link ILogOutput} to use to print the log. */ @Deprecated public static void setLogOutput(ILogOutput logOutput) { sLogOutput = logOutput; } public static void addLogger(@NonNull ILogOutput logOutput) { sOutputLoggers.add(logOutput); } public static void removeLogger(@NonNull ILogOutput logOutput) { sOutputLoggers.remove(logOutput); } /** * Show hex dump. *

* Local addition. Output looks like: * 1230- 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef *

* Uses no string concatenation; creates one String object per line. */ static void hexDump(String tag, LogLevel level, byte[] data, int offset, int length) { int kHexOffset = 6; int kAscOffset = 55; char[] line = new char[mSpaceLine.length]; int addr, baseAddr, count; int i, ch; boolean needErase = true; //Log.w(tag, "HEX DUMP: off=" + offset + ", length=" + length); baseAddr = 0; while (length != 0) { if (length > 16) { // full line count = 16; } else { // partial line; re-copy blanks to clear end count = length; needErase = true; } if (needErase) { System.arraycopy(mSpaceLine, 0, line, 0, mSpaceLine.length); needErase = false; } // output the address (currently limited to 4 hex digits) addr = baseAddr; addr &= 0xffff; ch = 3; while (addr != 0) { line[ch] = mHexDigit[addr & 0x0f]; ch--; addr >>>= 4; } // output hex digits and ASCII chars ch = kHexOffset; for (i = 0; i < count; i++) { byte val = data[offset + i]; line[ch++] = mHexDigit[(val >>> 4) & 0x0f]; line[ch++] = mHexDigit[val & 0x0f]; ch++; if (val >= 0x20 && val < 0x7f) line[kAscOffset + i] = (char) val; else line[kAscOffset + i] = '.'; } println(level, tag, new String(line)); // advance to next chunk of data length -= count; offset += count; baseAddr += count; } } /** * Dump the entire contents of a byte array with DEBUG priority. */ static void hexDump(byte[] data) { hexDump("ddms", LogLevel.DEBUG, data, 0, data.length); } private static void println(LogLevel logLevel, String tag, String message) { if (logLevel.getPriority() < sLevel.getPriority()) { return; } if (!sOutputLoggers.isEmpty()) { for (ILogOutput logger : sOutputLoggers) { logger.printLog(logLevel, tag, message); } } if (sLogOutput != null) { sLogOutput.printLog(logLevel, tag, message); } else if (sOutputLoggers.isEmpty()) { printLog(logLevel, tag, message); } } public static void printLog(LogLevel logLevel, String tag, String message) { System.out.print(getLogFormatString(logLevel, tag, message)); } public static String getLogFormatString(LogLevel logLevel, String tag, String message) { SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss", Locale.getDefault()); return String.format("%s %c/%s: %s\n", formatter.format(new Date()), logLevel.getPriorityLetter(), tag, message); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy