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