content: /*
   * Copyright (C) 2016 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.server.wifi;
  
  import android.annotation.NonNull;
  
  import com.google.errorprone.annotations.CompileTimeConstant;
  
  import javax.annotation.CheckReturnValue;
  
  /**
   * Provides an abstraction of logging back-ends.
   *
   * The abstraction is designed to
   * a) minimize the cost of disabled log messages,
   * b) allow callers to tag message parameters as containing sensitive
   *    information,
   * c) avoid the use of format codes, and
   * d) easily support additional data types.
   *
   * Implementations of WifiLog may or may not be thread-safe.
   * Implementations of LogMessage are expected _not_ to be thread-safe,
   * as LogMessage instances are not expected to be shared between threads.
   */
  @SuppressWarnings("NonFinalCompileTimeConstant")  // See below.
  public interface WifiLog {
      // Explanation of SuppressWarnings above:
      //
      // We use @CompileTimeConstant to verify that our callers do not stringify
      // arguments into the |format| parameter. And, by default, error-prone
      // requires that CompileTimeConstant parameters are declared final.
      //
      // However, declaring an interface parameter as final has no effect, since
      // classes implementing the interface are free to declare their parameters
      // as non-final. Moreover, to avoid such confusing situations (interface says
      // final, implementation does not), checkstyle rejects |final| qualification
      // of method parameters in interface methods.
      //
      // To avoid making empty promises. we override error-prone's default behavior,
      // and allow the CompileTimeConstant parameters to be non-final.
  
      char PLACEHOLDER = '%';
  
      // New-style API.
      /**
       * Allocate an error-level log message, which the caller will fill with
       * additional parameters according to |format|. After filling the message
       * with parameters, the caller must call flush(), to actually log the message.
       *
       * Error-level messages should be used when a malfunction has occurred,
       * and the malfunction is likely to cause an externally visible problem.
       * For example: we failed to initialize the Wifi interface.
       *
       * Typical usage is as follows:
       *     WifiDevice() {
       *         mLog = new LogcatLog("ModuleName");
       *     }
       *
       *     void start() {
       *         // ...
       *         mLog.err("error % while starting interface %").c(errNum).c(ifaceName).flush();
       *     }
       *
       *     void stop() {
       *         // ...
       *         mLog.err("error % while stopping interface %").c(errNum).c(ifaceName).flush();
       *     }
       */
      @CheckReturnValue
      @NonNull
      LogMessage err(@CompileTimeConstant @NonNull String format);
  
      /**
       * Like {@link #err(String) err()}, except that a warning-level message is
       * allocated.
       *
       * Warning-level messages should be used when a malfunction has occurred,
       * but the malfunction is _unlikely_ to cause an externally visible problem
       * on its own. For example: if we fail to start the debugging subsystem.
       */
      @CheckReturnValue
      @NonNull
      LogMessage warn(@CompileTimeConstant @NonNull String format);
  
      /**
       * Like {@link #err(String) err()}, except that a info-level message is
       * allocated.
       *
       * Info-level messages should be used to report progress or status messages
       * that help understand the program's external behavior. For example: we
       * might log an info message before initiating a Wifi association.
       */
      @CheckReturnValue
      @NonNull
      LogMessage info(@CompileTimeConstant @NonNull String format);
  
      /**
       * Like {@link #err(String) err()}, except:
       * - a trace-level message is allocated
       * - the log message is prefixed with the caller's name
       *
       * Trace-level messages should be used to report progress or status messages
       * that help understand the program's internal behavior. For example:
       * "invoked with verbose=%".
       */
      @CheckReturnValue
      @NonNull
      LogMessage trace(@CompileTimeConstant @NonNull String format);
  
      /**
       * Like {@link #trace(String) trace(String)}, except that, rather than logging
       * the immediate caller, the |numFramesToIgnore + 1|-th caller will be logged.
       *
       * E.g. if numFramesToIgnore == 1, then the caller's caller will be logged.
       *
       * Trace-level messages should be used to report progress or status messages
       * that help understand the program's internal behavior. For example:
       * "invoked with verbose=%".
       */
      @CheckReturnValue
      @NonNull
      LogMessage trace(@NonNull String format, int numFramesToIgnore);
  
      /**
       * Like {@link #err(String) err()}, except that a dump-level message is
       * allocated.
       *
       * Dump-level messages should be used to report detailed internal state.
       */
      @CheckReturnValue
      @NonNull
      LogMessage dump(@CompileTimeConstant @NonNull String format);
  
      /**
       * Log a warning using the default tag for this WifiLog instance. Mark
       * the message as 'clean' (i.e. _not_ containing any sensitive data).
       *
       * NOTE: this method should only be used for literal strings. For messages with
       * parameters, use err().
       *
       * @param msg the message to be logged
       */
      void eC(@CompileTimeConstant String msg);
  
      /**
       * Like {@link #eC(String)} eC()}, except that a warning-level message
       * is logged.
       */
      void wC(@CompileTimeConstant String msg);
  
      /**
       * Like {@link #eC(String)} eC()}, except that an info-level message
       * is logged.
       */
      void iC(@CompileTimeConstant String msg);
  
      /**
       * Like {@link #eC(String)} eC()}, except that a trace-level message
       * is logged.
       */
      void tC(@CompileTimeConstant String msg);
  
      /**
       * Note: dC() is deliberately omitted, as "dumping" is inherently at
       * odds with the intention that the caller pass in a literal string.
       */
  
      /**
       * Represents a single log message.
       *
       * Implementations are expected _not_ to be thread-safe.
       */
      interface LogMessage {
          /**
           * Replace the first available placeholder in this LogMessage's format
           * with the specified value. Mark the value as 'raw', to inform the
           * logging daemon that the value may contain sensitive data.
           *
           * @return |this|, to allow chaining of calls
           */
          @CheckReturnValue
          @NonNull
          LogMessage r(String value);
  
          /**
           * Like {@link #r(String) r()}, except that the value is marked
           * as 'clean', to inform the logging daemon that the value does _not_
           * contain sensitive data.
           */
          @CheckReturnValue
          @NonNull
          LogMessage c(String value);
  
          /**
           * Like {@link #c(String) c(String)}, except that the value is a long.
           */
          @CheckReturnValue
          @NonNull
          LogMessage c(long value);
  
          /**
           * Like {@link #c(String) c(String)}, except that the value is a char.
           */
          @CheckReturnValue
          @NonNull
          LogMessage c(char value);
  
          /**
           * Like {@link #c(String) c(String)}, except that the value is a boolean.
           */
          @CheckReturnValue
          @NonNull
          LogMessage c(boolean value);
  
          /**
           * Write this LogMessage to the logging daemon. Writing the
           * message is best effort. More specifically:
           * 1) The operation is non-blocking. If we’re unable to write
           *    the log message to the IPC channel, the message is
           *    dropped silently.
           * 2) If the number of |value|s provided exceeds the number of
           *    placeholders in the |format|, then extraneous |value|s
           *    are silently dropped.
           * 3) If the number of placeholders in the |format| exceeds
           *    the number of |value|s provided, the message is sent to
           *    the logging daemon without generating an Exception.
           * 4) If the total message length exceeds the logging
           *    protocol’s maximum message length, the message is
           *    silently truncated.
           */
          void flush();
      }
  
      // Legacy API.
      /**
       * Log an error using the default tag for this WifiLog instance.
       * @param msg the message to be logged
       * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
       */
      void e(String msg);
  
      /**
       * Log a warning using the default tag for this WifiLog instance.
       * @param msg the message to be logged
       * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
       */
      void w(String msg);
  
      /**
       * Log an informational message using the default tag for this WifiLog instance.
       * @param msg the message to be logged
       * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
       */
      void i(String msg);
  
      /**
       * Log a debug message using the default tag for this WifiLog instance.
       * @param msg the message to be logged
       * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
       */
      void d(String msg);
  
      /**
       * Log a verbose message using the default tag for this WifiLog instance.
       * @param msg the message to be logged
       * TODO(b/30736737): Remove this method, once all code has migrated to alternatives.
       */
      void v(String msg);
  }
  