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