media utils: dump audio HAL service before restarting audioserver

Add request to create tombstones of audio HAL servers before restarting
audioserver process when the watchdog triggers.

Add audio device factory HAL interface API to retrieve HAL process pids when
possible (on debug builds).

Add AudioFlinger service API to set audio HAL process pids from
JAVA AudioService.

Bug: 141528385
Test: Force watchdog and verify tombstone creation
Change-Id: I68c1e8fb4db23e5952ad0c93d7d0b9d121b8ec18
gugelfrei
Eric Laurent 5 years ago
parent 484d6119d3
commit 42896a0774

@ -1392,6 +1392,12 @@ status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo> *microph
return af->getMicrophones(microphones);
}
status_t AudioSystem::setAudioHalPids(const std::vector<pid_t>& pids) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == nullptr) return PERMISSION_DENIED;
return af->setAudioHalPids(pids);
}
status_t AudioSystem::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,

@ -90,10 +90,12 @@ enum {
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
SET_EFFECT_SUSPENDED,
SET_AUDIO_HAL_PIDS
};
#define MAX_ITEMS_PER_LIST 1024
class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
@ -900,6 +902,20 @@ public:
status = reply.readParcelableVector(microphones);
return status;
}
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(pids.size());
for (auto pid : pids) {
data.writeInt32(pid);
}
status_t status = remote()->transact(SET_AUDIO_HAL_PIDS, data, &reply);
if (status != NO_ERROR) {
return status;
}
return static_cast <status_t> (reply.readInt32());
}
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@ -955,7 +971,8 @@ status_t BnAudioFlinger::onTransact(
case SET_MODE:
case SET_MIC_MUTE:
case SET_LOW_RAM_DEVICE:
case SYSTEM_READY: {
case SYSTEM_READY:
case SET_AUDIO_HAL_PIDS: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@ -1544,6 +1561,31 @@ status_t BnAudioFlinger::onTransact(
}
return NO_ERROR;
}
case SET_AUDIO_HAL_PIDS: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
std::vector<pid_t> pids;
int32_t size;
status_t status = data.readInt32(&size);
if (status != NO_ERROR) {
return status;
}
if (size < 0) {
return BAD_VALUE;
}
if (size > MAX_ITEMS_PER_LIST) {
size = MAX_ITEMS_PER_LIST;
}
for (int32_t i = 0; i < size; i++) {
int32_t pid;
status = data.readInt32(&pid);
if (status != NO_ERROR) {
return status;
}
pids.push_back(pid);
}
reply->writeInt32(setAudioHalPids(pids));
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -399,6 +399,12 @@ public:
static bool isCallScreenModeSupported();
/**
* Send audio HAL server process pids to native audioserver process for use
* when generating audio HAL servers tombstones
*/
static status_t setAudioHalPids(const std::vector<pid_t>& pids);
// ----------------------------------------------------------------------------
class AudioVolumeGroupCallback : public RefBase

@ -523,6 +523,8 @@ public:
/* List available microphones and their characteristics */
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
};

@ -20,6 +20,7 @@
#define LOG_TAG "DevicesFactoryHalHidl"
//#define LOG_NDEBUG 0
#include "android/hidl/manager/1.0/IServiceManager.h"
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h>
@ -28,6 +29,8 @@
#include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h"
#include <set>
using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CPP_VERSION::Result;
using ::android::hardware::Return;
@ -108,5 +111,29 @@ status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterfa
return BAD_VALUE;
}
status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
std::set<pid_t> pidsSet;
for (const auto& factory : mDeviceFactories) {
using ::android::hidl::base::V1_0::DebugInfo;
using android::hidl::manager::V1_0::IServiceManager;
DebugInfo debugInfo;
auto ret = factory->getDebugInfo([&] (const auto &info) {
debugInfo = info;
});
if (!ret.isOk()) {
return INVALID_OPERATION;
}
if (debugInfo.pid == (int)IServiceManager::PidConstant::NO_PID) {
continue;
}
pidsSet.insert(debugInfo.pid);
}
*pids = {pidsSet.begin(), pidsSet.end()};
return NO_ERROR;
}
} // namespace CPP_VERSION
} // namespace android

@ -37,6 +37,9 @@ class DevicesFactoryHalHidl : public DevicesFactoryHalInterface
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
status_t getHalPids(std::vector<pid_t> *pids) override;
private:
std::vector<sp<IDevicesFactory>> mDeviceFactories;

@ -37,6 +37,14 @@ status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInter
}
return mLocalFactory->openDevice(name, device);
}
status_t DevicesFactoryHalHybrid::getHalPids(std::vector<pid_t> *pids) {
if (mHidlFactory != 0) {
return mHidlFactory->getHalPids(pids);
}
return INVALID_OPERATION;
}
} // namespace CPP_VERSION
template <>

@ -36,6 +36,8 @@ class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
status_t getHalPids(std::vector<pid_t> *pids) override;
private:
sp<DevicesFactoryHalInterface> mLocalFactory;
sp<DevicesFactoryHalInterface> mHidlFactory;

@ -33,6 +33,10 @@ class DevicesFactoryHalLocal : public DevicesFactoryHalInterface
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
status_t getHalPids(std::vector<pid_t> *pids __unused) override {
return INVALID_OPERATION;
}
private:
friend class DevicesFactoryHalHybrid;

@ -20,6 +20,7 @@
#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <vector>
namespace android {
@ -30,6 +31,8 @@ class DevicesFactoryHalInterface : public RefBase
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
virtual status_t getHalPids(std::vector<pid_t> *pids) = 0;
static sp<DevicesFactoryHalInterface> create();
protected:

@ -51,6 +51,10 @@ cc_library {
"libmedia_headers",
],
include_dirs: [
// For DEBUGGER_SIGNAL
"system/core/debuggerd/include",
],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
}

@ -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);
}

@ -20,7 +20,7 @@
#include <utils/KeyedVector.h>
#include <utils/Thread.h>
#include <vector>
namespace android {
@ -35,6 +35,8 @@ public:
TimeCheck(const char *tag, uint32_t timeoutMs = kDefaultTimeOutMs);
~TimeCheck();
static void setAudioHalPids(const std::vector<pid_t>& pids);
static std::vector<pid_t> getAudioHalPids();
private:
@ -63,6 +65,7 @@ private:
};
static sp<TimeCheckThread> getTimeCheckThread();
static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
const nsecs_t mEndTimeNs;
};

@ -70,6 +70,7 @@
#include <media/nbaio/PipeReader.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
#include <private/android_filesystem_config.h>
//#define BUFLOG_NDEBUG 0
@ -193,6 +194,9 @@ AudioFlinger::AudioFlinger()
mEffectsFactoryHal = EffectsFactoryHalInterface::create();
mMediaLogNotifier->run("MediaLogNotifier");
std::vector<pid_t> halPids;
mDevicesFactoryHal->getHalPids(&halPids);
TimeCheck::setAudioHalPids(halPids);
}
void AudioFlinger::onFirstRef()
@ -218,6 +222,11 @@ void AudioFlinger::onFirstRef()
gAudioFlinger = this;
}
status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
TimeCheck::setAudioHalPids(pids);
return NO_ERROR;
}
AudioFlinger::~AudioFlinger()
{
while (!mRecordThreads.isEmpty()) {

@ -278,6 +278,8 @@ public:
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
virtual status_t onTransact(
uint32_t code,
const Parcel& data,

Loading…
Cancel
Save