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