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