@ -14,13 +14,50 @@
* limitations under the License .
*/
# define LOG_TAG "TimeCheck"
# include <utils/Log.h>
# include <mediautils/TimeCheck.h>
# include <mediautils/EventLog.h>
# include "debuggerd/handler.h"
namespace android {
// Audio HAL server pids vector used to generate audio HAL processes tombstone
// when audioserver watchdog triggers.
// We use a lockless storage to avoid potential deadlocks in the context of watchdog
// trigger.
// Protection again simultaneous writes is not needed given one update takes place
// during AudioFlinger construction and other comes necessarily later once the IAudioFlinger
// interface is available.
// The use of an atomic index just guaranties that current vector is fully initialized
// when read.
/* static */
void TimeCheck : : accessAudioHalPids ( std : : vector < pid_t > * pids , bool update ) {
static constexpr int kNumAudioHalPidsVectors = 3 ;
static std : : vector < pid_t > audioHalPids [ kNumAudioHalPidsVectors ] ;
static std : : atomic < int > curAudioHalPids = 0 ;
if ( update ) {
audioHalPids [ ( curAudioHalPids + 1 ) % kNumAudioHalPidsVectors ] = * pids ;
curAudioHalPids + + ;
} else {
* pids = audioHalPids [ curAudioHalPids ] ;
}
}
/* static */
void TimeCheck : : setAudioHalPids ( const std : : vector < pid_t > & pids ) {
accessAudioHalPids ( & ( const_cast < std : : vector < pid_t > & > ( pids ) ) , true ) ;
}
/* static */
std : : vector < pid_t > TimeCheck : : getAudioHalPids ( ) {
std : : vector < pid_t > pids ;
accessAudioHalPids ( & pids , false ) ;
return pids ;
}
/* static */
sp < TimeCheck : : TimeCheckThread > TimeCheck : : getTimeCheckThread ( )
{
@ -83,6 +120,18 @@ bool TimeCheck::TimeCheckThread::threadLoop()
status = mCond . waitRelative ( mMutex , waitTimeNs ) ;
}
if ( status ! = NO_ERROR ) {
// Generate audio HAL processes tombstones and allow time to complete
// before forcing restart
std : : vector < pid_t > pids = getAudioHalPids ( ) ;
if ( pids . size ( ) ! = 0 ) {
for ( const auto & pid : pids ) {
ALOGI ( " requesting tombstone for pid: %d " , pid ) ;
sigqueue ( pid , DEBUGGER_SIGNAL , { . sival_int = 0 } ) ;
}
sleep ( 1 ) ;
} else {
ALOGI ( " No HAL process pid available, skipping tombstones " ) ;
}
LOG_EVENT_STRING ( LOGTAG_AUDIO_BINDER_TIMEOUT , tag ) ;
LOG_ALWAYS_FATAL ( " TimeCheck timeout for %s " , tag ) ;
}