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 */ 16 package com.android.mail.utils; 17 18 import android.net.Uri; 19 import android.text.TextUtils; 20 import android.util.Log; 21 import com.google.common.annotations.VisibleForTesting; 22 23 import java.util.List; 24 import java.util.regex.Pattern; 25 26 public class LogUtils { 27 28 // "GMT" + "+" or "-" + 4 digits 29 private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE = 30 Pattern.compile("GMT([-+]\\d{4})$"); 31 private static String LOG_TAG = "UnifiedEmail"; 32 33 /** 34 * Get the log tag to apply to logging. 35 */ 36 public String getLogTag() { 37 return LOG_TAG; 38 } 39 40 /** 41 * Priority constant for the println method; use LogUtils.v. 42 */ 43 public static final int VERBOSE = Log.VERBOSE; 44 45 /** 46 * Priority constant for the println method; use LogUtils.d. 47 */ 48 public static final int DEBUG = Log.DEBUG; 49 50 /** 51 * Priority constant for the println method; use LogUtils.i. 52 */ 53 public static final int INFO = Log.INFO; 54 55 /** 56 * Priority constant for the println method; use LogUtils.w. 57 */ 58 public static final int WARN = Log.WARN; 59 60 /** 61 * Priority constant for the println method; use LogUtils.e. 62 */ 63 public static final int ERROR = Log.ERROR; 64 65 /** 66 * Used to enable/disable logging that we don't want included in 67 * production releases. 68 */ 69 private static final int MAX_ENABLED_LOG_LEVEL = VERBOSE; 70 71 private static Boolean sDebugLoggingEnabledForTests = null; 72 73 /** 74 * Enable debug logging for unit tests. 75 */ 76 @VisibleForTesting 77 static void setDebugLoggingEnabledForTests(boolean enabled) { 78 sDebugLoggingEnabledForTests = Boolean.valueOf(enabled); 79 } 80 81 /** 82 * Returns true if the build configuration prevents debug logging. 83 */ 84 @VisibleForTesting 85 public static boolean buildPreventsDebugLogging() { 86 return MAX_ENABLED_LOG_LEVEL > VERBOSE; 87 } 88 89 /** 90 * Returns a boolean indicating whether debug logging is enabled. 91 */ 92 protected static boolean isDebugLoggingEnabled() { 93 if (buildPreventsDebugLogging()) { 94 return false; 95 } 96 if (sDebugLoggingEnabledForTests != null) { 97 return sDebugLoggingEnabledForTests.booleanValue(); 98 } 99 return Log.isLoggable(LOG_TAG, Log.DEBUG); 100 } 101 102 /** 103 * Returns a String for the specified content provider uri. This will do 104 * sanitation of the uri to remove PII if debug logging is not enabled. 105 */ 106 public static String contentUriToString(Uri uri) { 107 108 if (isDebugLoggingEnabled()) { 109 // Debug logging has been enabled, so log the uri as is 110 return uri.toString(); 111 } else { 112 // Debug logging is not enabled, we want to remove the email address from the uri. 113 List<String> pathSegments = uri.getPathSegments(); 114 115 Uri.Builder builder = new Uri.Builder() 116 .scheme(uri.getScheme()) 117 .authority(uri.getAuthority()) 118 .query(uri.getQuery()) 119 .fragment(uri.getFragment()); 120 121 // This assumes that the first path segment is the account 122 final String account = pathSegments.get(0); 123 124 builder = builder.appendPath(String.valueOf(account.hashCode())); 125 for (int i = 1; i < pathSegments.size(); i++) { 126 builder.appendPath(pathSegments.get(i)); 127 } 128 return builder.toString(); 129 } 130 } 131 132 /* TODO: what is the correct behavior for base case and the Gmail case? Seems like this 133 * belongs in override code in UnifiedGmail. 134 *Converts the specified set of labels to a string, and removes any PII as necessary 135 * public static String labelSetToString(Set<String> labelSet) { 136 if (isDebugLoggingEnabled() || labelSet == null) { 137 return labelSet != null ? labelSet.toString() : ""; 138 } else { 139 final StringBuilder builder = new StringBuilder("["); 140 int i = 0; 141 for(String label : labelSet) { 142 if (i > 0) { 143 builder.append(", "); 144 } 145 builder.append(sanitizeLabelName(label)); 146 i++; 147 } 148 builder.append(']'); 149 return builder.toString(); 150 } 151 } 152 153 private static String sanitizeLabelName(String canonicalName) { 154 if (TextUtils.isEmpty(canonicalName)) { 155 return ""; 156 } 157 158 if (Gmail.isSystemLabel(canonicalName)) { 159 return canonicalName; 160 } 161 162 return USER_LABEL_PREFIX + String.valueOf(canonicalName.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); 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