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