Home | History | Annotate | Download | only in telecom
      1 /*
      2  * Copyright 2014, 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 com.android.server.telecom;
     18 
     19 import android.net.Uri;
     20 import android.telecom.PhoneAccount;
     21 import android.telephony.PhoneNumberUtils;
     22 
     23 import java.security.MessageDigest;
     24 import java.security.NoSuchAlgorithmException;
     25 import java.util.IllegalFormatException;
     26 import java.util.Locale;
     27 
     28 /**
     29  * Manages logging for the entire module.
     30  */
     31 public class Log {
     32 
     33     // Generic tag for all In Call logging
     34     private static final String TAG = "Telecom";
     35 
     36     public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
     37     public static final boolean SYSTRACE_DEBUG = false; /* STOP SHIP if true */
     38     public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
     39     public static final boolean INFO = isLoggable(android.util.Log.INFO);
     40     public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
     41     public static final boolean WARN = isLoggable(android.util.Log.WARN);
     42     public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
     43 
     44     private Log() {}
     45 
     46     public static boolean isLoggable(int level) {
     47         return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
     48     }
     49 
     50     public static void d(String prefix, String format, Object... args) {
     51         if (DEBUG) {
     52             android.util.Slog.d(TAG, buildMessage(prefix, format, args));
     53         }
     54     }
     55 
     56     public static void d(Object objectPrefix, String format, Object... args) {
     57         if (DEBUG) {
     58             android.util.Slog.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
     59         }
     60     }
     61 
     62     public static void i(String prefix, String format, Object... args) {
     63         if (INFO) {
     64             android.util.Slog.i(TAG, buildMessage(prefix, format, args));
     65         }
     66     }
     67 
     68     public static void i(Object objectPrefix, String format, Object... args) {
     69         if (INFO) {
     70             android.util.Slog.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
     71         }
     72     }
     73 
     74     public static void v(String prefix, String format, Object... args) {
     75         if (VERBOSE) {
     76             android.util.Slog.v(TAG, buildMessage(prefix, format, args));
     77         }
     78     }
     79 
     80     public static void v(Object objectPrefix, String format, Object... args) {
     81         if (VERBOSE) {
     82             android.util.Slog.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
     83         }
     84     }
     85 
     86     public static void w(String prefix, String format, Object... args) {
     87         if (WARN) {
     88             android.util.Slog.w(TAG, buildMessage(prefix, format, args));
     89         }
     90     }
     91 
     92     public static void w(Object objectPrefix, String format, Object... args) {
     93         if (WARN) {
     94             android.util.Slog.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
     95         }
     96     }
     97 
     98     public static void e(String prefix, Throwable tr, String format, Object... args) {
     99         if (ERROR) {
    100             android.util.Slog.e(TAG, buildMessage(prefix, format, args), tr);
    101         }
    102     }
    103 
    104     public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
    105         if (ERROR) {
    106             android.util.Slog.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
    107                     tr);
    108         }
    109     }
    110 
    111     public static void wtf(String prefix, Throwable tr, String format, Object... args) {
    112         android.util.Slog.wtf(TAG, buildMessage(prefix, format, args), tr);
    113     }
    114 
    115     public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
    116         android.util.Slog.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
    117                 tr);
    118     }
    119 
    120     public static void wtf(String prefix, String format, Object... args) {
    121         String msg = buildMessage(prefix, format, args);
    122         android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
    123     }
    124 
    125     public static void wtf(Object objectPrefix, String format, Object... args) {
    126         String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
    127         android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
    128     }
    129 
    130     public static String piiHandle(Object pii) {
    131         if (pii == null || VERBOSE) {
    132             return String.valueOf(pii);
    133         }
    134 
    135         if (pii instanceof Uri) {
    136             Uri uri = (Uri) pii;
    137 
    138             // All Uri's which are not "tel" go through normal pii() method.
    139             if (!PhoneAccount.SCHEME_TEL.equals(uri.getScheme())) {
    140                 return pii(pii);
    141             } else {
    142                 pii = uri.getSchemeSpecificPart();
    143             }
    144         }
    145 
    146         String originalString = String.valueOf(pii);
    147         StringBuilder stringBuilder = new StringBuilder(originalString.length());
    148         for (char c : originalString.toCharArray()) {
    149             if (PhoneNumberUtils.isDialable(c)) {
    150                 stringBuilder.append('*');
    151             } else {
    152                 stringBuilder.append(c);
    153             }
    154         }
    155         return stringBuilder.toString();
    156     }
    157 
    158     /**
    159      * Redact personally identifiable information for production users.
    160      * If we are running in verbose mode, return the original string, otherwise
    161      * return a SHA-1 hash of the input string.
    162      */
    163     public static String pii(Object pii) {
    164         if (pii == null || VERBOSE) {
    165             return String.valueOf(pii);
    166         }
    167         return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
    168     }
    169 
    170     private static String secureHash(byte[] input) {
    171         MessageDigest messageDigest;
    172         try {
    173             messageDigest = MessageDigest.getInstance("SHA-1");
    174         } catch (NoSuchAlgorithmException e) {
    175             return null;
    176         }
    177         messageDigest.update(input);
    178         byte[] result = messageDigest.digest();
    179         return encodeHex(result);
    180     }
    181 
    182     private static String encodeHex(byte[] bytes) {
    183         StringBuffer hex = new StringBuffer(bytes.length * 2);
    184 
    185         for (int i = 0; i < bytes.length; i++) {
    186             int byteIntValue = bytes[i] & 0xff;
    187             if (byteIntValue < 0x10) {
    188                 hex.append("0");
    189             }
    190             hex.append(Integer.toString(byteIntValue, 16));
    191         }
    192 
    193         return hex.toString();
    194     }
    195 
    196     private static String getPrefixFromObject(Object obj) {
    197         return obj == null ? "<null>" : obj.getClass().getSimpleName();
    198     }
    199 
    200     private static String buildMessage(String prefix, String format, Object... args) {
    201         String msg;
    202         try {
    203             msg = (args == null || args.length == 0) ? format
    204                     : String.format(Locale.US, format, args);
    205         } catch (IllegalFormatException ife) {
    206             e("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
    207                     args.length);
    208             msg = format + " (An error occurred while formatting the message.)";
    209         }
    210         return String.format(Locale.US, "%s: %s", prefix, msg);
    211     }
    212 }
    213