blob: 8bee8d1d1189b13dd2e709899b88285a92788ef3 [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
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080017#pragma once
Eric Laurent3528c932018-02-23 17:17:22 -080018
Eric Laurent42896a02019-09-27 15:40:33 -070019#include <vector>
Eric Laurent3528c932018-02-23 17:17:22 -080020
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080021#include <mediautils/TimerThread.h>
22
Andy Hung5c6d68a2022-03-09 21:54:59 -080023namespace android::mediautils {
Eric Laurent3528c932018-02-23 17:17:22 -080024
25// A class monitoring execution time for a code block (scoped variable) and causing an assert
26// if it exceeds a certain time
27
28class TimeCheck {
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080029 public:
Andy Hungdf1ed5c2022-06-13 19:49:43 -070030
31 // Duration for TimeCheck is based on steady_clock, typically nanoseconds.
32 using Duration = std::chrono::steady_clock::duration;
33
34 // Duration for printing is in milliseconds, using float for additional precision.
35 using FloatMs = std::chrono::duration<float, std::milli>;
36
37 // OnTimerFunc is the callback function with 2 parameters.
38 // bool timeout (which is true when the TimeCheck object
39 // times out, false when the TimeCheck object is
40 // destroyed or leaves scope before the timer expires.)
41 // float elapsedMs (the elapsed time to this event).
Andy Hung5c6d68a2022-03-09 21:54:59 -080042 using OnTimerFunc = std::function<void(bool /* timeout */, float /* elapsedMs */ )>;
43
Eric Laurent3528c932018-02-23 17:17:22 -080044 // The default timeout is chosen to be less than system server watchdog timeout
Andy Hungdf1ed5c2022-06-13 19:49:43 -070045 // Note: kDefaultTimeOutMs should be no less than 2 seconds, otherwise spurious timeouts
46 // may occur with system suspend.
Eric Laurent3528c932018-02-23 17:17:22 -080047 static constexpr uint32_t kDefaultTimeOutMs = 5000;
48
Andy Hung5c6d68a2022-03-09 21:54:59 -080049 /**
50 * TimeCheck is a RAII object which will notify a callback
51 * on timer expiration or when the object is deallocated.
52 *
53 * TimeCheck is used as a watchdog and aborts by default on timer expiration.
54 * When it aborts, it will also send a debugger signal to pids passed in through
55 * setAudioHalPids().
56 *
57 * If the callback function returns for timeout it will not be called again for
58 * the deallocation.
59 *
60 * \param tag string associated with the TimeCheck object.
Andy Hungdf1ed5c2022-06-13 19:49:43 -070061 * \param onTimer callback function with 2 parameters (described above in OnTimerFunc).
Andy Hung5c6d68a2022-03-09 21:54:59 -080062 * The callback when timeout is true will be called on a different thread.
Andy Hunga2a1ac32022-03-18 16:12:11 -070063 * This will cancel the callback on the destructor but is not guaranteed
64 * to block for callback completion if it is already in progress
65 * (for maximum concurrency and reduced deadlock potential), so use proper
66 * lifetime analysis (e.g. shared or weak pointers).
Andy Hungdf1ed5c2022-06-13 19:49:43 -070067 * \param requestedTimeoutMs timeout in milliseconds.
Andy Hunga2a1ac32022-03-18 16:12:11 -070068 * A zero timeout means no timeout is set -
69 * the callback is called only when
70 * the TimeCheck object is destroyed or leaves scope.
Andy Hung5c6d68a2022-03-09 21:54:59 -080071 * \param crashOnTimeout true if the object issues an abort on timeout.
72 */
Andy Hungc8c2dde2022-07-15 15:18:59 -070073 explicit TimeCheck(std::string_view tag, OnTimerFunc&& onTimer = {},
Andy Hungdf1ed5c2022-06-13 19:49:43 -070074 uint32_t requestedTimeoutMs = kDefaultTimeOutMs, bool crashOnTimeout = true);
Andy Hunga2a1ac32022-03-18 16:12:11 -070075
76 TimeCheck() = default;
Andy Hung5c6d68a2022-03-09 21:54:59 -080077 // Remove copy constructors as there should only be one call to the destructor.
78 // Move is kept implicitly disabled, but would be logically consistent if enabled.
79 TimeCheck(const TimeCheck& other) = delete;
80 TimeCheck& operator=(const TimeCheck&) = delete;
81
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080082 ~TimeCheck();
Andy Hunga2a1ac32022-03-18 16:12:11 -070083 static std::string toString();
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080084 static void setAudioHalPids(const std::vector<pid_t>& pids);
85 static std::vector<pid_t> getAudioHalPids();
Eric Laurent3528c932018-02-23 17:17:22 -080086
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080087 private:
Andy Hung5c6d68a2022-03-09 21:54:59 -080088 // Helper class for handling events.
89 // The usage here is const safe.
90 class TimeCheckHandler {
91 public:
Andy Hungc8c2dde2022-07-15 15:18:59 -070092 template <typename S, typename F>
93 TimeCheckHandler(S&& _tag, F&& _onTimer, bool _crashOnTimeout,
Andy Hungdf1ed5c2022-06-13 19:49:43 -070094 Duration _timeoutDuration,
95 std::chrono::system_clock::time_point _startSystemTime,
Andy Hungc8c2dde2022-07-15 15:18:59 -070096 pid_t _tid)
97 : tag(std::forward<S>(_tag))
98 , onTimer(std::forward<F>(_onTimer))
99 , crashOnTimeout(_crashOnTimeout)
Andy Hungdf1ed5c2022-06-13 19:49:43 -0700100 , timeoutDuration(_timeoutDuration)
101 , startSystemTime(_startSystemTime)
Andy Hungc8c2dde2022-07-15 15:18:59 -0700102 , tid(_tid)
103 {}
104 const FixedString62 tag;
Andy Hung5c6d68a2022-03-09 21:54:59 -0800105 const OnTimerFunc onTimer;
106 const bool crashOnTimeout;
Andy Hungdf1ed5c2022-06-13 19:49:43 -0700107 const Duration timeoutDuration;
108 const std::chrono::system_clock::time_point startSystemTime;
Andy Hung5c6d68a2022-03-09 21:54:59 -0800109 const pid_t tid;
110
111 void onCancel(TimerThread::Handle handle) const;
Andy Hungdf1ed5c2022-06-13 19:49:43 -0700112 void onTimeout(TimerThread::Handle handle) const;
Andy Hung5c6d68a2022-03-09 21:54:59 -0800113 };
114
Andy Hungdf1ed5c2022-06-13 19:49:43 -0700115 // Returns a string that represents the timeout vs elapsed time,
116 // and diagnostics if there are any potential issues.
117 static std::string analyzeTimeouts(
118 float timeoutMs, float elapsedSteadyMs, float elapsedSystemMs);
119
Andy Hunga2a1ac32022-03-18 16:12:11 -0700120 static TimerThread& getTimeCheckThread();
121 static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
122
Andy Hung5c6d68a2022-03-09 21:54:59 -0800123 // mTimeCheckHandler is immutable, prefer to be first initialized, last destroyed.
124 // Technically speaking, we do not need a shared_ptr here because TimerThread::cancelTask()
125 // is mutually exclusive of the callback, but the price paid for lifetime safety is minimal.
126 const std::shared_ptr<const TimeCheckHandler> mTimeCheckHandler;
Andy Hunga2a1ac32022-03-18 16:12:11 -0700127 const TimerThread::Handle mTimerHandle = TimerThread::INVALID_HANDLE;
Eric Laurent3528c932018-02-23 17:17:22 -0800128};
129
Andy Hung224f82f2022-03-22 00:00:49 -0700130// Returns a TimeCheck object that sends info to MethodStatistics
131// obtained from getStatisticsForClass(className).
132TimeCheck makeTimeCheckStatsForClassMethod(
133 std::string_view className, std::string_view methodName);
134
Andy Hung5c6d68a2022-03-09 21:54:59 -0800135} // namespace android::mediautils