1/** 2 * Copyright (c) 2011, Google Inc. 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 */ 16package com.android.mail.utils; 17 18import android.net.Uri; 19import android.text.TextUtils; 20import android.util.Log; 21 22import com.google.common.annotations.VisibleForTesting; 23 24import java.util.List; 25import java.util.regex.Pattern; 26 27public class LogUtils { 28 29 public static final String TAG = LogTag.getLogTag(); 30 31 // "GMT" + "+" or "-" + 4 digits 32 private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE = 33 Pattern.compile("GMT([-+]\\d{4})$"); 34 35 private static final String ACCOUNT_PREFIX = "account:"; 36 37 /** 38 * Priority constant for the println method; use LogUtils.v. 39 */ 40 public static final int VERBOSE = Log.VERBOSE; 41 42 /** 43 * Priority constant for the println method; use LogUtils.d. 44 */ 45 public static final int DEBUG = Log.DEBUG; 46 47 /** 48 * Priority constant for the println method; use LogUtils.i. 49 */ 50 public static final int INFO = Log.INFO; 51 52 /** 53 * Priority constant for the println method; use LogUtils.w. 54 */ 55 public static final int WARN = Log.WARN; 56 57 /** 58 * Priority constant for the println method; use LogUtils.e. 59 */ 60 public static final int ERROR = Log.ERROR; 61 62 /** 63 * Used to enable/disable logging that we don't want included in 64 * production releases. This should be set to DEBUG for production releases, and VERBOSE for 65 * internal builds. 66 */ 67 private static final int MAX_ENABLED_LOG_LEVEL = DEBUG; 68 69 private static Boolean sDebugLoggingEnabledForTests = null; 70 71 /** 72 * Enable debug logging for unit tests. 73 */ 74 @VisibleForTesting 75 public static void setDebugLoggingEnabledForTests(boolean enabled) { 76 setDebugLoggingEnabledForTestsInternal(enabled); 77 } 78 79 protected static void setDebugLoggingEnabledForTestsInternal(boolean enabled) { 80 sDebugLoggingEnabledForTests = Boolean.valueOf(enabled); 81 } 82 83 /** 84 * Returns true if the build configuration prevents debug logging. 85 */ 86 @VisibleForTesting 87 public static boolean buildPreventsDebugLogging() { 88 return MAX_ENABLED_LOG_LEVEL > VERBOSE; 89 } 90 91 /** 92 * Returns a boolean indicating whether debug logging is enabled. 93 */ 94 protected static boolean isDebugLoggingEnabled(String tag) { 95 if (buildPreventsDebugLogging()) { 96 return false; 97 } 98 if (sDebugLoggingEnabledForTests != null) { 99 return sDebugLoggingEnabledForTests.booleanValue(); 100 } 101 return Log.isLoggable(tag, Log.DEBUG) || Log.isLoggable(TAG, Log.DEBUG); 102 } 103 104 /** 105 * Returns a String for the specified content provider uri. This will do 106 * sanitation of the uri to remove PII if debug logging is not enabled. 107 */ 108 public static String contentUriToString(final Uri uri) { 109 return contentUriToString(TAG, uri); 110 } 111 112 /** 113 * Returns a String for the specified content provider uri. This will do 114 * sanitation of the uri to remove PII if debug logging is not enabled. 115 */ 116 public static String contentUriToString(String tag, Uri uri) { 117 if (isDebugLoggingEnabled(tag)) { 118 // Debug logging has been enabled, so log the uri as is 119 return uri.toString(); 120 } else { 121 // Debug logging is not enabled, we want to remove the email address from the uri. 122 List<String> pathSegments = uri.getPathSegments(); 123 124 Uri.Builder builder = new Uri.Builder() 125 .scheme(uri.getScheme()) 126 .authority(uri.getAuthority()) 127 .query(uri.getQuery()) 128 .fragment(uri.getFragment()); 129 130 // This assumes that the first path segment is the account 131 final String account = pathSegments.get(0); 132 133 builder = builder.appendPath(sanitizeAccountName(account)); 134 for (int i = 1; i < pathSegments.size(); i++) { 135 builder.appendPath(pathSegments.get(i)); 136 } 137 return builder.toString(); 138 } 139 } 140 141 /** 142 * Sanitizes an account name. If debug logging is not enabled, a sanitized name 143 * is returned. 144 */ 145 public static String sanitizeAccountName(String accountName) { 146 if (TextUtils.isEmpty(accountName)) { 147 return ""; 148 } 149 150 return ACCOUNT_PREFIX + sanitizeName(TAG, accountName); 151 } 152 153 public static String sanitizeName(final String tag, final String name) { 154 if (TextUtils.isEmpty(name)) { 155 return ""; 156 } 157 158 if (isDebugLoggingEnabled(tag)) { 159 return name; 160 } 161 162 return String.valueOf(name.hashCode()); 163 } 164 165 /** 166 * Checks to see whether or not a log for the specified tag is loggable at the specified level. 167 */ 168 public static boolean isLoggable(String tag, int level) { 169 if (MAX_ENABLED_LOG_LEVEL > level) { 170 return false; 171 } 172 return Log.isLoggable(tag, level) || Log.isLoggable(TAG, level); 173 } 174 175 /** 176 * Send a {@link #VERBOSE} log message. 177 * @param tag Used to identify the source of a log message. It usually identifies 178 * the class or activity where the log call occurs. 179 * @param format the format string (see {@link java.util.Formatter#format}) 180 * @param args 181 * the list of arguments passed to the formatter. If there are 182 * more arguments than required by {@code format}, 183 * additional arguments are ignored. 184 */ 185 public static int v(String tag, String format, Object... args) { 186 if (isLoggable(tag, VERBOSE)) { 187 return Log.v(tag, String.format(format, args)); 188 } 189 return 0; 190 } 191 192 /** 193 * Send a {@link #VERBOSE} log message. 194 * @param tag Used to identify the source of a log message. It usually identifies 195 * the class or activity where the log call occurs. 196 * @param tr An exception to log 197 * @param format the format string (see {@link java.util.Formatter#format}) 198 * @param args 199 * the list of arguments passed to the formatter. If there are 200 * more arguments than required by {@code format}, 201 * additional arguments are ignored. 202 */ 203 public static int v(String tag, Throwable tr, String format, Object... args) { 204 if (isLoggable(tag, VERBOSE)) { 205 return Log.v(tag, String.format(format, args), tr); 206 } 207 return 0; 208 } 209 210 /** 211 * Send a {@link #DEBUG} log message. 212 * @param tag Used to identify the source of a log message. It usually identifies 213 * the class or activity where the log call occurs. 214 * @param format the format string (see {@link java.util.Formatter#format}) 215 * @param args 216 * the list of arguments passed to the formatter. If there are 217 * more arguments than required by {@code format}, 218 * additional arguments are ignored. 219 */ 220 public static int d(String tag, String format, Object... args) { 221 if (isLoggable(tag, DEBUG)) { 222 return Log.d(tag, String.format(format, args)); 223 } 224 return 0; 225 } 226 227 /** 228 * Send a {@link #DEBUG} 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 tr An exception to log 232 * @param format the format string (see {@link java.util.Formatter#format}) 233 * @param args 234 * the list of arguments passed to the formatter. If there are 235 * more arguments than required by {@code format}, 236 * additional arguments are ignored. 237 */ 238 public static int d(String tag, Throwable tr, String format, Object... args) { 239 if (isLoggable(tag, DEBUG)) { 240 return Log.d(tag, String.format(format, args), tr); 241 } 242 return 0; 243 } 244 245 /** 246 * Send a {@link #INFO} log message. 247 * @param tag Used to identify the source of a log message. It usually identifies 248 * the class or activity where the log call occurs. 249 * @param format the format string (see {@link java.util.Formatter#format}) 250 * @param args 251 * the list of arguments passed to the formatter. If there are 252 * more arguments than required by {@code format}, 253 * additional arguments are ignored. 254 */ 255 public static int i(String tag, String format, Object... args) { 256 if (isLoggable(tag, INFO)) { 257 return Log.i(tag, String.format(format, args)); 258 } 259 return 0; 260 } 261 262 /** 263 * Send a {@link #INFO} log message. 264 * @param tag Used to identify the source of a log message. It usually identifies 265 * the class or activity where the log call occurs. 266 * @param tr An exception to log 267 * @param format the format string (see {@link java.util.Formatter#format}) 268 * @param args 269 * the list of arguments passed to the formatter. If there are 270 * more arguments than required by {@code format}, 271 * additional arguments are ignored. 272 */ 273 public static int i(String tag, Throwable tr, String format, Object... args) { 274 if (isLoggable(tag, INFO)) { 275 return Log.i(tag, String.format(format, args), tr); 276 } 277 return 0; 278 } 279 280 /** 281 * Send a {@link #WARN} log message. 282 * @param tag Used to identify the source of a log message. It usually identifies 283 * the class or activity where the log call occurs. 284 * @param format the format string (see {@link java.util.Formatter#format}) 285 * @param args 286 * the list of arguments passed to the formatter. If there are 287 * more arguments than required by {@code format}, 288 * additional arguments are ignored. 289 */ 290 public static int w(String tag, String format, Object... args) { 291 if (isLoggable(tag, WARN)) { 292 return Log.w(tag, String.format(format, args)); 293 } 294 return 0; 295 } 296 297 /** 298 * Send a {@link #WARN} log message. 299 * @param tag Used to identify the source of a log message. It usually identifies 300 * the class or activity where the log call occurs. 301 * @param tr An exception to log 302 * @param format the format string (see {@link java.util.Formatter#format}) 303 * @param args 304 * the list of arguments passed to the formatter. If there are 305 * more arguments than required by {@code format}, 306 * additional arguments are ignored. 307 */ 308 public static int w(String tag, Throwable tr, String format, Object... args) { 309 if (isLoggable(tag, WARN)) { 310 return Log.w(tag, String.format(format, args), tr); 311 } 312 return 0; 313 } 314 315 /** 316 * Send a {@link #ERROR} log message. 317 * @param tag Used to identify the source of a log message. It usually identifies 318 * the class or activity where the log call occurs. 319 * @param format the format string (see {@link java.util.Formatter#format}) 320 * @param args 321 * the list of arguments passed to the formatter. If there are 322 * more arguments than required by {@code format}, 323 * additional arguments are ignored. 324 */ 325 public static int e(String tag, String format, Object... args) { 326 if (isLoggable(tag, ERROR)) { 327 return Log.e(tag, String.format(format, args)); 328 } 329 return 0; 330 } 331 332 /** 333 * Send a {@link #ERROR} log message. 334 * @param tag Used to identify the source of a log message. It usually identifies 335 * the class or activity where the log call occurs. 336 * @param tr An exception to log 337 * @param format the format string (see {@link java.util.Formatter#format}) 338 * @param args 339 * the list of arguments passed to the formatter. If there are 340 * more arguments than required by {@code format}, 341 * additional arguments are ignored. 342 */ 343 public static int e(String tag, Throwable tr, String format, Object... args) { 344 if (isLoggable(tag, ERROR)) { 345 return Log.e(tag, String.format(format, args), tr); 346 } 347 return 0; 348 } 349 350 /** 351 * What a Terrible Failure: Report a condition that should never happen. 352 * The error will always be logged at level ASSERT with the call stack. 353 * Depending on system configuration, a report may be added to the 354 * {@link android.os.DropBoxManager} and/or the process may be terminated 355 * immediately with an error dialog. 356 * @param tag Used to identify the source of a log message. It usually identifies 357 * the class or activity where the log call occurs. 358 * @param format the format string (see {@link java.util.Formatter#format}) 359 * @param args 360 * the list of arguments passed to the formatter. If there are 361 * more arguments than required by {@code format}, 362 * additional arguments are ignored. 363 */ 364 public static int wtf(String tag, String format, Object... args) { 365 return Log.wtf(tag, String.format(format, args), new Error()); 366 } 367 368 /** 369 * What a Terrible Failure: Report a condition that should never happen. 370 * The error will always be logged at level ASSERT with the call stack. 371 * Depending on system configuration, a report may be added to the 372 * {@link android.os.DropBoxManager} and/or the process may be terminated 373 * immediately with an error dialog. 374 * @param tag Used to identify the source of a log message. It usually identifies 375 * the class or activity where the log call occurs. 376 * @param tr An exception to log 377 * @param format the format string (see {@link java.util.Formatter#format}) 378 * @param args 379 * the list of arguments passed to the formatter. If there are 380 * more arguments than required by {@code format}, 381 * additional arguments are ignored. 382 */ 383 public static int wtf(String tag, Throwable tr, String format, Object... args) { 384 return Log.wtf(tag, String.format(format, args), tr); 385 } 386 387 388 /** 389 * Try to make a date MIME(RFC 2822/5322)-compliant. 390 * 391 * It fixes: 392 * - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700" 393 * (4 digit zone value can't be preceded by "GMT") 394 * We got a report saying eBay sends a date in this format 395 */ 396 public static String cleanUpMimeDate(String date) { 397 if (TextUtils.isEmpty(date)) { 398 return date; 399 } 400 date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1"); 401 return date; 402 } 403 404 405 public static String byteToHex(int b) { 406 return byteToHex(new StringBuilder(), b).toString(); 407 } 408 409 public static StringBuilder byteToHex(StringBuilder sb, int b) { 410 b &= 0xFF; 411 sb.append("0123456789ABCDEF".charAt(b >> 4)); 412 sb.append("0123456789ABCDEF".charAt(b & 0xF)); 413 return sb; 414 } 415 416} 417