• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 (when the TID cycle to counter map is empty).
25  *   - The start and stop functions handle simultaneous call monitoring
26  *   and single call monitoring differently. See function documentation for
27  *   more details.
28  * To disable/enable:
29  *   - adb shell cmd media.camera set-watchdog [0/1]
30  */
31 #pragma once
32 #include <chrono>
33 #include <set>
34 #include <thread>
35 #include <time.h>
36 #include <utils/Thread.h>
37 #include <utils/Log.h>
38 #include <unordered_map>
39 
40 #include "utils/CameraServiceProxyWrapper.h"
41 
42 // Used to wrap the call of interest in start and stop calls
43 #define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
44 
45 // Default cycles and cycle length values used to calculate permitted elapsed time
46 const static size_t   kMaxCycles     = 650;
47 const static uint32_t kCycleLengthMs = 100;
48 
49 namespace android {
50 
51 class CameraServiceWatchdog : public Thread {
52 
53 struct MonitoredFunction {
54     uint32_t cycles;
55     std::string functionName;
56 };
57 
58 public:
59 
CameraServiceWatchdog(const std::set<pid_t> & pids,pid_t clientPid,bool isNativePid,const std::string & cameraId,std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper)60     explicit CameraServiceWatchdog(
61             const std::set<pid_t> &pids, pid_t clientPid,
62             bool isNativePid, const std::string &cameraId,
63             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
64                     mProviderPids(pids), mClientPid(clientPid), mIsNativePid(isNativePid),
65                     mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
66                     mCycleLengthMs(kCycleLengthMs), mEnabled(true),
67                     mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
68 
~CameraServiceWatchdog()69     virtual ~CameraServiceWatchdog() {};
70 
71     virtual void requestExit();
72 
73     /** Enables/disables the watchdog */
74     void setEnabled(bool enable);
75 
76     /** Used to wrap monitored calls in start and stop functions using class timer values */
77     template<typename T>
watchThread(T func,uint32_t tid,const char * functionName)78     auto watchThread(T func, uint32_t tid, const char* functionName) {
79         decltype(func()) res;
80         AutoMutex _l(mEnabledLock);
81 
82         if (mEnabled) {
83             start(tid, functionName);
84             res = func();
85             stop(tid);
86         } else {
87             res = func();
88         }
89 
90         return res;
91     }
92 
93 private:
94 
95     /**
96      * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
97      * start() unblocks and starts the watchdog
98      */
99     void start(uint32_t tid, const char* functionName);
100 
101     /**
102      * If there are no calls left to be monitored, stop blocks/pauses threadloop
103      * otherwise stop() erases the cycle counter to end watchdog for the calling thread
104      */
105     void stop(uint32_t tid);
106 
107     std::string getAbortMessage(const std::string& functionName);
108 
109     virtual bool    threadLoop();
110 
111     Mutex           mWatchdogLock;      // Lock for condition variable
112     Mutex           mEnabledLock;       // Lock for enabled status
113     Condition       mWatchdogCondition; // Condition variable for stop/start
114     std::set<pid_t> mProviderPids;      // Process ID set of camera providers
115     pid_t           mClientPid;         // Process ID of the client
116     bool            mIsNativePid;       // Whether the client is a native process
117     std::string     mCameraId;          // Camera Id the watchdog belongs to
118     bool            mPause;             // True if tid map is empty
119     uint32_t        mMaxCycles;         // Max cycles
120     uint32_t        mCycleLengthMs;     // Length of time elapsed per cycle
121     bool            mEnabled;           // True if watchdog is enabled
122 
123     std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
124 
125     std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
126                                                              // which retrieves the num of cycles
127                                                              // and name of the function
128 };
129 
130 }   // namespace android
131