1 /*
2  * Copyright (C) 2019 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.internal.net.utils;
18 
19 import com.android.internal.annotations.VisibleForTesting;
20 
21 import java.util.Locale;
22 import java.util.Objects;
23 
24 /**
25  * Manages logging for all IKE packages. Wraps Android's Log class to prevent leakage of PII.
26  */
27 public class Log {
28     private static final boolean VDBG = false;
29 
30     private final String mTAG;
31     private final boolean mIsVdbg;
32     private final boolean mLogSensitive;
33 
34     /**
35      * Constructs a Log instance configured with the given tag and logSensitive flag
36      *
37      * @param tag the String tag to be used for this Log's logging
38      * @param logSensitive boolean flag marking whether sensitive data (PII) should be logged
39      */
Log(String tag, boolean logSensitive)40     public Log(String tag, boolean logSensitive) {
41         this(tag, VDBG, logSensitive);
42     }
43 
44     @VisibleForTesting
Log(String tag, boolean isVdbg, boolean logSensitive)45     Log(String tag, boolean isVdbg, boolean logSensitive) {
46         this.mTAG = tag;
47         this.mIsVdbg = isVdbg;
48         this.mLogSensitive = logSensitive;
49     }
50 
51     /**
52      * Logs the given prefix and msg Strings.
53      *
54      * <p>Note: Logging is only done if this instance's logging level is {@link
55      * android.util.Log#VERBOSE} or higher.
56      *
57      * @param prefix the String prefix to be used for this log entry
58      * @param msg the String msg to be logged
59      */
v(String prefix, String msg)60     public void v(String prefix, String msg) {
61         if (isLoggable(android.util.Log.VERBOSE)) {
62             android.util.Log.v(mTAG, prefix + ": " + msg);
63         }
64     }
65 
66     /**
67      * Logs the given prefix and msg Strings.
68      *
69      * <p>Note: Logging is only done if this instance's logging level is {@link
70      * android.util.Log#VERBOSE} or higher.
71      *
72      * @param prefix the String prefix to be used for this log entry
73      * @param msg the String msg to be logged
74      * @param tr an Exception to log
75      */
v(String prefix, String msg, Throwable tr)76     public void v(String prefix, String msg, Throwable tr) {
77         if (isLoggable(android.util.Log.VERBOSE)) {
78             android.util.Log.v(mTAG, prefix + ": " + msg, tr);
79         }
80     }
81 
82     /**
83      * Logs the given prefix and msg Strings.
84      *
85      * <p>Note: Logging is only done if this instance's logging level is {@link
86      * android.util.Log#DEBUG} or higher.
87      *
88      * @param prefix the String prefix to be used for this log entry
89      * @param msg the String msg to be logged
90      */
d(String prefix, String msg)91     public void d(String prefix, String msg) {
92         if (isLoggable(android.util.Log.DEBUG)) {
93             android.util.Log.d(mTAG, prefix + ": " + msg);
94         }
95     }
96 
97     /**
98      * Logs the given prefix and msg Strings.
99      *
100      * <p>Note: Logging is only done if this instance's logging level is {@link
101      * android.util.Log#DEBUG} or higher.
102      *
103      * @param prefix the String prefix to be used for this log entry
104      * @param msg the String msg to be logged
105      * @param tr an Exception to log
106      */
d(String prefix, String msg, Throwable tr)107     public void d(String prefix, String msg, Throwable tr) {
108         if (isLoggable(android.util.Log.DEBUG)) {
109             android.util.Log.d(mTAG, prefix + ": " + msg, tr);
110         }
111     }
112 
113     /**
114      * Logs the given prefix and msg Strings.
115      *
116      * <p>Note: Logging is only done if this instance's logging level is {@link
117      * android.util.Log#INFO} or higher.
118      *
119      * @param prefix the String prefix to be used for this log entry
120      * @param msg the String msg to be logged
121      */
i(String prefix, String msg)122     public void i(String prefix, String msg) {
123         if (isLoggable(android.util.Log.INFO)) {
124             android.util.Log.i(mTAG, prefix + ": " + msg);
125         }
126     }
127 
128     /**
129      * Logs the given prefix and msg Strings.
130      *
131      * <p>Note: Logging is only done if this instance's logging level is {@link
132      * android.util.Log#INFO} or higher.
133      *
134      * @param prefix the String prefix to be used for this log entry
135      * @param msg the String msg to be logged
136      * @param tr an Exception to log
137      */
i(String prefix, String msg, Throwable tr)138     public void i(String prefix, String msg, Throwable tr) {
139         if (isLoggable(android.util.Log.INFO)) {
140             android.util.Log.i(mTAG, prefix + ": " + msg, tr);
141         }
142     }
143 
144     /**
145      * Logs the given prefix and msg Strings.
146      *
147      * <p>Note: Logging is only done if this instance's logging level is {@link
148      * android.util.Log#WARN} or higher.
149      *
150      * @param prefix the String prefix to be used for this log entry
151      * @param msg the String msg to be logged
152      */
w(String prefix, String msg)153     public void w(String prefix, String msg) {
154         if (isLoggable(android.util.Log.WARN)) {
155             android.util.Log.w(mTAG, prefix + ": " + msg);
156         }
157     }
158 
159     /**
160      * Logs the given prefix and msg Strings.
161      *
162      * <p>Note: Logging is only done if this instance's logging level is {@link
163      * android.util.Log#WARN} or higher.
164      *
165      * @param prefix the String prefix to be used for this log entry
166      * @param msg the String msg to be logged
167      * @param tr an Exception to log
168      */
w(String prefix, String msg, Throwable tr)169     public void w(String prefix, String msg, Throwable tr) {
170         if (isLoggable(android.util.Log.WARN)) {
171             android.util.Log.w(mTAG, prefix + ": " + msg, tr);
172         }
173     }
174 
175     /**
176      * Logs the given prefix and msg Strings.
177      *
178      * <p>Note: Logging is only done if this instance's logging level is {@link
179      * android.util.Log#ERROR} or higher.
180      *
181      * @param prefix the String prefix to be used for this log entry
182      * @param msg the String msg to be logged
183      */
e(String prefix, String msg)184     public void e(String prefix, String msg) {
185         if (isLoggable(android.util.Log.ERROR)) {
186             android.util.Log.e(mTAG, prefix + ": " + msg);
187         }
188     }
189 
190     /**
191      * Logs the given prefix and msg Strings.
192      *
193      * <p>Note: Logging is only done if this instance's logging level is {@link
194      * android.util.Log#ERROR} or higher.
195      *
196      * @param prefix the String prefix to be used for this log entry
197      * @param msg the String msg to be logged
198      * @param tr an Exception to log
199      */
e(String prefix, String msg, Throwable tr)200     public void e(String prefix, String msg, Throwable tr) {
201         if (isLoggable(android.util.Log.ERROR)) {
202             android.util.Log.e(mTAG, prefix + ": " + msg, tr);
203         }
204     }
205 
206     /**
207      * What a Terrible Failure: Report a condition that should never happen.
208      * The error will always be logged at level ASSERT with the call stack.
209      * Depending on system configuration, a report may be added to the
210      * {@link android.os.DropBoxManager} and/or the process may be terminated
211      * immediately with an error dialog.
212      *
213      * @param prefix the String prefix to be used for this log entry
214      * @param msg the String msg to be logged
215      */
wtf(String prefix, String msg)216     public void wtf(String prefix, String msg) {
217         android.util.Log.wtf(mTAG, prefix + ": " + msg);
218     }
219 
220     /**
221      * What a Terrible Failure: Report a condition that should never happen.
222      * The error will always be logged at level ASSERT with the call stack.
223      * Depending on system configuration, a report may be added to the
224      * {@link android.os.DropBoxManager} and/or the process may be terminated
225      * immediately with an error dialog.
226      *
227      * @param prefix the String prefix to be used for this log entry
228      * @param msg the String msg to be logged
229      * @param tr an Exception to log
230      */
wtf(String prefix, String msg, Throwable tr)231     public void wtf(String prefix, String msg, Throwable tr) {
232         android.util.Log.wtf(mTAG, prefix + ": " + msg, tr);
233     }
234 
235     /**
236      * Returns a String-formatted version of the given PII.
237      *
238      * <p>Depending on the logging configurations and build-type, the returned PII may be
239      * obfuscated.
240      *
241      * @param pii the PII to be formatted
242      * @return the String-formatted version of the PII
243      */
pii(Object pii)244     public String pii(Object pii) {
245         if (!mIsVdbg || !mLogSensitive) {
246             return String.valueOf(Objects.hashCode(pii));
247         } else {
248             if (pii instanceof byte[]) {
249                 return byteArrayToHexString((byte[]) pii);
250             }
251             return String.valueOf(pii);
252         }
253     }
254 
255     /**
256      * Checks whether the given logging level (defined in {@link android.util.Log}) is loggable for
257      * this Log.
258      *
259      * @param level the logging level to be checked for being loggable
260      * @return true iff level is at the configured logging level or higher
261      */
isLoggable(int level)262     private boolean isLoggable(int level) {
263         return android.util.Log.isLoggable(mTAG, level);
264     }
265 
266     /**
267      * Returns the hex-String representation of the given byte[].
268      *
269      * @param data the byte[] to be represented
270      * @return the String representation of data
271      */
byteArrayToHexString(byte[] data)272     public static String byteArrayToHexString(byte[] data) {
273         if (data == null || data.length == 0) {
274             return "";
275         }
276 
277         StringBuilder sb = new StringBuilder();
278         for (byte b : data) {
279             sb.append(String.format(Locale.US, "%02X", b));
280         }
281         return sb.toString();
282     }
283 }
284