blob: 9f258656d1992c983ac28e6dd11bae329f706e83 [file] [log] [blame]
Ravneet98ffa752022-03-02 07:22:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * The CameraService watchdog is used to help detect bad states in the
19 * Camera HAL. The threadloop uses cycle counters, assigned to each calling
20 * thread, to monitor the elapsing time and kills the process when the
21 * expected duration has exceeded.
22 * Notes on multi-threaded behaviors:
23 * - The threadloop is blocked/paused when there are no calls being
Ravneet74cd3732022-03-30 05:33:03 +000024 * monitored (when the TID cycle to counter map is empty).
Ravneet98ffa752022-03-02 07:22:46 +000025 * - The start and stop functions handle simultaneous call monitoring
26 * and single call monitoring differently. See function documentation for
27 * more details.
Ravneet74cd3732022-03-30 05:33:03 +000028 * To disable/enable:
29 * - adb shell cmd media.camera set-cameraservice-watchdog [0/1]
Ravneet98ffa752022-03-02 07:22:46 +000030 */
Jayant Chowdhary48162a72022-05-27 05:37:14 +000031#pragma once
Ravneet98ffa752022-03-02 07:22:46 +000032#include <chrono>
33#include <thread>
34#include <time.h>
35#include <utils/Thread.h>
36#include <utils/Log.h>
37#include <unordered_map>
38
Shuzhen Wang03fe6232023-02-05 12:41:15 -080039#include "utils/CameraServiceProxyWrapper.h"
40
Ravneet98ffa752022-03-02 07:22:46 +000041// Used to wrap the call of interest in start and stop calls
Ravneet Dhanjal3c782742023-01-07 00:38:04 +000042#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
Ravneet98ffa752022-03-02 07:22:46 +000043#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
Ravneet Dhanjal3c782742023-01-07 00:38:04 +000044 watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__, cycles, cycleLength);
Ravneet98ffa752022-03-02 07:22:46 +000045
46// Default cycles and cycle length values used to calculate permitted elapsed time
47const static size_t kMaxCycles = 100;
48const static uint32_t kCycleLengthMs = 100;
49
50namespace android {
51
52class CameraServiceWatchdog : public Thread {
53
Ravneet Dhanjal3c782742023-01-07 00:38:04 +000054struct MonitoredFunction {
55 uint32_t cycles;
56 std::string functionName;
57};
Ravneet98ffa752022-03-02 07:22:46 +000058
Ravneetdbd5b242022-03-02 07:22:46 +000059public:
Xin Li65d53082023-08-25 14:16:11 -070060 explicit CameraServiceWatchdog(const std::string &cameraId,
Shuzhen Wang03fe6232023-02-05 12:41:15 -080061 std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
62 mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
63 mCycleLengthMs(kCycleLengthMs), mEnabled(true),
64 mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
Ravneetdbd5b242022-03-02 07:22:46 +000065
Xin Li65d53082023-08-25 14:16:11 -070066 explicit CameraServiceWatchdog (const std::string &cameraId, size_t maxCycles,
Shuzhen Wang03fe6232023-02-05 12:41:15 -080067 uint32_t cycleLengthMs, bool enabled,
68 std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
69 mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
70 mCycleLengthMs(cycleLengthMs), mEnabled(enabled),
71 mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
Ravneet98ffa752022-03-02 07:22:46 +000072
73 virtual ~CameraServiceWatchdog() {};
74
75 virtual void requestExit();
76
Ravneet74cd3732022-03-30 05:33:03 +000077 /** Enables/disables the watchdog */
78 void setEnabled(bool enable);
79
Ravneet98ffa752022-03-02 07:22:46 +000080 /** Used to wrap monitored calls in start and stop functions using custom timer values */
81 template<typename T>
Ravneet Dhanjal3c782742023-01-07 00:38:04 +000082 auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles,
83 uint32_t cycleLength) {
Jayant Chowdhary48162a72022-05-27 05:37:14 +000084 decltype(func()) res;
Ravneet98ffa752022-03-02 07:22:46 +000085
86 if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
87 // Create another instance of the watchdog to prevent disruption
88 // of timer for current monitored calls
Ravneet74cd3732022-03-30 05:33:03 +000089
90 // Lock for mEnabled
91 mEnabledLock.lock();
Shuzhen Wang03fe6232023-02-05 12:41:15 -080092 sp<CameraServiceWatchdog> tempWatchdog = new CameraServiceWatchdog(
93 mCameraId, cycles, cycleLength, mEnabled, mCameraServiceProxyWrapper);
Ravneet74cd3732022-03-30 05:33:03 +000094 mEnabledLock.unlock();
95
96 status_t status = tempWatchdog->run("CameraServiceWatchdog");
97 if (status != OK) {
98 ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status);
Ravneet Dhanjal3c782742023-01-07 00:38:04 +000099 res = watchThread(func, tid, functionName);
Ravneet74cd3732022-03-30 05:33:03 +0000100 return res;
101 }
102
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000103 res = tempWatchdog->watchThread(func, tid, functionName);
Ravneet98ffa752022-03-02 07:22:46 +0000104 tempWatchdog->requestExit();
105 tempWatchdog.clear();
106 } else {
107 // If custom timer values are equivalent to set class timer values, use
108 // current thread
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000109 res = watchThread(func, tid, functionName);
Ravneet98ffa752022-03-02 07:22:46 +0000110 }
111
112 return res;
113 }
114
115 /** Used to wrap monitored calls in start and stop functions using class timer values */
116 template<typename T>
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000117 auto watchThread(T func, uint32_t tid, const char* functionName) {
Ravneet74cd3732022-03-30 05:33:03 +0000118 decltype(func()) res;
119 AutoMutex _l(mEnabledLock);
Ravneet98ffa752022-03-02 07:22:46 +0000120
Ravneet74cd3732022-03-30 05:33:03 +0000121 if (mEnabled) {
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000122 start(tid, functionName);
Ravneet74cd3732022-03-30 05:33:03 +0000123 res = func();
124 stop(tid);
125 } else {
126 res = func();
127 }
Ravneet98ffa752022-03-02 07:22:46 +0000128
129 return res;
130 }
131
132private:
133
134 /**
135 * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
136 * start() unblocks and starts the watchdog
137 */
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000138 void start(uint32_t tid, const char* functionName);
Ravneet98ffa752022-03-02 07:22:46 +0000139
140 /**
141 * If there are no calls left to be monitored, stop blocks/pauses threadloop
142 * otherwise stop() erases the cycle counter to end watchdog for the calling thread
143 */
144 void stop(uint32_t tid);
145
Ravneet62455912023-04-25 01:30:23 +0000146 std::string getAbortMessage(const std::string& functionName);
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000147
Ravneet98ffa752022-03-02 07:22:46 +0000148 virtual bool threadLoop();
149
Ravneet74cd3732022-03-30 05:33:03 +0000150 Mutex mWatchdogLock; // Lock for condition variable
151 Mutex mEnabledLock; // Lock for enabled status
152 Condition mWatchdogCondition; // Condition variable for stop/start
Xin Li65d53082023-08-25 14:16:11 -0700153 std::string mCameraId; // Camera Id the watchdog belongs to
Ravneet74cd3732022-03-30 05:33:03 +0000154 bool mPause; // True if tid map is empty
155 uint32_t mMaxCycles; // Max cycles
156 uint32_t mCycleLengthMs; // Length of time elapsed per cycle
157 bool mEnabled; // True if watchdog is enabled
Ravneet98ffa752022-03-02 07:22:46 +0000158
Shuzhen Wang03fe6232023-02-05 12:41:15 -0800159 std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
160
Ravneet Dhanjal3c782742023-01-07 00:38:04 +0000161 std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
162 // which retrieves the num of cycles
163 // and name of the function
Ravneet98ffa752022-03-02 07:22:46 +0000164};
165
166} // namespace android