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