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