1 /*
2  * Copyright (C) 2006 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 android.util;
18 
19 import android.os.DeadSystemException;
20 
21 import com.android.internal.os.RuntimeInit;
22 import com.android.internal.util.FastPrintWriter;
23 import com.android.internal.util.LineBreakBufferedWriter;
24 
25 import java.io.PrintWriter;
26 import java.io.StringWriter;
27 import java.io.Writer;
28 import java.net.UnknownHostException;
29 
30 /**
31  * API for sending log output.
32  *
33  * <p>Generally, you should use the {@link #v Log.v()}, {@link #d Log.d()},
34  * {@link #i Log.i()}, {@link #w Log.w()}, and {@link #e Log.e()} methods to write logs.
35  * You can then <a href="{@docRoot}studio/debug/am-logcat.html">view the logs in logcat</a>.
36  *
37  * <p>The order in terms of verbosity, from least to most is
38  * ERROR, WARN, INFO, DEBUG, VERBOSE.  Verbose should never be compiled
39  * into an application except during development.  Debug logs are compiled
40  * in but stripped at runtime.  Error, warning and info logs are always kept.
41  *
42  * <p><b>Tip:</b> A good convention is to declare a <code>TAG</code> constant
43  * in your class:
44  *
45  * <pre>private static final String TAG = "MyActivity";</pre>
46  *
47  * and use that in subsequent calls to the log methods.
48  * </p>
49  *
50  * <p><b>Tip:</b> Don't forget that when you make a call like
51  * <pre>Log.v(TAG, "index=" + i);</pre>
52  * that when you're building the string to pass into Log.d, the compiler uses a
53  * StringBuilder and at least three allocations occur: the StringBuilder
54  * itself, the buffer, and the String object.  Realistically, there is also
55  * another buffer allocation and copy, and even more pressure on the gc.
56  * That means that if your log message is filtered out, you might be doing
57  * significant work and incurring significant overhead.
58  */
59 public final class Log {
60 
61     /**
62      * Priority constant for the println method; use Log.v.
63      */
64     public static final int VERBOSE = 2;
65 
66     /**
67      * Priority constant for the println method; use Log.d.
68      */
69     public static final int DEBUG = 3;
70 
71     /**
72      * Priority constant for the println method; use Log.i.
73      */
74     public static final int INFO = 4;
75 
76     /**
77      * Priority constant for the println method; use Log.w.
78      */
79     public static final int WARN = 5;
80 
81     /**
82      * Priority constant for the println method; use Log.e.
83      */
84     public static final int ERROR = 6;
85 
86     /**
87      * Priority constant for the println method.
88      */
89     public static final int ASSERT = 7;
90 
91     /**
92      * Exception class used to capture a stack trace in {@link #wtf}.
93      * @hide
94      */
95     public static class TerribleFailure extends Exception {
TerribleFailure(String msg, Throwable cause)96         TerribleFailure(String msg, Throwable cause) { super(msg, cause); }
97     }
98 
99     /**
100      * Interface to handle terrible failures from {@link #wtf}.
101      *
102      * @hide
103      */
104     public interface TerribleFailureHandler {
onTerribleFailure(String tag, TerribleFailure what, boolean system)105         void onTerribleFailure(String tag, TerribleFailure what, boolean system);
106     }
107 
108     private static TerribleFailureHandler sWtfHandler = new TerribleFailureHandler() {
109             public void onTerribleFailure(String tag, TerribleFailure what, boolean system) {
110                 RuntimeInit.wtf(tag, what, system);
111             }
112         };
113 
Log()114     private Log() {
115     }
116 
117     /**
118      * Send a {@link #VERBOSE} log message.
119      * @param tag Used to identify the source of a log message.  It usually identifies
120      *        the class or activity where the log call occurs.
121      * @param msg The message you would like logged.
122      */
v(String tag, String msg)123     public static int v(String tag, String msg) {
124         return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
125     }
126 
127     /**
128      * Send a {@link #VERBOSE} log message and log the exception.
129      * @param tag Used to identify the source of a log message.  It usually identifies
130      *        the class or activity where the log call occurs.
131      * @param msg The message you would like logged.
132      * @param tr An exception to log
133      */
v(String tag, String msg, Throwable tr)134     public static int v(String tag, String msg, Throwable tr) {
135         return printlns(LOG_ID_MAIN, VERBOSE, tag, msg, tr);
136     }
137 
138     /**
139      * Send a {@link #DEBUG} log message.
140      * @param tag Used to identify the source of a log message.  It usually identifies
141      *        the class or activity where the log call occurs.
142      * @param msg The message you would like logged.
143      */
d(String tag, String msg)144     public static int d(String tag, String msg) {
145         return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
146     }
147 
148     /**
149      * Send a {@link #DEBUG} log message and log the exception.
150      * @param tag Used to identify the source of a log message.  It usually identifies
151      *        the class or activity where the log call occurs.
152      * @param msg The message you would like logged.
153      * @param tr An exception to log
154      */
d(String tag, String msg, Throwable tr)155     public static int d(String tag, String msg, Throwable tr) {
156         return printlns(LOG_ID_MAIN, DEBUG, tag, msg, tr);
157     }
158 
159     /**
160      * Send an {@link #INFO} log message.
161      * @param tag Used to identify the source of a log message.  It usually identifies
162      *        the class or activity where the log call occurs.
163      * @param msg The message you would like logged.
164      */
i(String tag, String msg)165     public static int i(String tag, String msg) {
166         return println_native(LOG_ID_MAIN, INFO, tag, msg);
167     }
168 
169     /**
170      * Send a {@link #INFO} log message and log the exception.
171      * @param tag Used to identify the source of a log message.  It usually identifies
172      *        the class or activity where the log call occurs.
173      * @param msg The message you would like logged.
174      * @param tr An exception to log
175      */
i(String tag, String msg, Throwable tr)176     public static int i(String tag, String msg, Throwable tr) {
177         return printlns(LOG_ID_MAIN, INFO, tag, msg, tr);
178     }
179 
180     /**
181      * Send a {@link #WARN} log message.
182      * @param tag Used to identify the source of a log message.  It usually identifies
183      *        the class or activity where the log call occurs.
184      * @param msg The message you would like logged.
185      */
w(String tag, String msg)186     public static int w(String tag, String msg) {
187         return println_native(LOG_ID_MAIN, WARN, tag, msg);
188     }
189 
190     /**
191      * Send a {@link #WARN} log message and log the exception.
192      * @param tag Used to identify the source of a log message.  It usually identifies
193      *        the class or activity where the log call occurs.
194      * @param msg The message you would like logged.
195      * @param tr An exception to log
196      */
w(String tag, String msg, Throwable tr)197     public static int w(String tag, String msg, Throwable tr) {
198         return printlns(LOG_ID_MAIN, WARN, tag, msg, tr);
199     }
200 
201     /**
202      * Checks to see whether or not a log for the specified tag is loggable at the specified level.
203      *
204      *  The default level of any tag is set to INFO. This means that any level above and including
205      *  INFO will be logged. Before you make any calls to a logging method you should check to see
206      *  if your tag should be logged. You can change the default level by setting a system property:
207      *      'setprop log.tag.&lt;YOUR_LOG_TAG> &lt;LEVEL>'
208      *  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will
209      *  turn off all logging for your tag. You can also create a local.prop file that with the
210      *  following in it:
211      *      'log.tag.&lt;YOUR_LOG_TAG>=&lt;LEVEL>'
212      *  and place that in /data/local.prop.
213      *
214      * @param tag The tag to check.
215      * @param level The level to check.
216      * @return Whether or not that this is allowed to be logged.
217      * @throws IllegalArgumentException is thrown if the tag.length() > 23
218      *         for Nougat (7.0) releases (API <= 23) and prior, there is no
219      *         tag limit of concern after this API level.
220      */
isLoggable(String tag, int level)221     public static native boolean isLoggable(String tag, int level);
222 
223     /*
224      * Send a {@link #WARN} log message and log the exception.
225      * @param tag Used to identify the source of a log message.  It usually identifies
226      *        the class or activity where the log call occurs.
227      * @param tr An exception to log
228      */
w(String tag, Throwable tr)229     public static int w(String tag, Throwable tr) {
230         return printlns(LOG_ID_MAIN, WARN, tag, "", tr);
231     }
232 
233     /**
234      * Send an {@link #ERROR} log message.
235      * @param tag Used to identify the source of a log message.  It usually identifies
236      *        the class or activity where the log call occurs.
237      * @param msg The message you would like logged.
238      */
e(String tag, String msg)239     public static int e(String tag, String msg) {
240         return println_native(LOG_ID_MAIN, ERROR, tag, msg);
241     }
242 
243     /**
244      * Send a {@link #ERROR} log message and log the exception.
245      * @param tag Used to identify the source of a log message.  It usually identifies
246      *        the class or activity where the log call occurs.
247      * @param msg The message you would like logged.
248      * @param tr An exception to log
249      */
e(String tag, String msg, Throwable tr)250     public static int e(String tag, String msg, Throwable tr) {
251         return printlns(LOG_ID_MAIN, ERROR, tag, msg, tr);
252     }
253 
254     /**
255      * What a Terrible Failure: Report a condition that should never happen.
256      * The error will always be logged at level ASSERT with the call stack.
257      * Depending on system configuration, a report may be added to the
258      * {@link android.os.DropBoxManager} and/or the process may be terminated
259      * immediately with an error dialog.
260      * @param tag Used to identify the source of a log message.
261      * @param msg The message you would like logged.
262      */
wtf(String tag, String msg)263     public static int wtf(String tag, String msg) {
264         return wtf(LOG_ID_MAIN, tag, msg, null, false, false);
265     }
266 
267     /**
268      * Like {@link #wtf(String, String)}, but also writes to the log the full
269      * call stack.
270      * @hide
271      */
wtfStack(String tag, String msg)272     public static int wtfStack(String tag, String msg) {
273         return wtf(LOG_ID_MAIN, tag, msg, null, true, false);
274     }
275 
276     /**
277      * What a Terrible Failure: Report an exception that should never happen.
278      * Similar to {@link #wtf(String, String)}, with an exception to log.
279      * @param tag Used to identify the source of a log message.
280      * @param tr An exception to log.
281      */
wtf(String tag, Throwable tr)282     public static int wtf(String tag, Throwable tr) {
283         return wtf(LOG_ID_MAIN, tag, tr.getMessage(), tr, false, false);
284     }
285 
286     /**
287      * What a Terrible Failure: Report an exception that should never happen.
288      * Similar to {@link #wtf(String, Throwable)}, with a message as well.
289      * @param tag Used to identify the source of a log message.
290      * @param msg The message you would like logged.
291      * @param tr An exception to log.  May be null.
292      */
wtf(String tag, String msg, Throwable tr)293     public static int wtf(String tag, String msg, Throwable tr) {
294         return wtf(LOG_ID_MAIN, tag, msg, tr, false, false);
295     }
296 
wtf(int logId, String tag, String msg, Throwable tr, boolean localStack, boolean system)297     static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack,
298             boolean system) {
299         TerribleFailure what = new TerribleFailure(msg, tr);
300         // Only mark this as ERROR, do not use ASSERT since that should be
301         // reserved for cases where the system is guaranteed to abort.
302         // The onTerribleFailure call does not always cause a crash.
303         int bytes = printlns(logId, ERROR, tag, msg, localStack ? what : tr);
304         sWtfHandler.onTerribleFailure(tag, what, system);
305         return bytes;
306     }
307 
wtfQuiet(int logId, String tag, String msg, boolean system)308     static void wtfQuiet(int logId, String tag, String msg, boolean system) {
309         TerribleFailure what = new TerribleFailure(msg, null);
310         sWtfHandler.onTerribleFailure(tag, what, system);
311     }
312 
313     /**
314      * Sets the terrible failure handler, for testing.
315      *
316      * @return the old handler
317      *
318      * @hide
319      */
setWtfHandler(TerribleFailureHandler handler)320     public static TerribleFailureHandler setWtfHandler(TerribleFailureHandler handler) {
321         if (handler == null) {
322             throw new NullPointerException("handler == null");
323         }
324         TerribleFailureHandler oldHandler = sWtfHandler;
325         sWtfHandler = handler;
326         return oldHandler;
327     }
328 
329     /**
330      * Handy function to get a loggable stack trace from a Throwable
331      * @param tr An exception to log
332      */
getStackTraceString(Throwable tr)333     public static String getStackTraceString(Throwable tr) {
334         if (tr == null) {
335             return "";
336         }
337 
338         // This is to reduce the amount of log spew that apps do in the non-error
339         // condition of the network being unavailable.
340         Throwable t = tr;
341         while (t != null) {
342             if (t instanceof UnknownHostException) {
343                 return "";
344             }
345             t = t.getCause();
346         }
347 
348         StringWriter sw = new StringWriter();
349         PrintWriter pw = new FastPrintWriter(sw, false, 256);
350         tr.printStackTrace(pw);
351         pw.flush();
352         return sw.toString();
353     }
354 
355     /**
356      * Low-level logging call.
357      * @param priority The priority/type of this log message
358      * @param tag Used to identify the source of a log message.  It usually identifies
359      *        the class or activity where the log call occurs.
360      * @param msg The message you would like logged.
361      * @return The number of bytes written.
362      */
println(int priority, String tag, String msg)363     public static int println(int priority, String tag, String msg) {
364         return println_native(LOG_ID_MAIN, priority, tag, msg);
365     }
366 
367     /** @hide */ public static final int LOG_ID_MAIN = 0;
368     /** @hide */ public static final int LOG_ID_RADIO = 1;
369     /** @hide */ public static final int LOG_ID_EVENTS = 2;
370     /** @hide */ public static final int LOG_ID_SYSTEM = 3;
371     /** @hide */ public static final int LOG_ID_CRASH = 4;
372 
println_native(int bufID, int priority, String tag, String msg)373     /** @hide */ public static native int println_native(int bufID,
374             int priority, String tag, String msg);
375 
376     /**
377      * Return the maximum payload the log daemon accepts without truncation.
378      * @return LOGGER_ENTRY_MAX_PAYLOAD.
379      */
logger_entry_max_payload_native()380     private static native int logger_entry_max_payload_native();
381 
382     /**
383      * Helper function for long messages. Uses the LineBreakBufferedWriter to break
384      * up long messages and stacktraces along newlines, but tries to write in large
385      * chunks. This is to avoid truncation.
386      * @hide
387      */
printlns(int bufID, int priority, String tag, String msg, Throwable tr)388     public static int printlns(int bufID, int priority, String tag, String msg,
389             Throwable tr) {
390         ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag);
391         // Acceptable buffer size. Get the native buffer size, subtract two zero terminators,
392         // and the length of the tag.
393         // Note: we implicitly accept possible truncation for Modified-UTF8 differences. It
394         //       is too expensive to compute that ahead of time.
395         int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD    // Base.
396                 - 2                                                // Two terminators.
397                 - (tag != null ? tag.length() : 0)                 // Tag length.
398                 - 32;                                              // Some slack.
399         // At least assume you can print *some* characters (tag is not too large).
400         bufferSize = Math.max(bufferSize, 100);
401 
402         LineBreakBufferedWriter lbbw = new LineBreakBufferedWriter(logWriter, bufferSize);
403 
404         lbbw.println(msg);
405 
406         if (tr != null) {
407             // This is to reduce the amount of log spew that apps do in the non-error
408             // condition of the network being unavailable.
409             Throwable t = tr;
410             while (t != null) {
411                 if (t instanceof UnknownHostException) {
412                     break;
413                 }
414                 if (t instanceof DeadSystemException) {
415                     lbbw.println("DeadSystemException: The system died; "
416                             + "earlier logs will point to the root cause");
417                     break;
418                 }
419                 t = t.getCause();
420             }
421             if (t == null) {
422                 tr.printStackTrace(lbbw);
423             }
424         }
425 
426         lbbw.flush();
427 
428         return logWriter.getWritten();
429     }
430 
431     /**
432      * PreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
433      * a JNI call during logging.
434      */
435     static class PreloadHolder {
436         public final static int LOGGER_ENTRY_MAX_PAYLOAD =
437                 logger_entry_max_payload_native();
438     }
439 
440     /**
441      * Helper class to write to the logcat. Different from LogWriter, this writes
442      * the whole given buffer and does not break along newlines.
443      */
444     private static class ImmediateLogWriter extends Writer {
445 
446         private int bufID;
447         private int priority;
448         private String tag;
449 
450         private int written = 0;
451 
452         /**
453          * Create a writer that immediately writes to the log, using the given
454          * parameters.
455          */
ImmediateLogWriter(int bufID, int priority, String tag)456         public ImmediateLogWriter(int bufID, int priority, String tag) {
457             this.bufID = bufID;
458             this.priority = priority;
459             this.tag = tag;
460         }
461 
getWritten()462         public int getWritten() {
463             return written;
464         }
465 
466         @Override
write(char[] cbuf, int off, int len)467         public void write(char[] cbuf, int off, int len) {
468             // Note: using String here has a bit of overhead as a Java object is created,
469             //       but using the char[] directly is not easier, as it needs to be translated
470             //       to a C char[] for logging.
471             written += println_native(bufID, priority, tag, new String(cbuf, off, len));
472         }
473 
474         @Override
flush()475         public void flush() {
476             // Ignored.
477         }
478 
479         @Override
close()480         public void close() {
481             // Ignored.
482         }
483     }
484 }
485