////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019-2023 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxchiofflinelogger.h
/// @brief Debug Print related defines
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CAMXCHIOFFLINELOGGER_H
#define CAMXCHIOFFLINELOGGER_H


// NOWHINE FILE PR007b: STL headers

#if defined (ANDROID)
#include "log.h"
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statvfs.h>

#define OFFLINELOG_ERROR(fmt, args...)   ALOGE("%s():%d " fmt "\n", __func__, __LINE__, ##args)
#define OFFLINELOG_WARN(fmt, args...)    ALOGW("%s():%d " fmt "\n", __func__, __LINE__, ##args)
#if OFFLINELOG_DEBUG
#define OFFLINELOG_INFO(fmt, args...)   ALOGI("%s():%d " fmt "\n", __func__, __LINE__, ##args)
#else
#define OFFLINELOG_INFO(fmt, args...)
#endif // OFFLINELOG_DEBUG

#if defined(__clang__) && defined(__has_attribute) && __has_attribute(no_sanitize)
#define OFFLINELOG_CFI_NO_SANITIZE  __attribute__((no_sanitize("cfi")))
#else
#define OFFLINELOG_CFI_NO_SANITIZE
#endif // defined(__clang__) && defined(__has_attribute) && __has_attribute(no_sanitize)

#else // (ANDROID)

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OFFLINELOG_ERROR(...)   printf(__VA_ARGS__)
#if OFFLINELOG_DEBUG
#define OFFLINELOG_INFO(...)    printf(__VA_ARGS__)
#else
#define OFFLINELOG_INFO(...)
#define OFFLINELOG_CFI_NO_SANITIZE
#endif // OFFLINELOG_DEBUG

#endif // (ANDROID)

#include <atomic>
#include <list>
#include <map>
#include <mutex>
#include <queue>
#include <shared_mutex>
#include <string>
#include <sstream>
#include <time.h>
#include <unistd.h>
#include <unordered_set>

#include "chiofflineloggerinterface.h"

#include "camxdefs.h"
#include "camxtypes.h"

CAMX_NAMESPACE_BEGIN

/// @brief Per thread queue data structure
///        being passed into offlinelogger container
struct PerLogThreadInfo
{
    BOOL           bNeedFlush;          ///< When queue reaches flush threshold, set this flag to true
    BOOL           bHasFileName;        ///< If this thread had already created file successfully
    UINT           threadID;            ///< Thread ID this info structure associated with
    INT            registerID;          ///< Queue ID registered within memory pool
    UINT           sessionCount;        ///< Session count corresponding to this buffer
    INT            segment;             ///< When filesize reaches threshold, plus this count
    UINT           numByteToWrite;      ///< The buffer size need to be written to file
    std::string    offlinelogFileName;  ///< Thread's unique filename for filesystem operation
    BOOL           bSegmentChanged;     ///< Indicate segment has been changed so the log file will not be updated any more
    UINT           currentLogSize;      ///< The log file size for the current local thread
};

/// @brief Per thread information data structure
///        being passed for tracking thread lifetime in offlinelogger
struct LifetimeThreadInfo
{
    UINT               threadID;          ///< Thread ID this info structure associated with
    INT                registerID;        ///< Memory container ID registered within offlinelogger
    BOOL               enableLoggerType;  ///< Offlinelogger enable flag
    OfflineLoggerType  loggerType;        ///< Offlinelogger type(eg, Binary/ASCII)

    // NOWHINE FILE CP003: C++ Structure(Structs with methods) used
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~LifetimeThreadInfo
    ///
    /// @brief  Destructor will be called while thread being killed
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ~LifetimeThreadInfo();
};

/// @brief Offlinelogger debug dump information

