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.RavenwoodNativeSubstitutionClass(
79 //        "com.android.platform.test.ravenwood.nativesubstitution.Log_host")
80 public final class Log {
81     /** @hide */
82     @IntDef({ASSERT, ERROR, WARN, INFO, DEBUG, VERBOSE})
83     @Retention(RetentionPolicy.SOURCE)
84     public @interface Level {}
85 
86     /**
87      * Priority constant for the println method; use Log.v.
88      */
89     public static final int VERBOSE = 2;
90 
91     /**
92      * Priority constant for the println method; use Log.d.
93      */
94     public static final int DEBUG = 3;
95 
96     /**
97      * Priority constant for the println method; use Log.i.
98      */
99     public static final int INFO = 4;
100 
101     /**
102      * Priority constant for the println method; use Log.w.
103      */
104     public static final int WARN = 5;
105 
106     /**
107      * Priority constant for the println method; use Log.e.
108      */
109     public static final int ERROR = 6;
110 
111     /**
112      * Priority constant for the println method.
113      */
114     public static final int ASSERT = 7;
115 
116     /**
117      * Exception class used to capture a stack trace in {@link #wtf}.
118      * @hide
119      */
120     public static class TerribleFailure extends Exception {
TerribleFailure(String msg, Throwable cause)121         TerribleFailure(String msg, Throwable cause) { super(msg, cause); }
122     }
123 
124     /**
125      * Interface to handle terrible failures from {@link #wtf}.
126      *
127      * @hide
128      */
129     public interface TerribleFailureHandler {
onTerribleFailure(String tag, TerribleFailure what, boolean system)130         void onTerribleFailure(String tag, TerribleFailure what, boolean system);
131     }
132 
133     private static TerribleFailureHandler sWtfHandler = new TerribleFailureHandler() {
134             public void onTerribleFailure(String tag, TerribleFailure what, boolean system) {
135                 RuntimeInit.wtf(tag, what, system);
136             }
137         };
138 
Log()139     private Log() {
140     }
141 
142     /**
143      * Send a {@link #VERBOSE} log message.
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      * @return A positive value if the message was loggable (see {@link #isLoggable}).
148      */
v(@ullable String tag, @NonNull String msg)149     public static int v(@Nullable String tag, @NonNull String msg) {
150         return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
151     }
152 
153     /**
154      * Send a {@link #VERBOSE} log message and log the exception.
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      * @param tr An exception to log.
159      * @return A positive value if the message was loggable (see {@link #isLoggable}).
160      */
v(@ullable String tag, @Nullable String msg, @Nullable Throwable tr)161     public static int v(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
162         return printlns(LOG_ID_MAIN, VERBOSE, tag, msg, tr);
163     }
164 
165     /**
166      * Send a {@link #DEBUG} log message.
167      * @param tag Used to identify the source of a log message.  It usually identifies
168      *        the class or activity where the log call occurs.
169      * @param msg The message you would like logged.
170      * @return A positive value if the message was loggable (see {@link #isLoggable}).
171      */
d(@ullable String tag, @NonNull String msg)172     public static int d(@Nullable String tag, @NonNull String msg) {
173         return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
174     }
175 
176     /**
177      * Send a {@link #DEBUG} log message and log the exception.
178      * @param tag Used to identify the source of a log message.  It usually identifies
179      *        the class or activity where the log call occurs.
180      * @param msg The message you would like logged.
181      * @param tr An exception to log.
182      * @return A positive value if the message was loggable (see {@link #isLoggable}).
183      */
d(@ullable String tag, @Nullable String msg, @Nullable Throwable tr)184     public static int d(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
185         return printlns(LOG_ID_MAIN, DEBUG, tag, msg, tr);
186     }
187 
188     /**
189      * Send an {@link #INFO} log message.
190      * @param tag Used to identify the source of a log message.  It usually identifies
191      *        the class or activity where the log call occurs.
192      * @param msg The message you would like logged.
193      * @return A positive value if the message was loggable (see {@link #isLoggable}).
194      */
i(@ullable String tag, @NonNull String msg)195     public static int i(@Nullable String tag, @NonNull String msg) {
196         return println_native(LOG_ID_MAIN, INFO, tag, msg);
197     }
198 
199     /**
200      * Send a {@link #INFO} log message and log the exception.
201      * @param tag Used to identify the source of a log message.  It usually identifies
202      *        the class or activity where the log call occurs.
203      * @param msg The message you would like logged.
204      * @param tr An exception to log.
205      */
i(@ullable String tag, @Nullable String msg, @Nullable Throwable tr)206     public static int i(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
207         return printlns(LOG_ID_MAIN, INFO, tag, msg, tr);
208     }
209 
210     /**
211      * Send a {@link #WARN} log message.
212      * @param tag Used to identify the source of a log message.  It usually identifies
213      *        the class or activity where the log call occurs.
214      * @param msg The message you would like logged.
215      * @return A positive value if the message was loggable (see {@link #isLoggable}).
216      */
w(@ullable String tag, @NonNull String msg)217     public static int w(@Nullable String tag, @NonNull String msg) {
218         return println_native(LOG_ID_MAIN, WARN, tag, msg);
219     }
220 
221     /**
222      * Send a {@link #WARN} log message and log the exception.
223      * @param tag Used to identify the source of a log message.  It usually identifies
224      *        the class or activity where the log call occurs.
225      * @param msg The message you would like logged.
226      * @param tr An exception to log.
227      * @return A positive value if the message was loggable (see {@link #isLoggable}).
228      */
w(@ullable String tag, @Nullable String msg, @Nullable Throwable tr)229     public static int w(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
230         return printlns(LOG_ID_MAIN, WARN, tag, msg, tr);
231     }
232 
233     /**
234      * Checks to see whether or not a log for the specified tag is loggable at the specified level.
235      *
236      *  The default level of any tag is set to INFO. This means that any level above and including
237      *  INFO will be logged. Before you make any calls to a logging method you should check to see
238      *  if your tag should be logged. You can change the default level by setting a system property:
239      *      'setprop log.tag.&lt;YOUR_LOG_TAG> &lt;LEVEL>'
240      *  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, or ASSERT.
241      *  You can also create a local.prop file that with the following in it:
242      *      'log.tag.&lt;YOUR_LOG_TAG>=&lt;LEVEL>'
243      *  and place that in /data/local.prop.
244      *
245      * @param tag The tag to check.
246      * @param level The level to check.
247      * @return Whether or not that this is allowed to be logged.
248      * @throws IllegalArgumentException is thrown if the tag.length() > 23
249      *         for Nougat (7.0) and prior releases (API <= 25), there is no
250      *         tag limit of concern after this API level.
251      */
252     @FastNative
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
println_native(int bufID, int priority, String tag, String msg)428     public static native int println_native(int bufID, int priority, String tag, String msg);
429 
430     /**
431      * Send a log message to the "radio" log buffer, which can be dumped with
432      * {@code adb logcat -b radio}.
433      *
434      * <p>Only the telephony mainline module should use it.
435      *
436      * <p>Note ART will protect {@code MODULE_LIBRARIES} system APIs from regular app code.
437      *
438      * @param priority Log priority.
439      * @param tag Used to identify the source of a log message.  It usually identifies
440      *        the class or activity where the log call occurs.
441      * @param message The message you would like logged.
442      * @return A positive value if the message was loggable (see {@link #isLoggable}).
443      * @hide
444      */
445     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
logToRadioBuffer(@evel int priority, @Nullable String tag, @Nullable String message)446     public static int logToRadioBuffer(@Level int priority, @Nullable String tag,
447             @Nullable String message) {
448         return println_native(LOG_ID_RADIO, priority, tag, message);
449     }
450 
451     /**
452      * Return the maximum payload the log daemon accepts without truncation.
453      * @return LOGGER_ENTRY_MAX_PAYLOAD.
454      */
logger_entry_max_payload_native()455     private static native int logger_entry_max_payload_native();
456 
457     /**
458      * Helper function for long messages. Uses the LineBreakBufferedWriter to break
459      * up long messages and stacktraces along newlines, but tries to write in large
460      * chunks. This is to avoid truncation.
461      * @return A positive value if the message was loggable (see {@link #isLoggable}).
462      * @hide
463      */
printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg, @Nullable Throwable tr)464     public static int printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg,
465             @Nullable Throwable tr) {
466         ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag);
467         // Acceptable buffer size. Get the native buffer size, subtract two zero terminators,
468         // and the length of the tag.
469         // Note: we implicitly accept possible truncation for Modified-UTF8 differences. It
470         //       is too expensive to compute that ahead of time.
471         int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD    // Base.
472                 - 2                                                // Two terminators.
473                 - (tag != null ? tag.length() : 0)                 // Tag length.
474                 - 32;                                              // Some slack.
475         // At least assume you can print *some* characters (tag is not too large).
476         bufferSize = Math.max(bufferSize, 100);
477 
478         LineBreakBufferedWriter lbbw = new LineBreakBufferedWriter(logWriter, bufferSize);
479 
480         lbbw.println(msg);
481 
482         if (tr != null) {
483             // This is to reduce the amount of log spew that apps do in the non-error
484             // condition of the network being unavailable.
485             Throwable t = tr;
486             while (t != null) {
487                 if (t instanceof UnknownHostException) {
488                     break;
489                 }
490                 if (t instanceof DeadSystemException) {
491                     lbbw.println("DeadSystemException: The system died; "
492                             + "earlier logs will point to the root cause");
493                     break;
494                 }
495                 t = t.getCause();
496             }
497             if (t == null) {
498                 tr.printStackTrace(lbbw);
499             }
500         }
501 
502         lbbw.flush();
503 
504         return logWriter.getWritten();
505     }
506 
507     /**
508      * PreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
509      * a JNI call during logging.
510      */
511     static class PreloadHolder {
512         public final static int LOGGER_ENTRY_MAX_PAYLOAD =
513                 logger_entry_max_payload_native();
514     }
515 
516     /**
517      * Helper class to write to the logcat. Different from LogWriter, this writes
518      * the whole given buffer and does not break along newlines.
519      */
520     private static class ImmediateLogWriter extends Writer {
521 
522         private int bufID;
523         private int priority;
524         private String tag;
525 
526         private int written = 0;
527 
528         /**
529          * Create a writer that immediately writes to the log, using the given
530          * parameters.
531          */
ImmediateLogWriter(int bufID, int priority, String tag)532         public ImmediateLogWriter(int bufID, int priority, String tag) {
533             this.bufID = bufID;
534             this.priority = priority;
535             this.tag = tag;
536         }
537 
getWritten()538         public int getWritten() {
539             return written;
540         }
541 
542         @Override
write(char[] cbuf, int off, int len)543         public void write(char[] cbuf, int off, int len) {
544             // Note: using String here has a bit of overhead as a Java object is created,
545             //       but using the char[] directly is not easier, as it needs to be translated
546             //       to a C char[] for logging.
547             written += println_native(bufID, priority, tag, new String(cbuf, off, len));
548         }
549 
550         @Override
flush()551         public void flush() {
552             // Ignored.
553         }
554 
555         @Override
close()556         public void close() {
557             // Ignored.
558         }
559     }
560 }
561