blob: 819e1468ea2740c508fcc45c5fa84a57f1af0fb8 [file] [log] [blame]
Eric Laurent3528c932018-02-23 17:17:22 -08001/*
2 * Copyright (C) 2018 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
Eric Laurent42896a02019-09-27 15:40:33 -070017#define LOG_TAG "TimeCheck"
Eric Laurent3528c932018-02-23 17:17:22 -080018
Eric Laurent39b09b52018-06-29 12:24:40 -070019#include <utils/Log.h>
Marco Nelissencf90b492019-09-26 11:20:54 -070020#include <mediautils/TimeCheck.h>
21#include <mediautils/EventLog.h>
Eric Laurent42896a02019-09-27 15:40:33 -070022#include "debuggerd/handler.h"
Eric Laurent3528c932018-02-23 17:17:22 -080023
24namespace android {
25
Eric Laurent42896a02019-09-27 15:40:33 -070026// Audio HAL server pids vector used to generate audio HAL processes tombstone
27// when audioserver watchdog triggers.
28// We use a lockless storage to avoid potential deadlocks in the context of watchdog
29// trigger.
30// Protection again simultaneous writes is not needed given one update takes place
31// during AudioFlinger construction and other comes necessarily later once the IAudioFlinger
32// interface is available.
33// The use of an atomic index just guaranties that current vector is fully initialized
34// when read.
35/* static */
36void TimeCheck::accessAudioHalPids(std::vector<pid_t>* pids, bool update) {
37 static constexpr int kNumAudioHalPidsVectors = 3;
38 static std::vector<pid_t> audioHalPids[kNumAudioHalPidsVectors];
39 static std::atomic<int> curAudioHalPids = 0;
40
41 if (update) {
Eric Laurent1ad278b2021-03-05 18:09:01 +010042 audioHalPids[(curAudioHalPids++ + 1) % kNumAudioHalPidsVectors] = *pids;
Eric Laurent42896a02019-09-27 15:40:33 -070043 } else {
Eric Laurent1ad278b2021-03-05 18:09:01 +010044 *pids = audioHalPids[curAudioHalPids % kNumAudioHalPidsVectors];
Eric Laurent42896a02019-09-27 15:40:33 -070045 }
46}
47
48/* static */
49void TimeCheck::setAudioHalPids(const std::vector<pid_t>& pids) {
50 accessAudioHalPids(&(const_cast<std::vector<pid_t>&>(pids)), true);
51}
52
53/* static */
54std::vector<pid_t> TimeCheck::getAudioHalPids() {
55 std::vector<pid_t> pids;
56 accessAudioHalPids(&pids, false);
57 return pids;
58}
59
Eric Laurent3528c932018-02-23 17:17:22 -080060/* static */
61sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
62{
63 static sp<TimeCheck::TimeCheckThread> sTimeCheckThread = new TimeCheck::TimeCheckThread();
64 return sTimeCheckThread;
65}
66
67TimeCheck::TimeCheck(const char *tag, uint32_t timeoutMs)
68 : mEndTimeNs(getTimeCheckThread()->startMonitoring(tag, timeoutMs))
69{
70}
71
72TimeCheck::~TimeCheck() {
73 getTimeCheckThread()->stopMonitoring(mEndTimeNs);
74}
75
76TimeCheck::TimeCheckThread::~TimeCheckThread()
77{
78 AutoMutex _l(mMutex);
79 requestExit();
80 mMonitorRequests.clear();
81 mCond.signal();
82}
83
84nsecs_t TimeCheck::TimeCheckThread::startMonitoring(const char *tag, uint32_t timeoutMs) {
85 Mutex::Autolock _l(mMutex);
86 nsecs_t endTimeNs = systemTime() + milliseconds(timeoutMs);
87 for (; mMonitorRequests.indexOfKey(endTimeNs) >= 0; ++endTimeNs);
88 mMonitorRequests.add(endTimeNs, tag);
89 mCond.signal();
90 return endTimeNs;
91}
92
93void TimeCheck::TimeCheckThread::stopMonitoring(nsecs_t endTimeNs) {
94 Mutex::Autolock _l(mMutex);
95 mMonitorRequests.removeItem(endTimeNs);
96 mCond.signal();
97}
98
99bool TimeCheck::TimeCheckThread::threadLoop()
100{
101 status_t status = TIMED_OUT;
Eric Laurent3528c932018-02-23 17:17:22 -0800102 {
103 AutoMutex _l(mMutex);
104
105 if (exitPending()) {
106 return false;
107 }
108
109 nsecs_t endTimeNs = INT64_MAX;
Mikhail Naganov72ee01d2020-03-26 13:07:31 -0700110 const char *tag = "<unspecified>";
Eric Laurent3528c932018-02-23 17:17:22 -0800111 // KeyedVector mMonitorRequests is ordered so take first entry as next timeout
112 if (mMonitorRequests.size() != 0) {
113 endTimeNs = mMonitorRequests.keyAt(0);
114 tag = mMonitorRequests.valueAt(0);
115 }
116
117 const nsecs_t waitTimeNs = endTimeNs - systemTime();
118 if (waitTimeNs > 0) {
119 status = mCond.waitRelative(mMutex, waitTimeNs);
120 }
Eric Laurent9b9b3de2019-10-14 18:47:34 -0700121 if (status != NO_ERROR) {
Eric Laurent42896a02019-09-27 15:40:33 -0700122 // Generate audio HAL processes tombstones and allow time to complete
123 // before forcing restart
124 std::vector<pid_t> pids = getAudioHalPids();
125 if (pids.size() != 0) {
126 for (const auto& pid : pids) {
127 ALOGI("requesting tombstone for pid: %d", pid);
128 sigqueue(pid, DEBUGGER_SIGNAL, {.sival_int = 0});
129 }
130 sleep(1);
131 } else {
132 ALOGI("No HAL process pid available, skipping tombstones");
133 }
Eric Laurent9b9b3de2019-10-14 18:47:34 -0700134 LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag);
135 LOG_ALWAYS_FATAL("TimeCheck timeout for %s", tag);
136 }
Eric Laurent39b09b52018-06-29 12:24:40 -0700137 }
Eric Laurent3528c932018-02-23 17:17:22 -0800138 return true;
139}
140
141}; // namespace android