Loading services/camera/libcameraservice/CameraServiceWatchdog.cpp +22 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define LOG_TAG "CameraServiceWatchdog" #include "CameraServiceWatchdog.h" #include "android/set_abort_message.h" #include "utils/CameraServiceProxyWrapper.h" namespace android { Loading @@ -36,12 +37,15 @@ bool CameraServiceWatchdog::threadLoop() { AutoMutex _l(mWatchdogLock); for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) { for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) { uint32_t currentThreadId = it->first; tidToCycleCounterMap[currentThreadId]++; mTidMap[currentThreadId].cycles++; if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) { if (mTidMap[currentThreadId].cycles >= mMaxCycles) { std::string abortMessage = getAbortMessage(getpid(), currentThreadId, mTidMap[currentThreadId].functionName); android_set_abort_message(abortMessage.c_str()); ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(), currentThreadId); mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/, Loading @@ -56,13 +60,20 @@ bool CameraServiceWatchdog::threadLoop() return true; } std::string CameraServiceWatchdog::getAbortMessage(int pid, int tid, std::string functionName) { std::string res = "CameraServiceWatchdog triggering abort during " + functionName + " | pid: " + std::to_string(pid) + " tid: " + std::to_string(tid); return res; } void CameraServiceWatchdog::requestExit() { Thread::requestExit(); AutoMutex _l(mWatchdogLock); tidToCycleCounterMap.clear(); mTidMap.clear(); if (mPause) { mPause = false; Loading @@ -85,18 +96,21 @@ void CameraServiceWatchdog::stop(uint32_t tid) { AutoMutex _l(mWatchdogLock); tidToCycleCounterMap.erase(tid); mTidMap.erase(tid); if (tidToCycleCounterMap.empty()) { if (mTidMap.empty()) { mPause = true; } } void CameraServiceWatchdog::start(uint32_t tid) void CameraServiceWatchdog::start(uint32_t tid, const char* functionName) { AutoMutex _l(mWatchdogLock); tidToCycleCounterMap[tid] = 0; MonitoredFunction monitoredFunction = {}; monitoredFunction.cycles = 0; monitoredFunction.functionName = functionName; mTidMap[tid] = monitoredFunction; if (mPause) { mPause = false; Loading services/camera/libcameraservice/CameraServiceWatchdog.h +20 −10 Original line number Diff line number Diff line Loading @@ -40,9 +40,9 @@ #include "utils/CameraServiceProxyWrapper.h" // Used to wrap the call of interest in start and stop calls #define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid()) #define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__) #define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \ watchThread([&]() { return toMonitor;}, gettid(), 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 = 100; Loading @@ -52,6 +52,11 @@ namespace android { class CameraServiceWatchdog : public Thread { struct MonitoredFunction { uint32_t cycles; std::string functionName; }; public: explicit CameraServiceWatchdog(const String8 &cameraId, std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) : Loading @@ -75,7 +80,8 @@ public: /** Used to wrap monitored calls in start and stop functions using custom timer values */ template<typename T> auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) { auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles, uint32_t cycleLength) { decltype(func()) res; if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) { Loading @@ -91,17 +97,17 @@ public: status_t status = tempWatchdog->run("CameraServiceWatchdog"); if (status != OK) { ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status); res = watchThread(func, tid); res = watchThread(func, tid, functionName); return res; } res = tempWatchdog->watchThread(func, tid); 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); res = watchThread(func, tid, functionName); } return res; Loading @@ -109,12 +115,12 @@ public: /** Used to wrap monitored calls in start and stop functions using class timer values */ template<typename T> auto watchThread(T func, uint32_t tid) { auto watchThread(T func, uint32_t tid, const char* functionName) { decltype(func()) res; AutoMutex _l(mEnabledLock); if (mEnabled) { start(tid); start(tid, functionName); res = func(); stop(tid); } else { Loading @@ -130,7 +136,7 @@ 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); void start(uint32_t tid, const char* functionName); /** * If there are no calls left to be monitored, stop blocks/pauses threadloop Loading @@ -138,6 +144,8 @@ private: */ void stop(uint32_t tid); std::string getAbortMessage(int pid, int tid, std::string functionName); virtual bool threadLoop(); Mutex mWatchdogLock; // Lock for condition variable Loading @@ -151,7 +159,9 @@ private: std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper; std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map 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 Loading
services/camera/libcameraservice/CameraServiceWatchdog.cpp +22 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define LOG_TAG "CameraServiceWatchdog" #include "CameraServiceWatchdog.h" #include "android/set_abort_message.h" #include "utils/CameraServiceProxyWrapper.h" namespace android { Loading @@ -36,12 +37,15 @@ bool CameraServiceWatchdog::threadLoop() { AutoMutex _l(mWatchdogLock); for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) { for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) { uint32_t currentThreadId = it->first; tidToCycleCounterMap[currentThreadId]++; mTidMap[currentThreadId].cycles++; if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) { if (mTidMap[currentThreadId].cycles >= mMaxCycles) { std::string abortMessage = getAbortMessage(getpid(), currentThreadId, mTidMap[currentThreadId].functionName); android_set_abort_message(abortMessage.c_str()); ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(), currentThreadId); mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/, Loading @@ -56,13 +60,20 @@ bool CameraServiceWatchdog::threadLoop() return true; } std::string CameraServiceWatchdog::getAbortMessage(int pid, int tid, std::string functionName) { std::string res = "CameraServiceWatchdog triggering abort during " + functionName + " | pid: " + std::to_string(pid) + " tid: " + std::to_string(tid); return res; } void CameraServiceWatchdog::requestExit() { Thread::requestExit(); AutoMutex _l(mWatchdogLock); tidToCycleCounterMap.clear(); mTidMap.clear(); if (mPause) { mPause = false; Loading @@ -85,18 +96,21 @@ void CameraServiceWatchdog::stop(uint32_t tid) { AutoMutex _l(mWatchdogLock); tidToCycleCounterMap.erase(tid); mTidMap.erase(tid); if (tidToCycleCounterMap.empty()) { if (mTidMap.empty()) { mPause = true; } } void CameraServiceWatchdog::start(uint32_t tid) void CameraServiceWatchdog::start(uint32_t tid, const char* functionName) { AutoMutex _l(mWatchdogLock); tidToCycleCounterMap[tid] = 0; MonitoredFunction monitoredFunction = {}; monitoredFunction.cycles = 0; monitoredFunction.functionName = functionName; mTidMap[tid] = monitoredFunction; if (mPause) { mPause = false; Loading
services/camera/libcameraservice/CameraServiceWatchdog.h +20 −10 Original line number Diff line number Diff line Loading @@ -40,9 +40,9 @@ #include "utils/CameraServiceProxyWrapper.h" // Used to wrap the call of interest in start and stop calls #define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid()) #define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__) #define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \ watchThread([&]() { return toMonitor;}, gettid(), 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 = 100; Loading @@ -52,6 +52,11 @@ namespace android { class CameraServiceWatchdog : public Thread { struct MonitoredFunction { uint32_t cycles; std::string functionName; }; public: explicit CameraServiceWatchdog(const String8 &cameraId, std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) : Loading @@ -75,7 +80,8 @@ public: /** Used to wrap monitored calls in start and stop functions using custom timer values */ template<typename T> auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) { auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles, uint32_t cycleLength) { decltype(func()) res; if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) { Loading @@ -91,17 +97,17 @@ public: status_t status = tempWatchdog->run("CameraServiceWatchdog"); if (status != OK) { ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status); res = watchThread(func, tid); res = watchThread(func, tid, functionName); return res; } res = tempWatchdog->watchThread(func, tid); 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); res = watchThread(func, tid, functionName); } return res; Loading @@ -109,12 +115,12 @@ public: /** Used to wrap monitored calls in start and stop functions using class timer values */ template<typename T> auto watchThread(T func, uint32_t tid) { auto watchThread(T func, uint32_t tid, const char* functionName) { decltype(func()) res; AutoMutex _l(mEnabledLock); if (mEnabled) { start(tid); start(tid, functionName); res = func(); stop(tid); } else { Loading @@ -130,7 +136,7 @@ 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); void start(uint32_t tid, const char* functionName); /** * If there are no calls left to be monitored, stop blocks/pauses threadloop Loading @@ -138,6 +144,8 @@ private: */ void stop(uint32_t tid); std::string getAbortMessage(int pid, int tid, std::string functionName); virtual bool threadLoop(); Mutex mWatchdogLock; // Lock for condition variable Loading @@ -151,7 +159,9 @@ private: std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper; std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map 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