blob: 038e7dde54ed54b70740cc9195180ba29e754608 [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 Hung5c6d68a2022-03-09 21:54:59 -080030 using OnTimerFunc = std::function<void(bool /* timeout */, float /* elapsedMs */ )>;
31
Eric Laurent3528c932018-02-23 17:17:22 -080032 // The default timeout is chosen to be less than system server watchdog timeout
33 static constexpr uint32_t kDefaultTimeOutMs = 5000;
34
Andy Hung5c6d68a2022-03-09 21:54:59 -080035 /**
36 * TimeCheck is a RAII object which will notify a callback
37 * on timer expiration or when the object is deallocated.
38 *
39 * TimeCheck is used as a watchdog and aborts by default on timer expiration.
40 * When it aborts, it will also send a debugger signal to pids passed in through
41 * setAudioHalPids().
42 *
43 * If the callback function returns for timeout it will not be called again for
44 * the deallocation.
45 *
46 * \param tag string associated with the TimeCheck object.
47 * \param onTimer callback function with 2 parameters
48 * bool timeout (which is true when the TimeCheck object
49 * times out, false when the TimeCheck object is
50 * destroyed or leaves scope before the timer expires.)
51 * float elapsedMs (the elapsed time to this event).
52 * The callback when timeout is true will be called on a different thread.
Andy Hunga2a1ac32022-03-18 16:12:11 -070053 * This will cancel the callback on the destructor but is not guaranteed
54 * to block for callback completion if it is already in progress
55 * (for maximum concurrency and reduced deadlock potential), so use proper
56 * lifetime analysis (e.g. shared or weak pointers).
Andy Hung5c6d68a2022-03-09 21:54:59 -080057 * \param timeoutMs timeout in milliseconds.
Andy Hunga2a1ac32022-03-18 16:12:11 -070058 * A zero timeout means no timeout is set -
59 * the callback is called only when
60 * the TimeCheck object is destroyed or leaves scope.
Andy Hung5c6d68a2022-03-09 21:54:59 -080061 * \param crashOnTimeout true if the object issues an abort on timeout.
62 */
Andy Hungc8c2dde2022-07-15 15:18:59 -070063 explicit TimeCheck(std::string_view tag, OnTimerFunc&& onTimer = {},
Andy Hung5c6d68a2022-03-09 21:54:59 -080064 uint32_t timeoutMs = kDefaultTimeOutMs, bool crashOnTimeout = true);
Andy Hunga2a1ac32022-03-18 16:12:11 -070065
66 TimeCheck() = default;
Andy Hung5c6d68a2022-03-09 21:54:59 -080067 // Remove copy constructors as there should only be one call to the destructor.
68 // Move is kept implicitly disabled, but would be logically consistent if enabled.
69 TimeCheck(const TimeCheck& other) = delete;
70 TimeCheck& operator=(const TimeCheck&) = delete;
71
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080072 ~TimeCheck();
Andy Hunga2a1ac32022-03-18 16:12:11 -070073 static std::string toString();
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080074 static void setAudioHalPids(const std::vector<pid_t>& pids);
75 static std::vector<pid_t> getAudioHalPids();
Eric Laurent3528c932018-02-23 17:17:22 -080076
Ytai Ben-Tsvi1ea62c92021-11-10 14:38:27 -080077 private:
Andy Hung5c6d68a2022-03-09 21:54:59 -080078 // Helper class for handling events.
79 // The usage here is const safe.
80 class TimeCheckHandler {
81 public:
Andy Hungc8c2dde2022-07-15 15:18:59 -070082 template <typename S, typename F>
83 TimeCheckHandler(S&& _tag, F&& _onTimer, bool _crashOnTimeout,
84 const std::chrono::system_clock::time_point& _startTime,
85 pid_t _tid)
86 : tag(std::forward<S>(_tag))
87 , onTimer(std::forward<F>(_onTimer))
88 , crashOnTimeout(_crashOnTimeout)
89 , startTime(_startTime)
90 , tid(_tid)
91 {}
92 const FixedString62 tag;
Andy Hung5c6d68a2022-03-09 21:54:59 -080093 const OnTimerFunc onTimer;
94 const bool crashOnTimeout;
95 const std::chrono::system_clock::time_point startTime;
96 const pid_t tid;
97
98 void onCancel(TimerThread::Handle handle) const;
99 void onTimeout() const;
100 };
101
Andy Hunga2a1ac32022-03-18 16:12:11 -0700102 static TimerThread& getTimeCheckThread();
103 static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
104
Andy Hung5c6d68a2022-03-09 21:54:59 -0800105 // mTimeCheckHandler is immutable, prefer to be first initialized, last destroyed.
106 // Technically speaking, we do not need a shared_ptr here because TimerThread::cancelTask()
107 // is mutually exclusive of the callback, but the price paid for lifetime safety is minimal.
108 const std::shared_ptr<const TimeCheckHandler> mTimeCheckHandler;
Andy Hunga2a1ac32022-03-18 16:12:11 -0700109 const TimerThread::Handle mTimerHandle = TimerThread::INVALID_HANDLE;
Eric Laurent3528c932018-02-23 17:17:22 -0800110};
111
Andy Hung224f82f2022-03-22 00:00:49 -0700112// Returns a TimeCheck object that sends info to MethodStatistics
113// obtained from getStatisticsForClass(className).
114TimeCheck makeTimeCheckStatsForClassMethod(
115 std::string_view className, std::string_view methodName);
116
Andy Hung5c6d68a2022-03-09 21:54:59 -0800117} // namespace android::mediautils