Merge "media utils: dump audio HAL service before restarting audioserver"

gugelfrei
Eric Laurent 5 years ago committed by Android (Google) Code Review
commit f1a584a44c

@ -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()) {

@ -281,6 +281,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