Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 1 | /* |
| 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 Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 17 | #define LOG_TAG "TimeCheck" |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 18 | |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 19 | #include <optional> |
Ytai Ben-Tsvi | 34f26b1 | 2021-12-02 13:58:38 -0800 | [diff] [blame] | 20 | #include <sstream> |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 21 | |
Marco Nelissen | cf90b49 | 2019-09-26 11:20:54 -0700 | [diff] [blame] | 22 | #include <mediautils/EventLog.h> |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 23 | #include <mediautils/TimeCheck.h> |
| 24 | #include <utils/Log.h> |
Eric Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 25 | #include "debuggerd/handler.h" |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 26 | |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 27 | namespace android::mediautils { |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 28 | |
Ytai Ben-Tsvi | 34f26b1 | 2021-12-02 13:58:38 -0800 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | std::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 Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 38 | // 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 */ |
| 48 | void TimeCheck::accessAudioHalPids(std::vector<pid_t>* pids, bool update) { |
| 49 | static constexpr int kNumAudioHalPidsVectors = 3; |
| 50 | static std::vector<pid_t> audioHalPids[kNumAudioHalPidsVectors]; |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 51 | static std::atomic<unsigned> curAudioHalPids = 0; |
Eric Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 52 | |
| 53 | if (update) { |
Eric Laurent | 1ad278b | 2021-03-05 18:09:01 +0100 | [diff] [blame] | 54 | audioHalPids[(curAudioHalPids++ + 1) % kNumAudioHalPidsVectors] = *pids; |
Eric Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 55 | } else { |
Eric Laurent | 1ad278b | 2021-03-05 18:09:01 +0100 | [diff] [blame] | 56 | *pids = audioHalPids[curAudioHalPids % kNumAudioHalPidsVectors]; |
Eric Laurent | 42896a0 | 2019-09-27 15:40:33 -0700 | [diff] [blame] | 57 | } |
| 58 | } |
| 59 | |
| 60 | /* static */ |
| 61 | void TimeCheck::setAudioHalPids(const std::vector<pid_t>& pids) { |
| 62 | accessAudioHalPids(&(const_cast<std::vector<pid_t>&>(pids)), true); |
| 63 | } |
| 64 | |
| 65 | /* static */ |
| 66 | std::vector<pid_t> TimeCheck::getAudioHalPids() { |
| 67 | std::vector<pid_t> pids; |
| 68 | accessAudioHalPids(&pids, false); |
| 69 | return pids; |
| 70 | } |
| 71 | |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 72 | /* static */ |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 73 | TimerThread& TimeCheck::getTimeCheckThread() { |
| 74 | static TimerThread sTimeCheckThread{}; |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 75 | return sTimeCheckThread; |
| 76 | } |
| 77 | |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 78 | TimeCheck::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-Tsvi | 34f26b1 | 2021-12-02 13:58:38 -0800 | [diff] [blame] | 91 | std::chrono::milliseconds(timeoutMs))) {} |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 92 | |
| 93 | TimeCheck::~TimeCheck() { |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 94 | mTimeCheckHandler->onCancel(mTimerHandle); |
Eric Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 95 | } |
| 96 | |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 97 | void 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 | |
| 107 | void 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-Tsvi | 34f26b1 | 2021-12-02 13:58:38 -0800 | [diff] [blame] | 117 | |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 118 | // Generate audio HAL processes tombstones and allow time to complete |
| 119 | // before forcing restart |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 120 | std::vector<pid_t> pids = TimeCheck::getAudioHalPids(); |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 121 | 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 Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 125 | } |
Ytai Ben-Tsvi | 1ea62c9 | 2021-11-10 14:38:27 -0800 | [diff] [blame] | 126 | sleep(1); |
| 127 | } else { |
| 128 | ALOGI("No HAL process pid available, skipping tombstones"); |
Eric Laurent | 39b09b5 | 2018-06-29 12:24:40 -0700 | [diff] [blame] | 129 | } |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 130 | 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 Laurent | 3528c93 | 2018-02-23 17:17:22 -0800 | [diff] [blame] | 133 | } |
| 134 | |
Andy Hung | 5c6d68a | 2022-03-09 21:54:59 -0800 | [diff] [blame] | 135 | } // namespace android::mediautils |