blob: 5f269affcabd7d37ced8bff38e2fc707e43001d4 [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
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080019#include <optional>
Ytai Ben-Tsvi34f26b12021-12-02 13:58:38 -080020#include <sstream>
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080021
Marco Nelissencf90b492019-09-26 11:20:54 -070022#include <mediautils/EventLog.h>
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080023#include <mediautils/TimeCheck.h>
24#include <utils/Log.h>
Eric Laurent42896a02019-09-27 15:40:33 -070025#include "debuggerd/handler.h"
Eric Laurent3528c932018-02-23 17:17:22 -080026
Andy Hung5c6d68a2022-03-09 21:54:59 -080027namespace android::mediautils {
Eric Laurent3528c932018-02-23 17:17:22 -080028
Ytai Ben-Tsvi34f26b12021-12-02 13:58:38 -080029namespace {
30
31std::string formatTime(std::chrono::system_clock::time_point t) {
32 auto msSinceEpoch = std::chrono::round<std::chrono::milliseconds>(t.time_since_epoch());
33 return (std::ostringstream() << msSinceEpoch.count()).str();
34}
35
36} // namespace
37
Eric Laurent42896a02019-09-27 15:40:33 -070038// Audio HAL server pids vector used to generate audio HAL processes tombstone
39// when audioserver watchdog triggers.
40// We use a lockless storage to avoid potential deadlocks in the context of watchdog
41// trigger.
42// Protection again simultaneous writes is not needed given one update takes place
43// during AudioFlinger construction and other comes necessarily later once the IAudioFlinger
44// interface is available.
45// The use of an atomic index just guaranties that current vector is fully initialized
46// when read.
47/* static */
48void TimeCheck::accessAudioHalPids(std::vector<pid_t>* pids, bool update) {
49 static constexpr int kNumAudioHalPidsVectors = 3;
50 static std::vector<pid_t> audioHalPids[kNumAudioHalPidsVectors];
Andy Hung5c6d68a2022-03-09 21:54:59 -080051 static std::atomic<unsigned> curAudioHalPids = 0;
Eric Laurent42896a02019-09-27 15:40:33 -070052
53 if (update) {
Eric Laurent1ad278b2021-03-05 18:09:01 +010054 audioHalPids[(curAudioHalPids++ + 1) % kNumAudioHalPidsVectors] = *pids;
Eric Laurent42896a02019-09-27 15:40:33 -070055 } else {
Eric Laurent1ad278b2021-03-05 18:09:01 +010056 *pids = audioHalPids[curAudioHalPids % kNumAudioHalPidsVectors];
Eric Laurent42896a02019-09-27 15:40:33 -070057 }
58}
59
60/* static */
61void TimeCheck::setAudioHalPids(const std::vector<pid_t>& pids) {
62 accessAudioHalPids(&(const_cast<std::vector<pid_t>&>(pids)), true);
63}
64
65/* static */
66std::vector<pid_t> TimeCheck::getAudioHalPids() {
67 std::vector<pid_t> pids;
68 accessAudioHalPids(&pids, false);
69 return pids;
70}
71
Eric Laurent3528c932018-02-23 17:17:22 -080072/* static */
Andy Hung5c6d68a2022-03-09 21:54:59 -080073TimerThread& TimeCheck::getTimeCheckThread() {
74 static TimerThread sTimeCheckThread{};
Eric Laurent3528c932018-02-23 17:17:22 -080075 return sTimeCheckThread;
76}
77
Andy Hung5c6d68a2022-03-09 21:54:59 -080078TimeCheck::TimeCheck(std::string tag, OnTimerFunc&& onTimer, uint32_t timeoutMs,
79 bool crashOnTimeout)
80 : mTimeCheckHandler(new TimeCheckHandler{
81 std::move(tag), std::move(onTimer), crashOnTimeout,
82 std::chrono::system_clock::now(), gettid()})
83 , mTimerHandle(getTimeCheckThread().scheduleTask(
84 // Pass in all the arguments by value to this task for safety.
85 // The thread could call the callback before the constructor is finished.
86 // The destructor will be blocked on the callback, but that is implementation
87 // dependent.
88 [ timeCheckHandler = mTimeCheckHandler ] {
89 timeCheckHandler->onTimeout();
90 },
Ytai Ben-Tsvi34f26b12021-12-02 13:58:38 -080091 std::chrono::milliseconds(timeoutMs))) {}
Eric Laurent3528c932018-02-23 17:17:22 -080092
93TimeCheck::~TimeCheck() {
Andy Hung5c6d68a2022-03-09 21:54:59 -080094 mTimeCheckHandler->onCancel(mTimerHandle);
Eric Laurent3528c932018-02-23 17:17:22 -080095}
96
Andy Hung5c6d68a2022-03-09 21:54:59 -080097void TimeCheck::TimeCheckHandler::onCancel(TimerThread::Handle timerHandle) const
98{
99 if (TimeCheck::getTimeCheckThread().cancelTask(timerHandle) && onTimer) {
100 const std::chrono::system_clock::time_point endTime = std::chrono::system_clock::now();
101 onTimer(false /* timeout */,
102 std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
103 endTime - startTime).count());
104 }
105}
106
107void TimeCheck::TimeCheckHandler::onTimeout() const
108{
109 const std::chrono::system_clock::time_point endTime = std::chrono::system_clock::now();
110 if (onTimer) {
111 onTimer(true /* timeout */,
112 std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
113 endTime - startTime).count());
114 }
115
116 if (!crashOnTimeout) return;
Ytai Ben-Tsvi34f26b12021-12-02 13:58:38 -0800117
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -0800118 // Generate audio HAL processes tombstones and allow time to complete
119 // before forcing restart
Andy Hung5c6d68a2022-03-09 21:54:59 -0800120 std::vector<pid_t> pids = TimeCheck::getAudioHalPids();
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -0800121 if (pids.size() != 0) {
122 for (const auto& pid : pids) {
123 ALOGI("requesting tombstone for pid: %d", pid);
124 sigqueue(pid, DEBUGGER_SIGNAL, {.sival_int = 0});
Eric Laurent3528c932018-02-23 17:17:22 -0800125 }
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -0800126 sleep(1);
127 } else {
128 ALOGI("No HAL process pid available, skipping tombstones");
Eric Laurent39b09b52018-06-29 12:24:40 -0700129 }
Andy Hung5c6d68a2022-03-09 21:54:59 -0800130 LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str());
131 LOG_ALWAYS_FATAL("TimeCheck timeout for %s on thread %d (start=%s, end=%s)",
132 tag.c_str(), tid, formatTime(startTime).c_str(), formatTime(endTime).c_str());
Eric Laurent3528c932018-02-23 17:17:22 -0800133}
134
Andy Hung5c6d68a2022-03-09 21:54:59 -0800135} // namespace android::mediautils