[go: nahoru, domu]

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
17package android.telecom;
18
19import android.net.Uri;
20import android.os.AsyncTask;
21import android.telephony.PhoneNumberUtils;
22import android.text.TextUtils;
23
24import java.security.MessageDigest;
25import java.security.NoSuchAlgorithmException;
26import java.util.IllegalFormatException;
27import java.util.Locale;
28
29/**
30 * Manages logging for the entire module.
31 *
32 * @hide
33 */
34final 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
49    private Log() {}
50
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
69    public static boolean isLoggable(int level) {
70        return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
71    }
72
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
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
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
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
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
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
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
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
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
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
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
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
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
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     */
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
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
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
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
219    private static String getPrefixFromObject(Object obj) {
220        return obj == null ? "<null>" : obj.getClass().getSimpleName();
221    }
222
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