/*
 * Copyright (C) 2020 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.
 */

#include "chre/platform/shared/log_buffer_manager.h"

#include "chre/core/event_loop_manager.h"
#include "chre/platform/shared/bt_snoop_log.h"
#include "chre/platform/shared/generated/host_messages_generated.h"
#include "chre/util/lock_guard.h"

void chrePlatformLogToBuffer(chreLogLevel chreLogLevel, const char *format,
                             ...) {
  va_list args;
  va_start(args, format);
  if (chre::LogBufferManagerSingleton::isInitialized()) {
    chre::LogBufferManagerSingleton::get()->logVa(chreLogLevel, format, args);
  }
  va_end(args);
}

void chrePlatformEncodedLogToBuffer(chreLogLevel level, const uint8_t *msg,
                                    size_t msgSize) {
  if (chre::LogBufferManagerSingleton::isInitialized()) {
    chre::LogBufferManagerSingleton::get()->logEncoded(level, msg, msgSize);
  }
}

void chrePlatformBtSnoopLog(BtSnoopDirection direction, const uint8_t *buffer,
                            size_t size) {
  chre::LogBufferManagerSingleton::get()->logBtSnoop(direction, buffer, size);
}

namespace chre {

using LogType = fbs::LogType;

void LogBufferManager::onLogsReady() {
  LockGuard<Mutex> lockGuard(mFlushLogsMutex);
  if (!mLogFlushToHostPending) {
    if (EventLoopManagerSingleton::isInitialized() &&
        EventLoopManagerSingleton::get()
            ->getEventLoop()
            .getPowerControlManager()
            .hostIsAwake()) {
      mLogFlushToHostPending = true;
      mSendLogsToHostCondition.notify_one();
    }
  } else {
    mLogsBecameReadyWhileFlushPending = true;
  }
}

void LogBufferManager::flushLogs() {
  onLogsReady();
}

void LogBufferManager::onLogsSentToHost(bool success) {
  LockGuard<Mutex> lockGuard(mFlushLogsMutex);
  onLogsSentToHostLocked(success);
}

void LogBufferManager::startSendLogsToHostLoop() {
  LockGuard<Mutex> lockGuard(mFlushLogsMutex);
  // TODO(b/181871430): Allow this loop to exit for certain platforms
  while (true) {
    while (!mLogFlushToHostPending) {
      mSendLogsToHostCondition.wait(mFlushLogsMutex);
    }
    bool logWasSent = false;
    if (EventLoopManagerSingleton::get()
            ->getEventLoop()
            .getPowerControlManager()
            .hostIsAwake()) {
      auto &hostCommsMgr =
          EventLoopManagerSingleton::get()->getHostCommsManager();
      preSecondaryBufferUse();
      if (mSecondaryLogBuffer.getBufferSize() == 0) {
        // TODO (b/184178045): Transfer logs into the secondary buffer from
        // primary if there is room.
        mPrimaryLogBuffer.transferTo(mSecondaryLogBuffer);
      }
      // If the primary buffer was not flushed to the secondary buffer then set
      // the flag that will cause sendLogsToHost to be run again after
      // onLogsSentToHost has been called and the secondary buffer has been
      // cleared out.
      if (mPrimaryLogBuffer.getBufferSize() > 0) {
        mLogsBecameReadyWhileFlushPending = true;
      }
      if (mSecondaryLogBuffer.getBufferSize() > 0) {
        mNumLogsDroppedTotal += mSecondaryLogBuffer.getNumLogsDropped();
        mFlushLogsMutex.unlock();
        hostCommsMgr.sendLogMessageV2(mSecondaryLogBuffer.getBufferData(),
                                      mSecondaryLogBuffer.getBufferSize(),
                                      mNumLogsDroppedTotal);
        logWasSent = true;
        mFlushLogsMutex.lock();
      }
    }
    if (!logWasSent) {
      onLogsSentToHostLocked(false);
    }
  }
}

void LogBufferManager::log(chreLogLevel logLevel, const char *formatStr, ...) {
  va_list args;
  va_start(args, formatStr);
  logVa(logLevel, formatStr, args);
  va_end(args);
}

uint32_t LogBufferManager::getTimestampMs() {
  uint64_t timeNs = SystemTime::getMonotonicTime().toRawNanoseconds();
  return static_cast<uint32_t>(timeNs / kOneMillisecondInNanoseconds);
}

void LogBufferManager::bufferOverflowGuard(size_t logSize, LogType type) {
  if (type == LogType::STRING) {
    // Add one byte because of the null terminator added at the end.
    logSize = logSize + LogBuffer::kStringLogOverhead;
  } else if (type == LogType::TOKENIZED) {
    logSize = logSize + LogBuffer::kTokenizedLogOffset;
  } else if (type == LogType::BLUETOOTH) {
    logSize = logSize + LogBuffer::kBtSnoopLogOffset;
  }
  if (mPrimaryLogBuffer.logWouldCauseOverflow(logSize)) {
    LockGuard<Mutex> lockGuard(mFlushLogsMutex);
    if (!mLogFlushToHostPending) {
      preSecondaryBufferUse();
      mPrimaryLogBuffer.transferTo(mSecondaryLogBuffer);
    }
  }
}

void LogBufferManager::logVa(chreLogLevel logLevel, const char *formatStr,
                             va_list args) {
  // Copy the va_list before getting size from vsnprintf so that the next
  // argument that will be accessed in buffer.handleLogVa is the starting one.
  va_list getSizeArgs;
  va_copy(getSizeArgs, args);
  size_t logSize = vsnprintf(nullptr, 0, formatStr, getSizeArgs);
  va_end(getSizeArgs);
  bufferOverflowGuard(logSize, LogType::STRING);
  mPrimaryLogBuffer.handleLogVa(chreToLogBufferLogLevel(logLevel),
                                getTimestampMs(), formatStr, args);
}

void LogBufferManager::logBtSnoop(BtSnoopDirection direction,
                                  const uint8_t *buffer, size_t size) {
#ifdef CHRE_BLE_SUPPORT_ENABLED
  bufferOverflowGuard(size, LogType::BLUETOOTH);
  mPrimaryLogBuffer.handleBtLog(direction, getTimestampMs(), buffer, size);
#else
  UNUSED_VAR(direction);
  UNUSED_VAR(buffer);
  UNUSED_VAR(size);
#endif  // CHRE_BLE_SUPPORT_ENABLED
}

void LogBufferManager::logEncoded(chreLogLevel logLevel,
                                  const uint8_t *encodedLog,
                                  size_t encodedLogSize) {
  bufferOverflowGuard(encodedLogSize, LogType::TOKENIZED);
  mPrimaryLogBuffer.handleEncodedLog(chreToLogBufferLogLevel(logLevel),
                                     getTimestampMs(), encodedLog,
                                     encodedLogSize);
}

LogBufferLogLevel LogBufferManager::chreToLogBufferLogLevel(
    chreLogLevel chreLogLevel) {
  switch (chreLogLevel) {
    case CHRE_LOG_ERROR:
      return LogBufferLogLevel::ERROR;
    case CHRE_LOG_WARN:
      return LogBufferLogLevel::WARN;
    case CHRE_LOG_INFO:
      return LogBufferLogLevel::INFO;
    default:  // CHRE_LOG_DEBUG
      return LogBufferLogLevel::DEBUG;
  }
}

void LogBufferManager::onLogsSentToHostLocked(bool success) {
  if (success) {
    mSecondaryLogBuffer.reset();
  }
  // If there is a failure to send a log through do not try to send another
  // one to avoid an infinite loop occurring
  mLogFlushToHostPending = mLogsBecameReadyWhileFlushPending && success;
  mLogsBecameReadyWhileFlushPending = false;
  if (mLogFlushToHostPending) {
    mSendLogsToHostCondition.notify_one();
  }
}

//! Explicitly instantiate the EventLoopManagerSingleton to reduce codesize.
template class Singleton<LogBufferManager>;

}  // namespace chre