struct OfflineLoggerDumpInfo
{
    INT    dumpFileFd;                       ///< Offlinelogger dump file fd.
    FILE*  pOfflinelogLogFile;               ///< Offlinelogger dump file pointer.
    INT    currentCountForFwrite;            ///< Current count for fwrite for performance measurement
    FLOAT  averageFwriteTime;                ///< Offlinelogger debug dump average fwrite time
    FLOAT  elapsedFlushTimeMs;               ///< Offlinelogger debug dump flush time
    INT    totalFlushInLastSessionCount;     ///< Offlinelogger debug dump flush count in last session
    INT    totalSuccessRemoveFileCount;      ///< Offlinelogger debug dump clean up count success
    INT    totalFailRemoveFileCount;         ///< Offlinelogger debug dump clean up count failed
    INT    totalRequestMemoryCount;          ///< Offlinelogger debug dump request memory count
    UINT   lastTimeFlushCount;               ///< Offlinelogger debug dump last time flush count
    BOOL   bEnableDebugDump;                 ///< Offlinelogger debug dump enabled / disabled
    BOOL   bTriggerCleanUp;                  ///< Offlinelogger debug dump trigger cleanup
};

/// @brief Offlinelogger config information
typedef struct OfflineLoggerConfigInfo
{
    UINT maxPreAllocateQueue;       ///< Total memory buckets during boot up
    UINT maxDynamicAllocateQueue;   ///< Total memory buckets while dynamic allocate is needed
    UINT minBufferNumFlushCriteria; ///< Exceed this mem buckets will trigger flush
    UINT maxLocalBufferSize;        ///< Each memory bucket size (MB)
} OFFLINELOGGERCONFIGINFO;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Definations of Offlinelogger Configs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const OFFLINELOGGERCONFIGINFO OfflineloggerAscConfigInfo
{
    25,
    25,
    6,
    3145728
};

static const OFFLINELOGGERCONFIGINFO OfflineloggerBinaryConfigInfo
{
    25,
    25,
    12,
    3145728
};

static const OFFLINELOGGERCONFIGINFO OfflineloggerCoredumpTextConfigInfo
{
    0,
    60,
    50,
    3145728
};

