1 /*
2  * Copyright (C) 2016 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.server.wifi;
18 
19 import android.annotation.NonNull;
20 
21 import com.google.errorprone.annotations.CompileTimeConstant;
22 
23 import javax.annotation.CheckReturnValue;
24 
25 /**
26  * Provides an abstraction of logging back-ends.
27  *
28  * The abstraction is designed to
29  * a) minimize the cost of disabled log messages,
30  * b) allow callers to tag message parameters as containing sensitive
31  *    information,
32  * c) avoid the use of format codes, and
33  * d) easily support additional data types.
34  *
35  * Implementations of WifiLog may or may not be thread-safe.
36  * Implementations of LogMessage are expected _not_ to be thread-safe,
37  * as LogMessage instances are not expected to be shared between threads.
38  */
39 @SuppressWarnings("NonFinalCompileTimeConstant")  // See below.
40 public interface WifiLog {
41     // Explanation of SuppressWarnings above:
42     //
43     // We use @CompileTimeConstant to verify that our callers do not stringify
44     // arguments into the |format| parameter. And, by default, error-prone
45     // requires that CompileTimeConstant parameters are declared final.
46     //
47     // However, declaring an interface parameter as final has no effect, since
48     // classes implementing the interface are free to declare their parameters
49     // as non-final. Moreover, to avoid such confusing situations (interface says
50     // final, implementation does not), checkstyle rejects |final| qualification
51     // of method parameters in interface methods.
52     //
53     // To avoid making empty promises. we override error-prone's default behavior,
54     // and allow the CompileTimeConstant parameters to be non-final.
55 
56     char PLACEHOLDER = '%';
57 
58     // New-style API.
59     /**
60      * Allocate an error-level log message, which the caller will fill with
61      * additional parameters according to |format|. After filling the message
62      * with parameters, the caller must call flush(), to actually log the message.
63      *
64      * Error-level messages should be used when a malfunction has occurred,
65      * and the malfunction is likely to cause an externally visible problem.
66      * For example: we failed to initialize the Wifi interface.
67      *
68      * Typical usage is as follows:
69      *     WifiDevice() {
70      *         mLog = new LogcatLog("ModuleName");
71      *     }
72      *
73      *     void start() {
74      *         // ...
75      *         mLog.err("error % while starting interface %").c(errNum).c(ifaceName).flush();
76      *     }
77      *
78      *     void stop() {
79      *         // ...
80      *         mLog.err("error % while stopping interface %").c(errNum).c(ifaceName).flush();
81      *     }
82      */
83     @CheckReturnValue
84     @NonNull
err(@ompileTimeConstant @onNull String format)85     LogMessage err(@CompileTimeConstant @NonNull String format);
86 
87     /**
88      * Like {@link #err(String) err()}, except that a warning-level message is
89      * allocated.
90      *
91      * Warning-level messages should be used when a malfunction has occurred,
92      * but the malfunction is _unlikely_ to cause an externally visible problem
93      * on its own. For example: if we fail to start the debugging subsystem.
94      */
95     @CheckReturnValue
96     @NonNull
warn(@ompileTimeConstant @onNull String format)97     LogMessage warn(@CompileTimeConstant @NonNull String format);
98 
99     /**
100      * Like {@link #err(String) err()}, except that a info-level message is
101      * allocated.
102      *
103      * Info-level messages should be used to report progress or status messages
104      * that help understand the program's external behavior. For example: we
105      * might log an info message before initiating a Wifi association.
106      */
107     @CheckReturnValue
108     @NonNull
info(@ompileTimeConstant @onNull String format)109     LogMessage info(@CompileTimeConstant @NonNull String format);
110 
111     /**
112      * Like {@link #err(String) err()}, except:
113      * - a trace-level message is allocated
114      * - the log message is prefixed with the caller's name
115      *
116      * Trace-level messages should be used to report progress or status messages
117      * that help understand the program's internal behavior. For example:
118      * "invoked with verbose=%".
119      */
120     @CheckReturnValue
121     @NonNull
trace(@ompileTimeConstant @onNull String format)122     LogMessage trace(@CompileTimeConstant @NonNull String format);
123 
124     /**
125      * Like {@link #trace(String) trace(String)}, except that, rather than logging
126      * the immediate caller, the |numFramesToIgnore + 1|-th caller will be logged.
127      *
128      * E.g. if numFramesToIgnore == 1, then the caller's caller will be logged.
129      *
130      * Trace-level messages should be used to report progress or status messages
131      * that help understand the program's internal behavior. For example:
132      * "invoked with verbose=%".
133      */
134     @CheckReturnValue
135     @NonNull
trace(@onNull String format, int numFramesToIgnore)136     LogMessage trace(@NonNull String format, int numFramesToIgnore);
137 
138     /**
139      * Like {@link #err(String) err()}, except that a dump-level message is
140      * allocated.
141      *
142      * Dump-level messages should be used to report detailed internal state.
143      */
144     @CheckReturnValue
145     @NonNull
dump(@ompileTimeConstant @onNull String format)146     LogMessage dump(@CompileTimeConstant @NonNull String format);
147 
148     /**
149      * Log a warning using the default tag for this WifiLog instance. Mark
150      * the message as 'clean' (i.e. _not_ containing any sensitive data).
151      *
152      * NOTE: this method should only be used for literal strings. For messages with
153      * parameters, use err().
154      *
155      * @param msg the message to be logged
156      */
eC(@ompileTimeConstant String msg)157     void eC(@CompileTimeConstant String msg);
158 
159     /**
160      * Like {@link #eC(String)} eC()}, except that a warning-level message
161      * is logged.
162      */
wC(@ompileTimeConstant String msg)163     void wC(@CompileTimeConstant String msg);
164 
165     /**
166      * Like {@link #eC(String)} eC()}, except that an info-level message
167      * is logged.
168      */
iC(@ompileTimeConstant String msg)169     void iC(@CompileTimeConstant String msg);
170 
171     /**
172      * Like {@link #eC(String)} eC()}, except that a trace-level message
173      * is logged.
174      */
tC(@ompileTimeConstant String msg)175     void tC(@CompileTimeConstant String msg);
176 
177     /**
178      * Note: dC() is deliberately omitted, as "dumping" is inherently at
179      * odds with the intention that the caller pass in a literal string.
180      */
181 
182     /**
183      * Represents a single log message.
184      *
185      * Implementations are expected _not_ to be thread-safe.
186      */
187     interface LogMessage {
188         /**
189          * Replace the first available placeholder in this LogMessage's format
190          * with the specified value. Mark the value as 'raw', to inform the
191          * logging daemon that the value may contain sensitive data.
192          *
193          * @return |this|, to allow chaining of calls
194          */
195         @CheckReturnValue
196         @NonNull
r(String value)197         LogMessage r(String value);
198 
199         /**
200          * Like {@link #r(String) r()}, except that the value is marked
201          * as 'clean', to inform the logging daemon that the value does _not_
202          * contain sensitive data.
203          */
204         @CheckReturnValue
205         @NonNull
c(String value)206         LogMessage c(String value);
207 
208         /**
209          * Like {@link #c(String) c(String)}, except that the value is a long.
210          */
211         @CheckReturnValue
212         @NonNull
c(long value)213         LogMessage c(long value);
214 
215         /**
216          * Like {@link #c(String) c(String)}, except that the value is a char.
217          */
218         @CheckReturnValue
219         @NonNull
c(char value)220         LogMessage c(char value);
221 
222         /**
223          * Like {@link #c(String) c(String)}, except that the value is a boolean.
224          */
225         @CheckReturnValue
226         @NonNull
c(boolean value)227         LogMessage c(boolean value);
228 
229         /**
230          * Write this LogMessage to the logging daemon. Writing the
231          * message is best effort. More specifically:
232          * 1) The operation is non-blocking. If we’re unable to write
233          *    the log message to the IPC channel, the message is
234          *    dropped silently.
235          * 2) If the number of |value|s provided exceeds the number of
236          *    placeholders in the |format|, then extraneous |value|s
237          *    are silently dropped.
238          * 3) If the number of placeholders in the |format| exceeds
239          *    the number of |value|s provided, the message is sent to
240          *    the logging daemon without generating an Exception.
241          * 4) If the total message length exceeds the logging
242          *    protocol’s maximum message length, the message is
243          *    silently truncated.
244          */
flush()245         void flush();
246     }
247 
248     // Legacy API.
249     /**
250      * Log an error using the default tag for this WifiLog instance.
251      * @param msg the message to be logged
252      * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
253      */
e(String msg)254     void e(String msg);
255 
256     /**
257      * Log a warning using the default tag for this WifiLog instance.
258      * @param msg the message to be logged
259      * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
260      */
w(String msg)261     void w(String msg);
262 
263     /**
264      * Log an informational message using the default tag for this WifiLog instance.
265      * @param msg the message to be logged
266      * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
267      */
i(String msg)268     void i(String msg);
269 
270     /**
271      * Log a debug message using the default tag for this WifiLog instance.
272      * @param msg the message to be logged
273      * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
274      */
d(String msg)275     void d(String msg);
276 
277     /**
278      * Log a verbose message using the default tag for this WifiLog instance.
279      * @param msg the message to be logged
280      * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
281      */
v(String msg)282     void v(String msg);
283 }
284