2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.ddmlib;
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
23 * Log class that mirrors the API in main Android sources.
24 * <p/>Default behavior outputs the log to {@link System#out}. Use
25 * {@link #setLogOutput(com.android.ddmlib.Log.ILogOutput)} to redirect the log somewhere else.
27 public final class Log {
32 public enum LogLevel {
33 VERBOSE(2, "verbose", 'V'), //$NON-NLS-1$
34 DEBUG(3, "debug", 'D'), //$NON-NLS-1$
35 INFO(4, "info", 'I'), //$NON-NLS-1$
36 WARN(5, "warn", 'W'), //$NON-NLS-1$
37 ERROR(6, "error", 'E'), //$NON-NLS-1$
38 ASSERT(7, "assert", 'A'); //$NON-NLS-1$
40 private int mPriorityLevel;
41 private String mStringValue;
42 private char mPriorityLetter;
44 LogLevel(int intPriority, String stringValue, char priorityChar) {
45 mPriorityLevel = intPriority;
46 mStringValue = stringValue;
47 mPriorityLetter = priorityChar;
50 public static LogLevel getByString(String value) {
51 for (LogLevel mode : values()) {
52 if (mode.mStringValue.equals(value)) {
61 * Returns the {@link LogLevel} enum matching the specified letter.
62 * @param letter the letter matching a <code>LogLevel</code> enum
63 * @return a <code>LogLevel</code> object or <code>null</code> if no match were found.
65 public static LogLevel getByLetter(char letter) {
66 for (LogLevel mode : values()) {
67 if (mode.mPriorityLetter == letter) {
76 * Returns the {@link LogLevel} enum matching the specified letter.
78 * The letter is passed as a {@link String} argument, but only the first character
80 * @param letter the letter matching a <code>LogLevel</code> enum
81 * @return a <code>LogLevel</code> object or <code>null</code> if no match were found.
83 public static LogLevel getByLetterString(String letter) {
84 if (letter.length() > 0) {
85 return getByLetter(letter.charAt(0));
92 * Returns the letter identifying the priority of the {@link LogLevel}.
94 public char getPriorityLetter() {
95 return mPriorityLetter;
99 * Returns the numerical value of the priority.
101 public int getPriority() {
102 return mPriorityLevel;
106 * Returns a non translated string representing the LogLevel.
108 public String getStringValue() {
114 * Classes which implement this interface provides methods that deal with outputting log
117 public interface ILogOutput {
119 * Sent when a log message needs to be printed.
120 * @param logLevel The {@link LogLevel} enum representing the priority of the message.
121 * @param tag The tag associated with the message.
122 * @param message The message to display.
124 public void printLog(LogLevel logLevel, String tag, String message);
127 * Sent when a log message needs to be printed, and, if possible, displayed to the user
129 * @param logLevel The {@link LogLevel} enum representing the priority of the message.
130 * @param tag The tag associated with the message.
131 * @param message The message to display.
133 public void printAndPromptLog(LogLevel logLevel, String tag, String message);
136 private static LogLevel mLevel = DdmPreferences.getLogLevel();
138 private static ILogOutput sLogOutput;
140 private static final char[] mSpaceLine = new char[72];
141 private static final char[] mHexDigit = new char[]
142 { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
144 /* prep for hex dump */
145 int i = mSpaceLine.length-1;
147 mSpaceLine[i--] = ' ';
148 mSpaceLine[0] = mSpaceLine[1] = mSpaceLine[2] = mSpaceLine[3] = '0';
152 static final class Config {
153 static final boolean LOGV = true;
154 static final boolean LOGD = true;
160 * Outputs a {@link LogLevel#VERBOSE} level message.
161 * @param tag The tag associated with the message.
162 * @param message The message to output.
164 public static void v(String tag, String message) {
165 println(LogLevel.VERBOSE, tag, message);
169 * Outputs a {@link LogLevel#DEBUG} level message.
170 * @param tag The tag associated with the message.
171 * @param message The message to output.
173 public static void d(String tag, String message) {
174 println(LogLevel.DEBUG, tag, message);
178 * Outputs a {@link LogLevel#INFO} level message.
179 * @param tag The tag associated with the message.
180 * @param message The message to output.
182 public static void i(String tag, String message) {
183 println(LogLevel.INFO, tag, message);
187 * Outputs a {@link LogLevel#WARN} level message.
188 * @param tag The tag associated with the message.
189 * @param message The message to output.
191 public static void w(String tag, String message) {
192 println(LogLevel.WARN, tag, message);
196 * Outputs a {@link LogLevel#ERROR} level message.
197 * @param tag The tag associated with the message.
198 * @param message The message to output.
200 public static void e(String tag, String message) {
201 println(LogLevel.ERROR, tag, message);
205 * Outputs a log message and attempts to display it in a dialog.
206 * @param tag The tag associated with the message.
207 * @param message The message to output.
209 public static void logAndDisplay(LogLevel logLevel, String tag, String message) {
210 if (sLogOutput != null) {
211 sLogOutput.printAndPromptLog(logLevel, tag, message);
213 println(logLevel, tag, message);
218 * Outputs a {@link LogLevel#ERROR} level {@link Throwable} information.
219 * @param tag The tag associated with the message.
220 * @param throwable The {@link Throwable} to output.
222 public static void e(String tag, Throwable throwable) {
223 if (throwable != null) {
224 StringWriter sw = new StringWriter();
225 PrintWriter pw = new PrintWriter(sw);
227 throwable.printStackTrace(pw);
228 println(LogLevel.ERROR, tag, throwable.getMessage() + '\n' + sw.toString());
232 static void setLevel(LogLevel logLevel) {
237 * Sets the {@link ILogOutput} to use to print the logs. If not set, {@link System#out}
239 * @param logOutput The {@link ILogOutput} to use to print the log.
241 public static void setLogOutput(ILogOutput logOutput) {
242 sLogOutput = logOutput;
248 * Local addition. Output looks like:
249 * 1230- 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
251 * Uses no string concatenation; creates one String object per line.
253 static void hexDump(String tag, LogLevel level, byte[] data, int offset, int length) {
257 char[] line = new char[mSpaceLine.length];
258 int addr, baseAddr, count;
260 boolean needErase = true;
262 //Log.w(tag, "HEX DUMP: off=" + offset + ", length=" + length);
265 while (length != 0) {
270 // partial line; re-copy blanks to clear end
276 System.arraycopy(mSpaceLine, 0, line, 0, mSpaceLine.length);
280 // output the address (currently limited to 4 hex digits)
285 line[ch] = mHexDigit[addr & 0x0f];
290 // output hex digits and ASCII chars
292 for (i = 0; i < count; i++) {
293 byte val = data[offset + i];
295 line[ch++] = mHexDigit[(val >>> 4) & 0x0f];
296 line[ch++] = mHexDigit[val & 0x0f];
299 if (val >= 0x20 && val < 0x7f)
300 line[kAscOffset + i] = (char) val;
302 line[kAscOffset + i] = '.';
305 println(level, tag, new String(line));
307 // advance to next chunk of data
316 * Dump the entire contents of a byte array with DEBUG priority.
318 static void hexDump(byte[] data) {
319 hexDump("ddms", LogLevel.DEBUG, data, 0, data.length);
322 /* currently prints to stdout; could write to a log window */
323 private static void println(LogLevel logLevel, String tag, String message) {
324 if (logLevel.getPriority() >= mLevel.getPriority()) {
325 if (sLogOutput != null) {
326 sLogOutput.printLog(logLevel, tag, message);
328 printLog(logLevel, tag, message);
334 * Prints a log message.
339 public static void printLog(LogLevel logLevel, String tag, String message) {
342 msec = System.currentTimeMillis();
343 String outMessage = String.format("%02d:%02d %c/%s: %s\n",
344 (msec / 60000) % 60, (msec / 1000) % 60,
345 logLevel.getPriorityLetter(), tag, message);
346 System.out.print(outMessage);