static const OFFLINELOGGERCONFIGINFO OfflineloggerCoredumpBinaryConfigInfo
{
    0,
    2,
    1,
    3145728
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Offline logger
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class OfflineLogger
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The maximum length for a log file name
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT MaxTimeStampLength = 50;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The maximum log path length for a log
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT MaxPathLength = 128;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The refresh rate for the offline logger
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT ReFlushRateToFile = 200;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The maximum support different types of loggers
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT MaxSupportLoggerTypeCount = static_cast<UINT>(OfflineLoggerType::NUM_OF_TYPE);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetInstance
    ///
    /// @brief  Return the reference singleton instance of OfflineLogger based on different Offlinelogger type
    ///
    /// @param  type  Logger type
    ///
    /// @return OfflineLogger reference instance
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC static OfflineLogger* GetInstance(
        OfflineLoggerType type);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddLog
    ///
    /// @brief  User through the API to push the log to offlinelogger and store it into a log container
    ///
    /// @param  pLog    text to Android file system
    /// @param  logSize log size in bytes
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual CamxResult AddLog(
        const CHAR* pLog,
        UINT        logSize);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FlushLogToFile
    ///
    /// @brief  Pop the text log from offlinelogger`s text log container and write it to file system
    ///
    /// @param  forceFlush  force flush all text from log container to file
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult FlushLogToFile(
        BOOL forceFlush,
        BOOL backupLogFile);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RequestNewLogQueue
    ///
    /// @brief  local thread to require a new log container
    ///
    /// @param  rpNewQueue  pass local thread container pointer and assinged a new one by offlinelogger
    /// @param  tid         current local thread id
    /// @param  segment     local thread own its file segment count and notice to offlinelogger
    ///
    /// @return Queue ID registered within memory pool
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual INT RequestNewLogQueue(
        BYTE* &rpNewQueue,
        UINT  tid,
        INT   segment);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RequestFlushLogQueue
    ///
    /// @brief  local thread to request need to flush its log container
    ///
    /// @param  registerId       local thread ask offlinelogger for flush its container by passing the registerId
    /// @param  segmentChanged   local thread send if the segment has been changed
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID RequestFlushLogQueue(
       INT  registerId,
       BOOL segmentChanged);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NotifyCameraOpen
    ///
    /// @brief  Notify offlinelogger and trigger camera open event
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID NotifyCameraOpen();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NotifyCameraClose
    ///
    /// @brief  Notify offlinelogger and trigger camera close event
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID NotifyCameraClose();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DisableOfflinelogger
    ///
    /// @brief  Disable the offlinelogger
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID DisableOfflinelogger();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsEnableOfflinelogger
    ///
    /// @brief  Get the Enable/Disable status of offlinelogger
    ///
    /// @return enable/disable status of offlinelogger
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual BOOL IsEnableOfflinelogger();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetFlushTriggerLink
    ///
    /// @brief  Set the flush trigger thread signal function pointer
    ///
    /// @param  pConditionVar    Function pointer to handle flush
    ///
    /// @return result of this operation
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual BOOL SetFlushTriggerLink(
        PFNSIGNALOFFLINETHREAD pConditionVar);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetLogInfoMask
    ///
    /// @brief  This API will allow each copy of DebugPrint to fetch correct LogMask
    ///
    /// @return result of this operation
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual DebugLogInfo GetLogInfoMask();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetLogInfoMask
    ///
    /// @brief  This API will store CamX setting logmask to OfflineLogger
    ///
    /// @param  pNewLogInfo  Pointer to log info
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID SetLogInfoMask(
        DebugLogInfo* pNewLogInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSettingLink
    ///
    /// @brief  This API will get override setting from CHI API
    ///
    /// @return result of this operation
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual BOOL GetSettingLink();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetCleanupTriggerLink
    ///
    /// @brief  Set the clean up trigger thread signal function pointer
    ///
    /// @param  pConditionVar    Function pointer to handle clean up
    ///
    /// @return result of this operation
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual BOOL SetCleanupTriggerLink(
        PFNSIGNALOFFLINETHREAD pConditionVar);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RemoveOlderLogFiles
    ///
    /// @brief  Remove old offline log files
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID RemoveOlderLogFiles();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetCurrentSessionPrefixFilename
    ///
    /// @brief  Get current session pre-fix file name
    ///
    /// @return pre-fix file name and path
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual std::string GetCurrentSessionPrefixFilename();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetCoredumpPath
    ///
    /// @brief  Setting offline logging coredump path
    ///
    /// @param  pPath    coredump path
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual CamxResult SetCoredumpPath(
        const CHAR* pPath);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FlushLogBySeperateThread
    ///
    /// @brief  Flush log by seperate thread
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID FlushLogBySeperateThread();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EnableCoredump
    ///
    /// @brief  Enable offline logger of coredump instance for coredump mode
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID EnableCoredump();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DisableCoredump
    ///
    /// @brief  Disable offline logger of coredump instance for coredump mode
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID DisableCoredump();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsCoredumpEnabled
    ///
    /// @brief  Return offline logger for coredump mode
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual BOOL IsCoredumpEnabled();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetMultiPathModeOn
    ///
    /// @brief  Set coredump instance for multi-dump path mode
    //
    /// @param  isMultiPathMode    multiPath Mode
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID SetMultiPathMode(BOOL isMultiPathMode);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CleanupCoredumpMemory
    ///
    /// @brief  Cleanup the coredump memory pool
    ///
    /// @return void
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC virtual VOID CleanupMemoryPool();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEnableBackupLogWhileCrash
    ///
    /// @brief  Get if we need to backup log file while crash event happened
    ///
    /// @return TRUE if enable
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL GetEnableBackupLogWhileCrash();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetMinimumRequireForBackupLog
    ///
    /// @brief  Get Minimum requirement of device storage (MB) for backup log whenevr crash happened
    ///
    /// @return UINT
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual UINT GetMinimumRequireForBackupLog();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetAvailableSpace
    ///
    /// @brief  Get Available Filesystem Space by input path
    ///
    /// @param  pPath   Path to file system
    ///
    /// @return FLOAT if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual DOUBLE GetAvailableSpace(
        const CHAR* pPath);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSignal35TombstoneTriggered
    ///
    /// @brief  Check if offline logger has Signal35Tombstone been triggered
    ///
    /// @return TRUE if offline logger has Signal35Tombstone Triggered
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL GetSignal35TombstoneTriggered();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetSignal35TombstoneTriggered
    ///
    /// @brief  Set offline logger trigger Signal35Tombstone flag
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID SetSignal35TombstoneTriggered();

protected:

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OfflineLogger
    ///
    /// @brief  Constructor
    ///
    /// @param  type  Logger type
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    explicit OfflineLogger(
        OfflineLoggerType        type,
        const OFFLINELOGGERCONFIGINFO* pOfflinelogConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~OfflineLogger
    ///
    /// @brief  Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~OfflineLogger();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPrefixFilename
    ///
    /// @brief  Get current file name by current system timestamp
    ///
    /// @return full file name and path
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual std::string GetPrefixFilename();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetAllToDefaultValue
    ///
    /// @brief  Clear and set member to default value
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID SetAllToDefaultValue();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AllocateLogQueueMemPool
    ///
    /// @brief  numOfAllocateAllocate total number of memory buckets to allocate
    /// @brief  sizeOfAllocate        the size of each memory buckets to allocate
    ///
    /// @return TRUE if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL AllocateLogQueueMemPool(UINT numOfAllocate, UINT sizeOfAllocate);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetCurrentTime
    ///
    /// @brief  Get Current System Timer for debug purpose
    ///
    /// @return string if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual std::string GetCurrentTime();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BackupRecentModifyLog
    ///
    /// @brief  Backup log if crash event happened
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult BackupRecentModifyLog();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GenerateLogFileNameByOfflineLoggerType
    ///
    /// @brief  Generate offline logging file name by different offline logger type
    ///
    /// @return string if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual std::string GenerateLogFileNameByOfflineLoggerType(std::vector<PerLogThreadInfo>::iterator* it);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MonitorFileSystemHealth
    ///
    /// @brief  Calculate average time of the fwrite
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult MonitorFileSystemHealth(FLOAT fileWritingTime);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DumpCurrentOfflineLogStatus
    ///
    /// @brief  Dump offlinelogger status to file
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult DumpCurrentOfflineLogStatus();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DPrintF
    ///
    /// @brief  Write formatted data from variable argument list to sized buffer
    ///
    /// @param  fd       File descriptor to print to
    /// @param  pFormat  Format string, printf style
    /// @param  ...      Parameters required by format
    ///
    /// @return Number of characters written
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual INT DPrintF(
        INT         fd,
        const CHAR* pFormat,
        ...);

    static thread_local BYTE* s_pThreadLocalLogBuffer[MaxSupportLoggerTypeCount];  ///< Log buffer container
    static thread_local INT   s_threadLocalQueuePoolId[MaxSupportLoggerTypeCount]; ///< Buffer container register id
    static thread_local UINT  s_threadLocalSessionCnt[MaxSupportLoggerTypeCount];  ///< Camera reopen count
    static thread_local UINT  s_threadLocalSegmentCnt[MaxSupportLoggerTypeCount];  ///< Log segment for current thread
    static thread_local UINT  s_threadLocalLogSize[MaxSupportLoggerTypeCount];     ///< Log size for current thread
    static thread_local UINT  s_threadLocalLogCurPos[MaxSupportLoggerTypeCount];   ///< Current buffer cursor location
    static thread_local BOOL  s_threadLocalFlushDone[MaxSupportLoggerTypeCount];   ///< To store if force flush happened
    BOOL                      m_enableLoggerType[MaxSupportLoggerTypeCount];       ///< Enable status for each logger type
    static thread_local LifetimeThreadInfo s_threadLocalLifeTime[MaxSupportLoggerTypeCount]; ///< Tracking for thread lifetime

    std::vector<BYTE*>              m_memoryLogPool;               ///< log container memory pool
    std::vector<PerLogThreadInfo>   m_perLogInfoPool;              ///< Each thread register pool
    std::queue<INT>                 m_availableQueueIdPool;        ///< Available memory id pool
    std::queue<INT>                 m_availableRegisterIdPool;     ///< Available registered id for log container
    std::queue<INT>                 m_registerIdFlushOrderQueue;   ///< Queue to track flush order, so timestamp will be sorted
    std::list<std::string>          m_recentModifyFileName;        ///< Maintain a list to record recently modify log filename
    std::unordered_set<std::string> m_nonDuplicateFileName;        ///< Maintain a set for no duplicate file name
    std::list<FLOAT>                m_monitorFileSystemTime;       ///< Maintain a list to monitor file system performance

    std::string               m_offlinelogPreFileName;            ///< Pre-filename for offlinelog
    std::string               m_offlinelogPreFileNameWithoutDir;  ///< Pre-filename with no prefix directory for offlinelog
    std::string               m_offlinelogPreLogTypeName;         ///< Pre-logType for offlinelog, eg:ASCII/Binary
    std::string               m_offlinelogRecentFolderName;       ///< Recent foldername for offlinelog
    BOOL                      m_offlinelogHasPreFileName;         ///< The flag for pre-filename created
    OfflineLoggerStatus       m_offlinelogStatus;                 ///< Offlinelogger status
    OfflineLoggerType         m_offlinelogType;                   ///< Offlinelogger type(eg, Binary/ASCII)
    UINT                      m_sessionCount;                     ///< Camera reopen count
    BOOL                      m_forceFlushDone;                   ///< Force flush done flag
    UINT                      m_needFlushThreadCount;             ///< Count of threads needing flush
    FLOAT                     m_totalFlushLogSize;                ///< Total log size flush to file since boot-up (Unit: MB)
    struct DebugLogInfo       m_debugLogInfo;                     ///< Store CamX setting logmask
    static std::mutex         m_pOfflineLoggerLock;             ///< Mutex to protect queue internal thread state
    static std::shared_mutex  m_pThreadLock;                      ///< Mutex to protect the critical section while closing camera
    static std::atomic_bool   m_pThreadGuard;                     ///< A guard if in the closing camera stage, no thead can addlog
    UINT                      m_maxLogFileNumBackupWhileCrash;    ///< Max num of log files need to be backup while crash event
    UINT                      m_MinBackupRequire;                 ///< Minimum requirement of device storage for backup log
    BOOL                      m_enableBackupLog;                  ///< Enable backup log while crash event happened
    std::string               m_coredumpPath;                     ///< Coredump path
    std::string               m_coredumpMultiPath;                ///< Coredump multi-path
    BOOL                      m_coredumpMode;                     ///< Coredump mode
    BOOL                      m_coredumpMultiPathMode;            ///< Coredump multi-path mode for METADATA/IFE dump
    OfflineLoggerDumpInfo     m_offlinelogDumpInfo;               ///< Offlinelogger dump information
    UINT                      m_concurrentCameraCount[MaxSupportLoggerTypeCount];  ///< Count the concurrent camera number
    BOOL                      m_signal35TombstoneTriggered;       ///< debug signal 35 has been triggered once

    std::list<PerLogThreadInfo>    m_oldSessionsFileList;         ///< Older sessions log file pool
    std::list<PerLogThreadInfo>    m_curRemovableFileList;        ///< Current session removable log file pool
    std::list<PerLogThreadInfo>    m_curBusyFileList;             ///< Current session busy and non-removable file pool
    std::map<UINT, INT>            m_writingFileThreadMap;        ///< Current writing thread pool
    UINT32                         m_maxTotalLogSize;             ///< Maximum total log size threshold

    const OFFLINELOGGERCONFIGINFO* m_pOfflineloggerConfig;        ///< Offline logger configuration

    /* Below static variables are specifically exported as they are accessed by client which calls inline
       function GetInstance() that uses these static member variables requiring their symbol*/
    CAMX_VISIBILITY_PUBLIC static BOOL         s_isInitValid;     ///< whether the Offlinelogger singleton is in a valid state

    PFNSIGNALOFFLINETHREAD    m_pSignalFlushTriggerThread;        ///< Function pointer to signal flush trigger thread
    PFNSIGNALOFFLINETHREAD    m_pSignalCleanupTriggerThread;      ///< Function pointer to signal cleanup trigger thread

private:

    /// Do not support the copy constructor or assignment operator
    OfflineLogger(const OfflineLogger& rOfflineLogger)             = delete;
    OfflineLogger& operator= (const OfflineLogger& rOfflineLogger) = delete;
};

CAMX_NAMESPACE_END
#endif // CAMXCHIOFFLINELOGGER_H
