1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (c) 2011, Google Inc.
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License");
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * you may not use this file except in compliance with the License.
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * You may obtain a copy of the License at
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *     http://www.apache.org/licenses/LICENSE-2.0
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage com.android.mail.utils;
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.net.Uri;
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.text.TextUtils;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.util.Log;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.google.common.annotations.VisibleForTesting;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.List;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.regex.Pattern;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class LogUtils {
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // "GMT" + "+" or "-" + 4 digits
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE =
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Pattern.compile("GMT([-+]\\d{4})$");
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static String LOG_TAG = "UnifiedEmail";
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Get the log tag to apply to logging.
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String getLogTag() {
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return LOG_TAG;
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Priority constant for the println method; use LogUtils.v.
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int VERBOSE = Log.VERBOSE;
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Priority constant for the println method; use LogUtils.d.
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int DEBUG = Log.DEBUG;
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Priority constant for the println method; use LogUtils.i.
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int INFO = Log.INFO;
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Priority constant for the println method; use LogUtils.w.
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int WARN = Log.WARN;
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Priority constant for the println method; use LogUtils.e.
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int ERROR = Log.ERROR;
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Used to enable/disable logging that we don't want included in
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * production releases.
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int MAX_ENABLED_LOG_LEVEL = VERBOSE;
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static Boolean sDebugLoggingEnabledForTests = null;
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Enable debug logging for unit tests.
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @VisibleForTesting
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static void setDebugLoggingEnabledForTests(boolean enabled) {
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        sDebugLoggingEnabledForTests = Boolean.valueOf(enabled);
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns true if the build configuration prevents debug logging.
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @VisibleForTesting
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static boolean buildPreventsDebugLogging() {
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return MAX_ENABLED_LOG_LEVEL > VERBOSE;
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns a boolean indicating whether debug logging is enabled.
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected static boolean isDebugLoggingEnabled() {
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (buildPreventsDebugLogging()) {
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return false;
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (sDebugLoggingEnabledForTests != null) {
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return sDebugLoggingEnabledForTests.booleanValue();
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return Log.isLoggable(LOG_TAG, Log.DEBUG);
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns a String for the specified content provider uri.  This will do
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * sanitation of the uri to remove PII if debug logging is not enabled.
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static String contentUriToString(Uri uri) {
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isDebugLoggingEnabled()) {
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Debug logging has been enabled, so log the uri as is
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return uri.toString();
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Debug logging is not enabled, we want to remove the email address from the uri.
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            List<String> pathSegments = uri.getPathSegments();
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Uri.Builder builder = new Uri.Builder()
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    .scheme(uri.getScheme())
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    .authority(uri.getAuthority())
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    .query(uri.getQuery())
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    .fragment(uri.getFragment());
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // This assumes that the first path segment is the account
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final String account = pathSegments.get(0);
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            builder = builder.appendPath(String.valueOf(account.hashCode()));
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            for (int i = 1; i < pathSegments.size(); i++) {
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                builder.appendPath(pathSegments.get(i));
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return builder.toString();
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook   /* TODO: what is the correct behavior for base case and the Gmail case? Seems like this
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    * belongs in override code in UnifiedGmail.
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    *Converts the specified set of labels to a string, and removes any PII as necessary
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    * public static String labelSetToString(Set<String> labelSet) {
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isDebugLoggingEnabled() || labelSet == null) {
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return labelSet != null ? labelSet.toString() : "";
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final StringBuilder builder = new StringBuilder("[");
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            int i = 0;
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            for(String label : labelSet) {
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (i > 0) {
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    builder.append(", ");
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                builder.append(sanitizeLabelName(label));
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                i++;
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            builder.append(']');
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return builder.toString();
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static String sanitizeLabelName(String canonicalName) {
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (TextUtils.isEmpty(canonicalName)) {
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return "";
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Gmail.isSystemLabel(canonicalName)) {
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return canonicalName;
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return USER_LABEL_PREFIX + String.valueOf(canonicalName.hashCode());
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }*/
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Checks to see whether or not a log for the specified tag is loggable at the specified level.
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static boolean isLoggable(String tag, int level) {
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (MAX_ENABLED_LOG_LEVEL > level) {
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return false;
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return Log.isLoggable(tag, level);
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #VERBOSE} log message.
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int v(String tag, String format, Object... args) {
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, VERBOSE)) {
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.v(tag, String.format(format, args));
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #VERBOSE} log message.
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int v(String tag, Throwable tr, String format, Object... args) {
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, VERBOSE)) {
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.v(tag, String.format(format, args), tr);
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #DEBUG} log message.
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int d(String tag, String format, Object... args) {
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, DEBUG)) {
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.d(tag, String.format(format, args));
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #DEBUG} log message.
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int d(String tag, Throwable tr, String format, Object... args) {
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, DEBUG)) {
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.d(tag, String.format(format, args), tr);
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #INFO} log message.
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int i(String tag, String format, Object... args) {
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, INFO)) {
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.i(tag, String.format(format, args));
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #INFO} log message.
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
270bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
271bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
272bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
273bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int i(String tag, Throwable tr, String format, Object... args) {
274bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, INFO)) {
275bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.i(tag, String.format(format, args), tr);
276bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
279bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
280bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
281bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #WARN} log message.
282bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
283bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
284bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
285bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
286bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
287bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
288bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
289bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
290bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int w(String tag, String format, Object... args) {
291bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, WARN)) {
292bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.w(tag, String.format(format, args));
293bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
294bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
295bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
296bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
297bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
298bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #WARN} log message.
299bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
300bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
301bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
302bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
303bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
304bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
305bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
306bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
307bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
308bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int w(String tag, Throwable tr, String format, Object... args) {
309bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, WARN)) {
310bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.w(tag, String.format(format, args), tr);
311bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
312bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
313bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
314bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
315bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
316bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #ERROR} log message.
317bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
318bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
319bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
320bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
321bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
322bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
323bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
324bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
325bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int e(String tag, String format, Object... args) {
326bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, ERROR)) {
327bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.e(tag, String.format(format, args));
328bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
329bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
330bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
331bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
332bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
333bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Send a {@link #ERROR} log message.
334bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
335bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
336bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
337bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
338bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
339bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
340bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
341bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
342bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
343bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int e(String tag, Throwable tr, String format, Object... args) {
344bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isLoggable(tag, ERROR)) {
345bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Log.e(tag, String.format(format, args), tr);
346bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
347bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
348bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
349bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
350bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
351bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * What a Terrible Failure: Report a condition that should never happen.
352bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The error will always be logged at level ASSERT with the call stack.
353bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Depending on system configuration, a report may be added to the
354bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link android.os.DropBoxManager} and/or the process may be terminated
355bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * immediately with an error dialog.
356bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
357bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
358bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
359bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
360bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
361bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
362bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
363bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
364bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int wtf(String tag, String format, Object... args) {
365bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return Log.wtf(tag, String.format(format, args), new Error());
366bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
367bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
368bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
369bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * What a Terrible Failure: Report a condition that should never happen.
370bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The error will always be logged at level ASSERT with the call stack.
371bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Depending on system configuration, a report may be added to the
372bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link android.os.DropBoxManager} and/or the process may be terminated
373bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * immediately with an error dialog.
374bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tag Used to identify the source of a log message.  It usually identifies
375bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        the class or activity where the log call occurs.
376bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param tr An exception to log
377bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param format the format string (see {@link java.util.Formatter#format})
378bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param args
379bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            the list of arguments passed to the formatter. If there are
380bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            more arguments than required by {@code format},
381bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *            additional arguments are ignored.
382bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
383bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static int wtf(String tag, Throwable tr, String format, Object... args) {
384bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return Log.wtf(tag, String.format(format, args), tr);
385bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
386bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
387bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
388bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
389bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Try to make a date MIME(RFC 2822/5322)-compliant.
390bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
391bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * It fixes:
392bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700"
393bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *   (4 digit zone value can't be preceded by "GMT")
394bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *   We got a report saying eBay sends a date in this format
395bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
396bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static String cleanUpMimeDate(String date) {
397bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (TextUtils.isEmpty(date)) {
398bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return date;
399bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
400bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1");
401bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return date;
402bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
403bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
404bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
405bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static String byteToHex(int b) {
406bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return byteToHex(new StringBuilder(), b).toString();
407bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
408bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
409bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static StringBuilder byteToHex(StringBuilder sb, int b) {
410bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        b &= 0xFF;
411bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        sb.append("0123456789ABCDEF".charAt(b >> 4));
412bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        sb.append("0123456789ABCDEF".charAt(b & 0xF));
413bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return sb;
414bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
415bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
416bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
417