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