160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad/*
260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * Copyright 2014, The Android Open Source Project
360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad *
460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * Licensed under the Apache License, Version 2.0 (the "License");
560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * you may not use this file except in compliance with the License.
660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * You may obtain a copy of the License at
760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad *
860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad *     http://www.apache.org/licenses/LICENSE-2.0
960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad *
1060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * Unless required by applicable law or agreed to in writing, software
1160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * distributed under the License is distributed on an "AS IS" BASIS,
1260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * See the License for the specific language governing permissions and
1460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * limitations under the License.
1560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad */
1660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
17ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunnpackage android.telecom;
1860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
193c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordonimport android.net.Uri;
20e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liuimport android.os.AsyncTask;
213c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordonimport android.telephony.PhoneNumberUtils;
223c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordonimport android.text.TextUtils;
23e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu
2460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awadimport java.security.MessageDigest;
2560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awadimport java.security.NoSuchAlgorithmException;
2660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awadimport java.util.IllegalFormatException;
2760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awadimport java.util.Locale;
2860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
2960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad/**
3060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * Manages logging for the entire module.
3160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad *
3260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad * @hide
3360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad */
3460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awadfinal public class Log {
3560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
36ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn    // Generic tag for all Telecom Framework logging
37ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn    private static final String TAG = "TelecomFramework";
3860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
39f3dba2f77de0c7223839bf54e070a7d2d146085aYorke Lee    public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
4060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
4160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static final boolean INFO = isLoggable(android.util.Log.INFO);
4260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
4360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static final boolean WARN = isLoggable(android.util.Log.WARN);
4460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
4560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
46e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu    private static MessageDigest sMessageDigest;
47792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu    private static final Object sMessageDigestLock = new Object();
48e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu
4960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    private Log() {}
5060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
51e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu    public static void initMd5Sum() {
52e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu        new AsyncTask<Void, Void, Void>() {
53e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu            @Override
54e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu            public Void doInBackground(Void... args) {
55e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                MessageDigest md;
56e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                try {
57e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                    md = MessageDigest.getInstance("SHA-1");
58e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                } catch (NoSuchAlgorithmException e) {
59e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                    md = null;
60e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                }
61792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                synchronized (sMessageDigestLock) {
62792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                    sMessageDigest = md;
63792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                }
64e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu                return null;
65e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu            }
66e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu        }.execute();
67e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu    }
68e362e501ee5d8f892d705c0762eff0a584cfb439Hall Liu
6960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static boolean isLoggable(int level) {
7060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
7160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
7260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
7360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void d(String prefix, String format, Object... args) {
7460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (DEBUG) {
7560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.d(TAG, buildMessage(prefix, format, args));
7660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
7760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
7860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
7960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void d(Object objectPrefix, String format, Object... args) {
8060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (DEBUG) {
8160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
8260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
8360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
8460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
8560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void i(String prefix, String format, Object... args) {
8660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (INFO) {
8760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.i(TAG, buildMessage(prefix, format, args));
8860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
8960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
9060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
9160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void i(Object objectPrefix, String format, Object... args) {
9260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (INFO) {
9360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
9460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
9560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
9660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
9760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void v(String prefix, String format, Object... args) {
9860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (VERBOSE) {
9960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.v(TAG, buildMessage(prefix, format, args));
10060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
10160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
10260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
10360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void v(Object objectPrefix, String format, Object... args) {
10460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (VERBOSE) {
10560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
10660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
10760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
10860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
10960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void w(String prefix, String format, Object... args) {
11060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (WARN) {
11160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.w(TAG, buildMessage(prefix, format, args));
11260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
11360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
11460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
11560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void w(Object objectPrefix, String format, Object... args) {
11660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (WARN) {
11760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
11860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
11960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
12060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
12160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void e(String prefix, Throwable tr, String format, Object... args) {
12260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (ERROR) {
12360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.e(TAG, buildMessage(prefix, format, args), tr);
12460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
12560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
12660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
12760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
12860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (ERROR) {
12960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            android.util.Log.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
13060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad                    tr);
13160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
13260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
13360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
13460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void wtf(String prefix, Throwable tr, String format, Object... args) {
13560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        android.util.Log.wtf(TAG, buildMessage(prefix, format, args), tr);
13660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
13760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
13860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
13960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        android.util.Log.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
14060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad                tr);
14160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
14260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
14360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void wtf(String prefix, String format, Object... args) {
14460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        String msg = buildMessage(prefix, format, args);
14560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
14660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
14760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
14860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static void wtf(Object objectPrefix, String format, Object... args) {
14960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
15060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
15160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
15260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
15360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    /**
15460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad     * Redact personally identifiable information for production users.
15560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad     * If we are running in verbose mode, return the original string, otherwise
15660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad     * return a SHA-1 hash of the input string.
15760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad     */
15860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    public static String pii(Object pii) {
15960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        if (pii == null || VERBOSE) {
16060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            return String.valueOf(pii);
1613c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        } if (pii instanceof Uri) {
1623c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon            return piiUri((Uri) pii);
16360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
16460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
16560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
16660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
1673c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon    private static String piiUri(Uri handle) {
1683c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        StringBuilder sb = new StringBuilder();
1693c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        String scheme = handle.getScheme();
1703c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        if (!TextUtils.isEmpty(scheme)) {
1713c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon            sb.append(scheme).append(":");
1723c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        }
1733c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        String value = handle.getSchemeSpecificPart();
1743c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        if (!TextUtils.isEmpty(value)) {
1753c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon            for (int i = 0; i < value.length(); i++) {
1763c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                char c = value.charAt(i);
1773c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                if (PhoneNumberUtils.isStartsPostDial(c)) {
1783c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                    sb.append(c);
1793c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                } else if (PhoneNumberUtils.isDialable(c)) {
1803c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                    sb.append("*");
1813c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
1823c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                    sb.append("*");
1833c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                } else {
1843c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                    sb.append(c);
1853c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon                }
1863c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon            }
1873c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        }
1883c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon        return sb.toString();
1893c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon
1903c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon    }
1913c20d633731a3a2f6ea03012cb4b1d4903a31520Santos Cordon
19260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    private static String secureHash(byte[] input) {
193792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu        synchronized (sMessageDigestLock) {
194792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu            if (sMessageDigest != null) {
195792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                sMessageDigest.reset();
196792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                sMessageDigest.update(input);
197792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                byte[] result = sMessageDigest.digest();
198792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                return encodeHex(result);
199792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu            } else {
200792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu                return "Uninitialized SHA1";
201792ad96eea1ad10da3a65f2655c194a544f49939Hall Liu            }
20260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
20360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
20460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
20560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    private static String encodeHex(byte[] bytes) {
20660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        StringBuffer hex = new StringBuffer(bytes.length * 2);
20760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
20860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        for (int i = 0; i < bytes.length; i++) {
20960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            int byteIntValue = bytes[i] & 0xff;
21060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            if (byteIntValue < 0x10) {
21160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad                hex.append("0");
21260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            }
21360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            hex.append(Integer.toString(byteIntValue, 16));
21460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
21560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
21660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        return hex.toString();
21760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
21860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
21960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    private static String getPrefixFromObject(Object obj) {
22060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        return obj == null ? "<null>" : obj.getClass().getSimpleName();
22160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
22260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad
22360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    private static String buildMessage(String prefix, String format, Object... args) {
22460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        String msg;
22560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        try {
22660ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            msg = (args == null || args.length == 0) ? format
22760ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad                    : String.format(Locale.US, format, args);
22860ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        } catch (IllegalFormatException ife) {
22960ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            wtf("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
23060ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad                    args.length);
23160ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad            msg = format + " (An error occurred while formatting the message.)";
23260ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        }
23360ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad        return String.format(Locale.US, "%s: %s", prefix, msg);
23460ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad    }
23560ac30bb8a30fa7283d592c12ddf2da9447adf14Ihab Awad}
236