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