• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.dialer.common;
18 
19 import android.support.annotation.NonNull;
20 import android.support.annotation.Nullable;
21 import android.telephony.PhoneNumberUtils;
22 import android.text.TextUtils;
23 
24 /** Provides logging functions. */
25 public class LogUtil {
26 
27   public static final String TAG = "Dialer";
28   private static final String SEPARATOR = " - ";
29 
LogUtil()30   private LogUtil() {}
31 
32   /**
33    * Log at a verbose level. Verbose logs should generally be filtered out, but may be useful when
34    * additional information is needed (e.g. to see how a particular flow evolved). These logs will
35    * not generally be available on production builds.
36    *
37    * @param tag An identifier to allow searching for related logs. Generally of the form
38    *     'Class.method'.
39    * @param msg The message you would like logged, possibly with format arguments.
40    * @param args Optional arguments to be used in the formatted string.
41    * @see {@link String#format(String, Object...)}
42    * @see {@link android.util.Log#v(String, String)}
43    */
v(@onNull String tag, @Nullable String msg, @Nullable Object... args)44   public static void v(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
45     println(android.util.Log.VERBOSE, TAG, tag, msg, args);
46   }
47 
48   /**
49    * Log at a debug level. Debug logs should provide known-useful information to aid in
50    * troubleshooting or evaluating flow. These logs will not generally be available on production
51    * builds.
52    *
53    * @param tag An identifier to allow searching for related logs. Generally of the form
54    *     'Class.method'
55    * @param msg The message you would like logged, possibly with format arguments
56    * @param args Optional arguments to be used in the formatted string
57    * @see {@link String#format(String, Object...)}
58    * @see {@link android.util.Log#d(String, String)}
59    */
d(@onNull String tag, @Nullable String msg, @Nullable Object... args)60   public static void d(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
61     println(android.util.Log.DEBUG, TAG, tag, msg, args);
62   }
63 
64   /**
65    * Log at an info level. Info logs provide information that would be useful to have on production
66    * builds for troubleshooting.
67    *
68    * @param tag An identifier to allow searching for related logs. Generally of the form
69    *     'Class.method'.
70    * @param msg The message you would like logged, possibly with format arguments.
71    * @param args Optional arguments to be used in the formatted string.
72    * @see {@link String#format(String, Object...)}
73    * @see {@link android.util.Log#i(String, String)}
74    */
i(@onNull String tag, @Nullable String msg, @Nullable Object... args)75   public static void i(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
76     println(android.util.Log.INFO, TAG, tag, msg, args);
77   }
78 
79   /**
80    * Log entry into a method at the info level.
81    *
82    * @param tag An identifier to allow searching for related logs. Generally of the form
83    *     'Class.method'.
84    */
enterBlock(String tag)85   public static void enterBlock(String tag) {
86     println(android.util.Log.INFO, TAG, tag, "enter");
87   }
88 
89   /**
90    * Log at a warn level. Warn logs indicate a possible error (e.g. a default switch branch was hit,
91    * or a null object was expected to be non-null), but recovery is possible. This may be used when
92    * it is not guaranteed that an indeterminate or bad state was entered, just that something may
93    * have gone wrong.
94    *
95    * @param tag An identifier to allow searching for related logs. Generally of the form
96    *     'Class.method'.
97    * @param msg The message you would like logged, possibly with format arguments.
98    * @param args Optional arguments to be used in the formatted string.
99    * @see {@link String#format(String, Object...)}
100    * @see {@link android.util.Log#w(String, String)}
101    */
w(@onNull String tag, @Nullable String msg, @Nullable Object... args)102   public static void w(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
103     println(android.util.Log.WARN, TAG, tag, msg, args);
104   }
105 
106   /**
107    * Log at an error level. Error logs are used when it is known that an error occurred and is
108    * possibly fatal. This is used to log information that will be useful for troubleshooting a crash
109    * or other severe condition (e.g. error codes, state values, etc.).
110    *
111    * @param tag An identifier to allow searching for related logs. Generally of the form
112    *     'Class.method'.
113    * @param msg The message you would like logged, possibly with format arguments.
114    * @param args Optional arguments to be used in the formatted string.
115    * @see {@link String#format(String, Object...)}
116    * @see {@link android.util.Log#e(String, String)}
117    */
e(@onNull String tag, @Nullable String msg, @Nullable Object... args)118   public static void e(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
119     println(android.util.Log.ERROR, TAG, tag, msg, args);
120   }
121 
122   /**
123    * Log an exception at an error level. Error logs are used when it is known that an error occurred
124    * and is possibly fatal. This is used to log information that will be useful for troubleshooting
125    * a crash or other severe condition (e.g. error codes, state values, etc.).
126    *
127    * @param tag An identifier to allow searching for related logs. Generally of the form
128    *     'Class.method'.
129    * @param msg The message you would like logged.
130    * @param throwable The exception to log.
131    * @see {@link String#format(String, Object...)}
132    * @see {@link android.util.Log#e(String, String)}
133    */
e(@onNull String tag, @Nullable String msg, @NonNull Throwable throwable)134   public static void e(@NonNull String tag, @Nullable String msg, @NonNull Throwable throwable) {
135     if (!TextUtils.isEmpty(msg)) {
136       println(android.util.Log.ERROR, TAG, tag, msg);
137     }
138     println(android.util.Log.ERROR, TAG, tag, android.util.Log.getStackTraceString(throwable));
139   }
140 
141   /**
142    * Used for log statements where we don't want to log various strings (e.g., usernames) with
143    * default logging to avoid leaking PII in logcat.
144    *
145    * @return text as is if {@value #TAG}'s log level is set to DEBUG or VERBOSE or on non-release
146    *     builds; returns a redacted version otherwise.
147    */
sanitizePii(@ullable Object object)148   public static String sanitizePii(@Nullable Object object) {
149     if (object == null) {
150       return "null";
151     }
152     if (isDebugEnabled()) {
153       return object.toString();
154     }
155     return "Redacted-" + object.toString().length() + "-chars";
156   }
157 
158   /** Anonymizes char to prevent logging personally identifiable information. */
sanitizeDialPadChar(char ch)159   public static char sanitizeDialPadChar(char ch) {
160     if (isDebugEnabled()) {
161       return ch;
162     }
163     if (is12Key(ch)) {
164       return '*';
165     }
166     return ch;
167   }
168 
169   /** Anonymizes the phone number to prevent logging personally identifiable information. */
sanitizePhoneNumber(@ullable String phoneNumber)170   public static String sanitizePhoneNumber(@Nullable String phoneNumber) {
171     if (isDebugEnabled()) {
172       return phoneNumber;
173     }
174     if (phoneNumber == null) {
175       return null;
176     }
177     StringBuilder stringBuilder = new StringBuilder(phoneNumber.length());
178     for (char c : phoneNumber.toCharArray()) {
179       stringBuilder.append(sanitizeDialPadChar(c));
180     }
181     return stringBuilder.toString();
182   }
183 
isVerboseEnabled()184   public static boolean isVerboseEnabled() {
185     return android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE);
186   }
187 
isDebugEnabled()188   public static boolean isDebugEnabled() {
189     return android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
190   }
191 
is12Key(char ch)192   private static boolean is12Key(char ch) {
193     return PhoneNumberUtils.is12Key(ch);
194   }
195 
println( int level, @NonNull String tag, @NonNull String localTag, @Nullable String msg, @Nullable Object... args)196   private static void println(
197       int level,
198       @NonNull String tag,
199       @NonNull String localTag,
200       @Nullable String msg,
201       @Nullable Object... args) {
202     // Formatted message is computed lazily if required.
203     String formattedMsg;
204     // Either null is passed as a single argument or more than one argument is passed.
205     boolean hasArgs = args == null || args.length > 0;
206     if ((level >= android.util.Log.INFO) || android.util.Log.isLoggable(tag, level)) {
207       formattedMsg = localTag;
208       if (!TextUtils.isEmpty(msg)) {
209         formattedMsg += SEPARATOR + (hasArgs ? String.format(msg, args) : msg);
210       }
211       android.util.Log.println(level, tag, formattedMsg);
212     }
213   }
214 }
215