OSDN Git Service

android-2.1_r1 snapshot
[android-x86/sdk.git] / ddms / libs / ddmlib / src / com / android / ddmlib / Log.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.ddmlib;
18
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
21
22 /**
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.
26  */
27 public final class Log {
28
29     /**
30      * Log Level enum.
31      */
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$
39
40         private int mPriorityLevel;
41         private String mStringValue;
42         private char mPriorityLetter;
43
44         LogLevel(int intPriority, String stringValue, char priorityChar) {
45             mPriorityLevel = intPriority;
46             mStringValue = stringValue;
47             mPriorityLetter = priorityChar;
48         }
49
50         public static LogLevel getByString(String value) {
51             for (LogLevel mode : values()) {
52                 if (mode.mStringValue.equals(value)) {
53                     return mode;
54                 }
55             }
56
57             return null;
58         }
59         
60         /**
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.
64          */
65         public static LogLevel getByLetter(char letter) {
66             for (LogLevel mode : values()) {
67                 if (mode.mPriorityLetter == letter) {
68                     return mode;
69                 }
70             }
71
72             return null;
73         }
74
75         /**
76          * Returns the {@link LogLevel} enum matching the specified letter.
77          * <p/>
78          * The letter is passed as a {@link String} argument, but only the first character
79          * is used. 
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.
82          */
83         public static LogLevel getByLetterString(String letter) {
84             if (letter.length() > 0) {
85                 return getByLetter(letter.charAt(0));
86             }
87
88             return null;
89         }
90
91         /**
92          * Returns the letter identifying the priority of the {@link LogLevel}.
93          */
94         public char getPriorityLetter() {
95             return mPriorityLetter;
96         }
97
98         /**
99          * Returns the numerical value of the priority.
100          */
101         public int getPriority() {
102             return mPriorityLevel;
103         }
104
105         /**
106          * Returns a non translated string representing the LogLevel.
107          */
108         public String getStringValue() {
109             return mStringValue;
110         }
111     }
112     
113     /**
114      * Classes which implement this interface provides methods that deal with outputting log
115      * messages.
116      */
117     public interface ILogOutput {
118         /**
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.
123          */
124         public void printLog(LogLevel logLevel, String tag, String message);
125
126         /**
127          * Sent when a log message needs to be printed, and, if possible, displayed to the user
128          * in a dialog box.
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.
132          */
133         public void printAndPromptLog(LogLevel logLevel, String tag, String message);
134     }
135
136     private static LogLevel mLevel = DdmPreferences.getLogLevel();
137
138     private static ILogOutput sLogOutput;
139
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' };
143     static {
144         /* prep for hex dump */
145         int i = mSpaceLine.length-1;
146         while (i >= 0)
147             mSpaceLine[i--] = ' ';
148         mSpaceLine[0] = mSpaceLine[1] = mSpaceLine[2] = mSpaceLine[3] = '0';
149         mSpaceLine[4] = '-';
150     }
151
152     static final class Config {
153         static final boolean LOGV = true;
154         static final boolean LOGD = true;
155     };
156
157     private Log() {}
158
159     /**
160      * Outputs a {@link LogLevel#VERBOSE} level message.
161      * @param tag The tag associated with the message.
162      * @param message The message to output.
163      */
164     public static void v(String tag, String message) {
165         println(LogLevel.VERBOSE, tag, message);
166     }
167
168     /**
169      * Outputs a {@link LogLevel#DEBUG} level message.
170      * @param tag The tag associated with the message.
171      * @param message The message to output.
172      */
173     public static void d(String tag, String message) {
174         println(LogLevel.DEBUG, tag, message);
175     }
176
177     /**
178      * Outputs a {@link LogLevel#INFO} level message.
179      * @param tag The tag associated with the message.
180      * @param message The message to output.
181      */
182     public static void i(String tag, String message) {
183         println(LogLevel.INFO, tag, message);
184     }
185
186     /**
187      * Outputs a {@link LogLevel#WARN} level message.
188      * @param tag The tag associated with the message.
189      * @param message The message to output.
190      */
191     public static void w(String tag, String message) {
192         println(LogLevel.WARN, tag, message);
193     }
194
195     /**
196      * Outputs a {@link LogLevel#ERROR} level message.
197      * @param tag The tag associated with the message.
198      * @param message The message to output.
199      */
200     public static void e(String tag, String message) {
201         println(LogLevel.ERROR, tag, message);
202     }
203
204     /**
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.
208      */
209     public static void logAndDisplay(LogLevel logLevel, String tag, String message) {
210         if (sLogOutput != null) {
211             sLogOutput.printAndPromptLog(logLevel, tag, message);
212         } else {
213             println(logLevel, tag, message);
214         }
215     }
216
217     /**
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.
221      */
222     public static void e(String tag, Throwable throwable) {
223         if (throwable != null) {
224             StringWriter sw = new StringWriter();
225             PrintWriter pw = new PrintWriter(sw);
226
227             throwable.printStackTrace(pw);
228             println(LogLevel.ERROR, tag, throwable.getMessage() + '\n' + sw.toString());
229         }
230     }
231
232     static void setLevel(LogLevel logLevel) {
233         mLevel = logLevel;
234     }
235
236     /**
237      * Sets the {@link ILogOutput} to use to print the logs. If not set, {@link System#out}
238      * will be used.
239      * @param logOutput The {@link ILogOutput} to use to print the log.
240      */
241     public static void setLogOutput(ILogOutput logOutput) {
242         sLogOutput = logOutput;
243     }
244
245     /**
246      * Show hex dump.
247      * <p/>
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
250      * <p/>
251      * Uses no string concatenation; creates one String object per line.
252      */
253     static void hexDump(String tag, LogLevel level, byte[] data, int offset, int length) {
254
255         int kHexOffset = 6;
256         int kAscOffset = 55;
257         char[] line = new char[mSpaceLine.length];
258         int addr, baseAddr, count;
259         int i, ch;
260         boolean needErase = true;
261
262         //Log.w(tag, "HEX DUMP: off=" + offset + ", length=" + length);
263
264         baseAddr = 0;
265         while (length != 0) {
266             if (length > 16) {
267                 // full line
268                 count = 16;
269             } else {
270                 // partial line; re-copy blanks to clear end
271                 count = length;
272                 needErase = true;
273             }
274
275             if (needErase) {
276                 System.arraycopy(mSpaceLine, 0, line, 0, mSpaceLine.length);
277                 needErase = false;
278             }
279
280             // output the address (currently limited to 4 hex digits)
281             addr = baseAddr;
282             addr &= 0xffff;
283             ch = 3;
284             while (addr != 0) {
285                 line[ch] = mHexDigit[addr & 0x0f];
286                 ch--;
287                 addr >>>= 4;
288             }
289
290             // output hex digits and ASCII chars
291             ch = kHexOffset;
292             for (i = 0; i < count; i++) {
293                 byte val = data[offset + i];
294
295                 line[ch++] = mHexDigit[(val >>> 4) & 0x0f];
296                 line[ch++] = mHexDigit[val & 0x0f];
297                 ch++;
298
299                 if (val >= 0x20 && val < 0x7f)
300                     line[kAscOffset + i] = (char) val;
301                 else
302                     line[kAscOffset + i] = '.';
303             }
304
305             println(level, tag, new String(line));
306
307             // advance to next chunk of data
308             length -= count;
309             offset += count;
310             baseAddr += count;
311         }
312
313     }
314
315     /**
316      * Dump the entire contents of a byte array with DEBUG priority.
317      */
318     static void hexDump(byte[] data) {
319         hexDump("ddms", LogLevel.DEBUG, data, 0, data.length);
320     }
321
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);
327             } else {
328                 printLog(logLevel, tag, message);
329             }
330         }
331     }
332     
333     /**
334      * Prints a log message.
335      * @param logLevel
336      * @param tag
337      * @param message
338      */
339     public static void printLog(LogLevel logLevel, String tag, String message) {
340         long msec;
341         
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);
347     }
348
349 }
350
351