1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "CameraServiceWatchdog"
18*ec779b8eSAndroid Build Coastguard Worker
19*ec779b8eSAndroid Build Coastguard Worker #include "CameraServiceWatchdog.h"
20*ec779b8eSAndroid Build Coastguard Worker #include "com_android_internal_camera_flags.h"
21*ec779b8eSAndroid Build Coastguard Worker #include "android/set_abort_message.h"
22*ec779b8eSAndroid Build Coastguard Worker #include "utils/CameraServiceProxyWrapper.h"
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker namespace android {
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker namespace flags = com::android::internal::camera::flags;
27*ec779b8eSAndroid Build Coastguard Worker
threadLoop()28*ec779b8eSAndroid Build Coastguard Worker bool CameraServiceWatchdog::threadLoop()
29*ec779b8eSAndroid Build Coastguard Worker {
30*ec779b8eSAndroid Build Coastguard Worker {
31*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mWatchdogLock);
32*ec779b8eSAndroid Build Coastguard Worker
33*ec779b8eSAndroid Build Coastguard Worker while (mPause) {
34*ec779b8eSAndroid Build Coastguard Worker mWatchdogCondition.wait(mWatchdogLock);
35*ec779b8eSAndroid Build Coastguard Worker }
36*ec779b8eSAndroid Build Coastguard Worker }
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(mCycleLengthMs));
39*ec779b8eSAndroid Build Coastguard Worker
40*ec779b8eSAndroid Build Coastguard Worker {
41*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mWatchdogLock);
42*ec779b8eSAndroid Build Coastguard Worker
43*ec779b8eSAndroid Build Coastguard Worker for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) {
44*ec779b8eSAndroid Build Coastguard Worker uint32_t currentThreadId = it->first;
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker mTidMap[currentThreadId].cycles++;
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker if (mTidMap[currentThreadId].cycles >= mMaxCycles) {
49*ec779b8eSAndroid Build Coastguard Worker std::string abortMessage = getAbortMessage(mTidMap[currentThreadId].functionName);
50*ec779b8eSAndroid Build Coastguard Worker android_set_abort_message(abortMessage.c_str());
51*ec779b8eSAndroid Build Coastguard Worker ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
52*ec779b8eSAndroid Build Coastguard Worker currentThreadId);
53*ec779b8eSAndroid Build Coastguard Worker mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
54*ec779b8eSAndroid Build Coastguard Worker true /*deviceError*/);
55*ec779b8eSAndroid Build Coastguard Worker // We use abort here so we can get a tombstone for better
56*ec779b8eSAndroid Build Coastguard Worker // debugging.
57*ec779b8eSAndroid Build Coastguard Worker if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
58*ec779b8eSAndroid Build Coastguard Worker for (pid_t pid : mProviderPids) {
59*ec779b8eSAndroid Build Coastguard Worker kill(pid, SIGABRT);
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker }
62*ec779b8eSAndroid Build Coastguard Worker
63*ec779b8eSAndroid Build Coastguard Worker abort();
64*ec779b8eSAndroid Build Coastguard Worker }
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker
68*ec779b8eSAndroid Build Coastguard Worker return true;
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker
getAbortMessage(const std::string & functionName)71*ec779b8eSAndroid Build Coastguard Worker std::string CameraServiceWatchdog::getAbortMessage(const std::string& functionName) {
72*ec779b8eSAndroid Build Coastguard Worker std::string res = "CameraServiceWatchdog triggering abort during "
73*ec779b8eSAndroid Build Coastguard Worker + functionName;
74*ec779b8eSAndroid Build Coastguard Worker return res;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker
requestExit()77*ec779b8eSAndroid Build Coastguard Worker void CameraServiceWatchdog::requestExit()
78*ec779b8eSAndroid Build Coastguard Worker {
79*ec779b8eSAndroid Build Coastguard Worker Thread::requestExit();
80*ec779b8eSAndroid Build Coastguard Worker
81*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mWatchdogLock);
82*ec779b8eSAndroid Build Coastguard Worker
83*ec779b8eSAndroid Build Coastguard Worker mTidMap.clear();
84*ec779b8eSAndroid Build Coastguard Worker
85*ec779b8eSAndroid Build Coastguard Worker if (mPause) {
86*ec779b8eSAndroid Build Coastguard Worker mPause = false;
87*ec779b8eSAndroid Build Coastguard Worker mWatchdogCondition.signal();
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker
setEnabled(bool enable)91*ec779b8eSAndroid Build Coastguard Worker void CameraServiceWatchdog::setEnabled(bool enable)
92*ec779b8eSAndroid Build Coastguard Worker {
93*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mEnabledLock);
94*ec779b8eSAndroid Build Coastguard Worker
95*ec779b8eSAndroid Build Coastguard Worker if (enable) {
96*ec779b8eSAndroid Build Coastguard Worker mEnabled = true;
97*ec779b8eSAndroid Build Coastguard Worker } else {
98*ec779b8eSAndroid Build Coastguard Worker mEnabled = false;
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker
stop(uint32_t tid)102*ec779b8eSAndroid Build Coastguard Worker void CameraServiceWatchdog::stop(uint32_t tid)
103*ec779b8eSAndroid Build Coastguard Worker {
104*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mWatchdogLock);
105*ec779b8eSAndroid Build Coastguard Worker
106*ec779b8eSAndroid Build Coastguard Worker mTidMap.erase(tid);
107*ec779b8eSAndroid Build Coastguard Worker
108*ec779b8eSAndroid Build Coastguard Worker if (mTidMap.empty()) {
109*ec779b8eSAndroid Build Coastguard Worker mPause = true;
110*ec779b8eSAndroid Build Coastguard Worker }
111*ec779b8eSAndroid Build Coastguard Worker }
112*ec779b8eSAndroid Build Coastguard Worker
start(uint32_t tid,const char * functionName)113*ec779b8eSAndroid Build Coastguard Worker void CameraServiceWatchdog::start(uint32_t tid, const char* functionName)
114*ec779b8eSAndroid Build Coastguard Worker {
115*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mWatchdogLock);
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker MonitoredFunction monitoredFunction = {};
118*ec779b8eSAndroid Build Coastguard Worker monitoredFunction.cycles = 0;
119*ec779b8eSAndroid Build Coastguard Worker monitoredFunction.functionName = functionName;
120*ec779b8eSAndroid Build Coastguard Worker mTidMap[tid] = monitoredFunction;
121*ec779b8eSAndroid Build Coastguard Worker
122*ec779b8eSAndroid Build Coastguard Worker if (mPause) {
123*ec779b8eSAndroid Build Coastguard Worker mPause = false;
124*ec779b8eSAndroid Build Coastguard Worker mWatchdogCondition.signal();
125*ec779b8eSAndroid Build Coastguard Worker }
126*ec779b8eSAndroid Build Coastguard Worker }
127*ec779b8eSAndroid Build Coastguard Worker
128*ec779b8eSAndroid Build Coastguard Worker } // namespace android
129