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