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.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.<YOUR_LOG_TAG> <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.<YOUR_LOG_TAG>=<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 * Return the maximum payload the log daemon accepts without truncation. 391 * @return LOGGER_ENTRY_MAX_PAYLOAD. 392 */ logger_entry_max_payload_native()393 private static native int logger_entry_max_payload_native(); 394 395 /** 396 * Helper function for long messages. Uses the LineBreakBufferedWriter to break 397 * up long messages and stacktraces along newlines, but tries to write in large 398 * chunks. This is to avoid truncation. 399 * @hide 400 */ printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg, @Nullable Throwable tr)401 public static int printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg, 402 @Nullable Throwable tr) { 403 ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag); 404 // Acceptable buffer size. Get the native buffer size, subtract two zero terminators, 405 // and the length of the tag. 406 // Note: we implicitly accept possible truncation for Modified-UTF8 differences. It 407 // is too expensive to compute that ahead of time. 408 int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base. 409 - 2 // Two terminators. 410 - (tag != null ? tag.length() : 0) // Tag length. 411 - 32; // Some slack. 412 // At least assume you can print *some* characters (tag is not too large). 413 bufferSize = Math.max(bufferSize, 100); 414 415 LineBreakBufferedWriter lbbw = new LineBreakBufferedWriter(logWriter, bufferSize); 416 417 lbbw.println(msg); 418 419 if (tr != null) { 420 // This is to reduce the amount of log spew that apps do in the non-error 421 // condition of the network being unavailable. 422 Throwable t = tr; 423 while (t != null) { 424 if (t instanceof UnknownHostException) { 425 break; 426 } 427 if (t instanceof DeadSystemException) { 428 lbbw.println("DeadSystemException: The system died; " 429 + "earlier logs will point to the root cause"); 430 break; 431 } 432 t = t.getCause(); 433 } 434 if (t == null) { 435 tr.printStackTrace(lbbw); 436 } 437 } 438 439 lbbw.flush(); 440 441 return logWriter.getWritten(); 442 } 443 444 /** 445 * PreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid 446 * a JNI call during logging. 447 */ 448 static class PreloadHolder { 449 public final static int LOGGER_ENTRY_MAX_PAYLOAD = 450 logger_entry_max_payload_native(); 451 } 452 453 /** 454 * Helper class to write to the logcat. Different from LogWriter, this writes 455 * the whole given buffer and does not break along newlines. 456 */ 457 private static class ImmediateLogWriter extends Writer { 458 459 private int bufID; 460 private int priority; 461 private String tag; 462 463 private int written = 0; 464 465 /** 466 * Create a writer that immediately writes to the log, using the given 467 * parameters. 468 */ ImmediateLogWriter(int bufID, int priority, String tag)469 public ImmediateLogWriter(int bufID, int priority, String tag) { 470 this.bufID = bufID; 471 this.priority = priority; 472 this.tag = tag; 473 } 474 getWritten()475 public int getWritten() { 476 return written; 477 } 478 479 @Override write(char[] cbuf, int off, int len)480 public void write(char[] cbuf, int off, int len) { 481 // Note: using String here has a bit of overhead as a Java object is created, 482 // but using the char[] directly is not easier, as it needs to be translated 483 // to a C char[] for logging. 484 written += println_native(bufID, priority, tag, new String(cbuf, off, len)); 485 } 486 487 @Override flush()488 public void flush() { 489 // Ignored. 490 } 491 492 @Override close()493 public void close() { 494 // Ignored. 495 } 496 } 497 } 498