blob: f4955e2d15c90cdb64085decee3c885b45c528ae [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
24 * monitored.
25 * - The start and stop functions handle simultaneous call monitoring
26 * and single call monitoring differently. See function documentation for
27 * more details.
28 */
29
30#include <chrono>
31#include <thread>
32#include <time.h>
33#include <utils/Thread.h>
34#include <utils/Log.h>
35#include <unordered_map>
36
37// Used to wrap the call of interest in start and stop calls
38#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
39#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
40 watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
41
42// Default cycles and cycle length values used to calculate permitted elapsed time
43const static size_t kMaxCycles = 100;
44const static uint32_t kCycleLengthMs = 100;
45
46namespace android {
47
48class CameraServiceWatchdog : public Thread {
49
50public:
51 explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
52 mCycleLengthMs(kCycleLengthMs) {};
53
54 explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs) :
55 mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs) {};
56
57 virtual ~CameraServiceWatchdog() {};
58
59 virtual void requestExit();
60
61 /** Used to wrap monitored calls in start and stop functions using custom timer values */
62 template<typename T>
63 auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
64 auto res = NULL;
65
66 if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
67 // Create another instance of the watchdog to prevent disruption
68 // of timer for current monitored calls
69 sp<CameraServiceWatchdog> tempWatchdog =
70 new CameraServiceWatchdog(cycles, cycleLength);
71 tempWatchdog->run("CameraServiceWatchdog");
72 res = tempWatchdog->watchThread(func, tid);
73 tempWatchdog->requestExit();
74 tempWatchdog.clear();
75 } else {
76 // If custom timer values are equivalent to set class timer values, use
77 // current thread
78 res = watchThread(func, tid);
79 }
80
81 return res;
82 }
83
84 /** Used to wrap monitored calls in start and stop functions using class timer values */
85 template<typename T>
86 auto watchThread(T func, uint32_t tid) {
87 auto res = NULL;
88
89 start(tid);
90 res = func();
91 stop(tid);
92
93 return res;
94 }
95
96private:
97
98 /**
99 * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
100 * start() unblocks and starts the watchdog
101 */
102 void start(uint32_t tid);
103
104 /**
105 * If there are no calls left to be monitored, stop blocks/pauses threadloop
106 * otherwise stop() erases the cycle counter to end watchdog for the calling thread
107 */
108 void stop(uint32_t tid);
109
110 virtual bool threadLoop();
111
112 Mutex mWatchdogLock; // Lock for condition variable
113 Condition mWatchdogCondition; // Condition variable for stop/start
114 bool mPause; // True if thread is currently paused
115 uint32_t mMaxCycles; // Max cycles
116 uint32_t mCycleLengthMs; // Length of time elapsed per cycle
117
118 std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
119};
120
121} // namespace android