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