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

/**
 * The CameraService watchdog is used to help detect bad states in the
 * Camera HAL. The threadloop uses cycle counters, assigned to each calling
 * thread, to monitor the elapsing time and kills the process when the
 * expected duration has exceeded.
 * Notes on multi-threaded behaviors:
 *    - The threadloop is blocked/paused when there are no calls being
 *   monitored (when the TID cycle to counter map is empty).
 *   - The start and stop functions handle simultaneous call monitoring
 *   and single call monitoring differently. See function documentation for
 *   more details.
 * To disable/enable:
 *   - adb shell cmd media.camera set-cameraservice-watchdog [0/1]
 */
#pragma once
#include <chrono>
#include <thread>
#include <time.h>
#include <utils/Thread.h>
#include <utils/Log.h>
#include <unordered_map>

#include "utils/CameraServiceProxyWrapper.h"

// Used to wrap the call of interest in start and stop calls
#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
        watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__, cycles, cycleLength);

// Default cycles and cycle length values used to calculate permitted elapsed time
const static size_t   kMaxCycles     = 650;
const static uint32_t kCycleLengthMs = 100;

namespace android {

class CameraServiceWatchdog : public Thread {

struct MonitoredFunction {
    uint32_t cycles;
    std::string functionName;
};

public:
    explicit CameraServiceWatchdog(const std::string &cameraId,
            std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
                    mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
                    mCycleLengthMs(kCycleLengthMs), mEnabled(true),
                    mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};

    explicit CameraServiceWatchdog (const std::string &cameraId, size_t maxCycles,
            uint32_t cycleLengthMs, bool enabled,
            std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
                    mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
                    mCycleLengthMs(cycleLengthMs), mEnabled(enabled),
                    mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};

    virtual ~CameraServiceWatchdog() {};

    virtual void requestExit();

    /** Enables/disables the watchdog */
    void setEnabled(bool enable);

    /** Used to wrap monitored calls in start and stop functions using custom timer values */
    template<typename T>
    auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles,
            uint32_t cycleLength) {
        decltype(func()) res;

        if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
            // Create another instance of the watchdog to prevent disruption
            // of timer for current monitored calls

            // Lock for mEnabled
            mEnabledLock.lock();
            sp<CameraServiceWatchdog> tempWatchdog = new CameraServiceWatchdog(
                    mCameraId, cycles, cycleLength, mEnabled, mCameraServiceProxyWrapper);
            mEnabledLock.unlock();

            status_t status = tempWatchdog->run("CameraServiceWatchdog");
            if (status != OK) {
                ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status);
                res = watchThread(func, tid, functionName);
                return res;
            }

            res = tempWatchdog->watchThread(func, tid, functionName);
            tempWatchdog->requestExit();
            tempWatchdog.clear();
        } else {
            // If custom timer values are equivalent to set class timer values, use
            // current thread
            res = watchThread(func, tid, functionName);
        }

        return res;
    }

    /** Used to wrap monitored calls in start and stop functions using class timer values */
    template<typename T>
    auto watchThread(T func, uint32_t tid, const char* functionName) {
        decltype(func()) res;
        AutoMutex _l(mEnabledLock);

        if (mEnabled) {
            start(tid, functionName);
            res = func();
            stop(tid);
        } else {
            res = func();
        }

        return res;
    }

private:

    /**
     * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
     * start() unblocks and starts the watchdog
     */
    void start(uint32_t tid, const char* functionName);

    /**
     * If there are no calls left to be monitored, stop blocks/pauses threadloop
     * otherwise stop() erases the cycle counter to end watchdog for the calling thread
     */
    void stop(uint32_t tid);

    std::string getAbortMessage(const std::string& functionName);

    virtual bool    threadLoop();

    Mutex           mWatchdogLock;      // Lock for condition variable
    Mutex           mEnabledLock;       // Lock for enabled status
    Condition       mWatchdogCondition; // Condition variable for stop/start
    std::string     mCameraId;          // Camera Id the watchdog belongs to
    bool            mPause;             // True if tid map is empty
    uint32_t        mMaxCycles;         // Max cycles
    uint32_t        mCycleLengthMs;     // Length of time elapsed per cycle
    bool            mEnabled;           // True if watchdog is enabled

    std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;

    std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
                                                             // which retrieves the num of cycles
                                                             // and name of the function
};

}   // namespace android
