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