1 /*
2  * Copyright (C) 2015 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.messaging.util;
18 
19 /**
20  * Log utility class.
21  */
22 public class LogUtil {
23     public static final String BUGLE_TAG = "MessagingApp";
24     public static final String PROFILE_TAG = "MessagingAppProf";
25     public static final String BUGLE_DATABASE_TAG = "MessagingAppDb";
26     public static final String BUGLE_DATABASE_PERF_TAG = "MessagingAppDbPerf";
27     public static final String BUGLE_DATAMODEL_TAG = "MessagingAppDataModel";
28     public static final String BUGLE_IMAGE_TAG = "MessagingAppImage";
29     public static final String BUGLE_NOTIFICATIONS_TAG = "MessagingAppNotif";
30     public static final String BUGLE_WIDGET_TAG = "MessagingAppWidget";
31 
32     public static final int DEBUG = android.util.Log.DEBUG;
33     public static final int WARN = android.util.Log.WARN;
34     public static final int VERBOSE = android.util.Log.VERBOSE;
35     public static final int INFO = android.util.Log.INFO;
36     public static final int ERROR = android.util.Log.ERROR;
37 
38     // If this is non-null, DEBUG and higher logs will be tracked in-memory. It will not include
39     // VERBOSE logs.
40     private static LogSaver sDebugLogSaver;
41     private static volatile boolean sCaptureDebugLogs;
42 
43     /**
44      * Read Gservices to see if logging should be enabled.
45      */
refreshGservices(final BugleGservices gservices)46     public static void refreshGservices(final BugleGservices gservices) {
47         sCaptureDebugLogs = gservices.getBoolean(
48                 BugleGservicesKeys.ENABLE_LOG_SAVER,
49                 BugleGservicesKeys.ENABLE_LOG_SAVER_DEFAULT);
50         if (sCaptureDebugLogs && (sDebugLogSaver == null || !sDebugLogSaver.isCurrent())) {
51             // We were not capturing logs before. We are now.
52             sDebugLogSaver = LogSaver.newInstance();
53         } else if (!sCaptureDebugLogs && sDebugLogSaver != null) {
54             // We were capturing logs. We aren't anymore.
55             sDebugLogSaver = null;
56         }
57     }
58 
59  // This is called from FactoryImpl once the Gservices class is initialized.
initializeGservices(final BugleGservices gservices)60     public static void initializeGservices (final BugleGservices gservices) {
61         gservices.registerForChanges(new Runnable() {
62             @Override
63             public void run() {
64                 refreshGservices(gservices);
65             }
66         });
67         refreshGservices(gservices);
68     }
69 
70     /**
71      * Send a {@link #VERBOSE} log message.
72      * @param tag Used to identify the source of a log message.  It usually identifies
73      *        the class or activity where the log call occurs.
74      * @param msg The message you would like logged.
75      */
v(final String tag, final String msg)76     public static void v(final String tag, final String msg) {
77         println(android.util.Log.VERBOSE, tag, msg);
78     }
79 
80     /**
81      * Send a {@link #VERBOSE} log message.
82      * @param tag Used to identify the source of a log message.  It usually identifies
83      *        the class or activity where the log call occurs.
84      * @param msg The message you would like logged.
85      * @param tr An exception to log
86      */
v(final String tag, final String msg, final Throwable tr)87     public static void v(final String tag, final String msg, final Throwable tr) {
88         println(android.util.Log.VERBOSE, tag, msg + '\n'
89                 + android.util.Log.getStackTraceString(tr));
90     }
91 
92     /**
93      * Send a {@link #DEBUG} log message.
94      * @param tag Used to identify the source of a log message.  It usually identifies
95      *        the class or activity where the log call occurs.
96      * @param msg The message you would like logged.
97      */
d(final String tag, final String msg)98     public static void d(final String tag, final String msg) {
99         println(android.util.Log.DEBUG, tag, msg);
100     }
101 
102     /**
103      * Send a {@link #DEBUG} log message and log the exception.
104      * @param tag Used to identify the source of a log message.  It usually identifies
105      *        the class or activity where the log call occurs.
106      * @param msg The message you would like logged.
107      * @param tr An exception to log
108      */
d(final String tag, final String msg, final Throwable tr)109     public static void d(final String tag, final String msg, final Throwable tr) {
110         println(android.util.Log.DEBUG, tag, msg + '\n'
111                 + android.util.Log.getStackTraceString(tr));
112     }
113 
114     /**
115      * Send an {@link #INFO} log message.
116      * @param tag Used to identify the source of a log message.  It usually identifies
117      *        the class or activity where the log call occurs.
118      * @param msg The message you would like logged.
119      */
i(final String tag, final String msg)120     public static void i(final String tag, final String msg) {
121         println(android.util.Log.INFO, tag, msg);
122     }
123 
124     /**
125      * Send a {@link #INFO} log message and log the exception.
126      * @param tag Used to identify the source of a log message.  It usually identifies
127      *        the class or activity where the log call occurs.
128      * @param msg The message you would like logged.
129      * @param tr An exception to log
130      */
i(final String tag, final String msg, final Throwable tr)131     public static void i(final String tag, final String msg, final Throwable tr) {
132         println(android.util.Log.INFO, tag, msg + '\n'
133                 + android.util.Log.getStackTraceString(tr));
134     }
135 
136     /**
137      * Send a {@link #WARN} log message.
138      * @param tag Used to identify the source of a log message.  It usually identifies
139      *        the class or activity where the log call occurs.
140      * @param msg The message you would like logged.
141      */
w(final String tag, final String msg)142     public static void w(final String tag, final String msg) {
143         println(android.util.Log.WARN, tag, msg);
144     }
145 
146     /**
147      * Send a {@link #WARN} log message and log the exception.
148      * @param tag Used to identify the source of a log message.  It usually identifies
149      *        the class or activity where the log call occurs.
150      * @param msg The message you would like logged.
151      * @param tr An exception to log
152      */
w(final String tag, final String msg, final Throwable tr)153     public static void w(final String tag, final String msg, final Throwable tr) {
154         println(android.util.Log.WARN, tag, msg);
155         println(android.util.Log.WARN, tag, android.util.Log.getStackTraceString(tr));
156     }
157 
158     /**
159      * Send an {@link #ERROR} log message.
160      * @param tag Used to identify the source of a log message.  It usually identifies
161      *        the class or activity where the log call occurs.
162      * @param msg The message you would like logged.
163      */
e(final String tag, final String msg)164     public static void e(final String tag, final String msg) {
165         println(android.util.Log.ERROR, tag, msg);
166     }
167 
168     /**
169      * Send a {@link #ERROR} log message and log the exception.
170      * @param tag Used to identify the source of a log message.  It usually identifies
171      *        the class or activity where the log call occurs.
172      * @param msg The message you would like logged.
173      * @param tr An exception to log
174      */
e(final String tag, final String msg, final Throwable tr)175     public static void e(final String tag, final String msg, final Throwable tr) {
176         println(android.util.Log.ERROR, tag, msg);
177         println(android.util.Log.ERROR, tag, android.util.Log.getStackTraceString(tr));
178     }
179 
180     /**
181      * What a Terrible Failure: Report a condition that should never happen.
182      * The error will always be logged at level ASSERT with the call stack.
183      * Depending on system configuration, a report may be added to the
184      * {@link android.os.DropBoxManager} and/or the process may be terminated
185      * immediately with an error dialog.
186      * @param tag Used to identify the source of a log message.
187      * @param msg The message you would like logged.
188      */
wtf(final String tag, final String msg)189     public static void wtf(final String tag, final String msg) {
190         // Make sure this goes into our log buffer
191         println(android.util.Log.ASSERT, tag, "wtf\n" + msg);
192         android.util.Log.wtf(tag, msg, new Exception());
193     }
194 
195     /**
196      * What a Terrible Failure: Report a condition that should never happen.
197      * The error will always be logged at level ASSERT with the call stack.
198      * Depending on system configuration, a report may be added to the
199      * {@link android.os.DropBoxManager} and/or the process may be terminated
200      * immediately with an error dialog.
201      * @param tag Used to identify the source of a log message.
202      * @param msg The message you would like logged.
203      * @param tr An exception to log
204      */
wtf(final String tag, final String msg, final Throwable tr)205     public static void wtf(final String tag, final String msg, final Throwable tr) {
206         // Make sure this goes into our log buffer
207         println(android.util.Log.ASSERT, tag, "wtf\n" + msg + '\n' +
208                 android.util.Log.getStackTraceString(tr));
209         android.util.Log.wtf(tag, msg, tr);
210     }
211 
212     /**
213      * Low-level logging call.
214      * @param level The priority/type of this log message
215      * @param tag Used to identify the source of a log message.  It usually identifies
216      *        the class or activity where the log call occurs.
217      * @param msg The message you would like logged.
218      */
println(final int level, final String tag, final String msg)219     private static void println(final int level, final String tag, final String msg) {
220         android.util.Log.println(level, tag, msg);
221 
222         LogSaver serviceLog = sDebugLogSaver;
223         if (serviceLog != null && level >= android.util.Log.DEBUG) {
224             serviceLog.log(level, tag, msg);
225         }
226     }
227 
228     /**
229      * Save logging into LogSaver only, for dumping to bug report
230      *
231      * @param level The priority/type of this log message
232      * @param tag Used to identify the source of a log message.  It usually identifies
233      *        the class or activity where the log call occurs.
234      * @param msg The message you would like logged.
235      */
save(final int level, final String tag, final String msg)236     public static void save(final int level, final String tag, final String msg) {
237         LogSaver serviceLog = sDebugLogSaver;
238         if (serviceLog != null) {
239             serviceLog.log(level, tag, msg);
240         }
241     }
242 
243     /**
244      * Checks to see whether or not a log for the specified tag is loggable at the specified level.
245      * See {@link android.util.Log#isLoggable(String, int)} for more discussion.
246      */
isLoggable(final String tag, final int level)247     public static boolean isLoggable(final String tag, final int level) {
248         return android.util.Log.isLoggable(tag, level);
249     }
250 
251     /**
252      * Returns text as is if {@value #BUGLE_TAG}'s log level is set to DEBUG or VERBOSE;
253      * returns "--" otherwise. Useful for log statements where we don't want to log
254      * various strings (e.g., usernames) with default logging to avoid leaking PII in logcat.
255      */
sanitizePII(final String text)256     public static String sanitizePII(final String text) {
257         if (text == null) {
258             return null;
259         }
260 
261         if (android.util.Log.isLoggable(BUGLE_TAG, android.util.Log.DEBUG)) {
262             return text;
263         } else {
264             return "Redacted-" + text.length();
265         }
266     }
267 
dump(java.io.PrintWriter out)268     public static void dump(java.io.PrintWriter out) {
269         final LogSaver logsaver = sDebugLogSaver;
270         if (logsaver != null) {
271             logsaver.dump(out);
272         }
273     }
274 }
275