audiohal: Add diagnostics to investigate HAL call crashes
This is intended to clarify whether surprising zeroing out of HAL control structures happens to a particular HAL module, or to any HAL module at random. Unfortunately, the crash itself can't be prevented as audioflinger can't work around a HAL outage, and needs to be restarted anyway. Bug: 36225019 Test: verified that the logged string contains the information Change-Id: I5843d89b4e5385b4ce269f72b5891ccb646daeba
This commit is contained in:
parent
f66f505bc6
commit
6c0f76a684
4 changed files with 63 additions and 10 deletions
|
@ -17,9 +17,11 @@
|
|||
#define LOG_TAG "DeviceHAL"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
|
@ -35,8 +37,57 @@ namespace audio {
|
|||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
Device::Device(audio_hw_device_t* device)
|
||||
: mDevice(device) {
|
||||
namespace {
|
||||
|
||||
class Diagnostics {
|
||||
public:
|
||||
static Diagnostics& getInstance() {
|
||||
std::lock_guard<std::mutex> _(mLock);
|
||||
if (mInstance == nullptr) {
|
||||
mInstance = new Diagnostics;
|
||||
}
|
||||
return *mInstance;
|
||||
}
|
||||
|
||||
void registerDevice(Device* dev) {
|
||||
std::lock_guard<std::mutex> _(mLock);
|
||||
mDevices.push_back(wp<Device>(dev));
|
||||
}
|
||||
|
||||
void checkForErasedHalCblk(const Device* dev) {
|
||||
if (dev->version() != 0) return; // all OK
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "Zero HAL CB for " << dev->type() << ":" << std::hex
|
||||
<< dev->device() << "; Others: ";
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mLock);
|
||||
for (auto wp : mDevices) {
|
||||
sp<Device> other{wp.promote()};
|
||||
if (other.get() == nullptr || other.get() == dev) continue;
|
||||
ss << other->type() << ":" << other->version() << ":"
|
||||
<< std::hex << other->device() << "; ";
|
||||
}
|
||||
}
|
||||
ALOGE("%s", ss.str().c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
Diagnostics() {}
|
||||
|
||||
static std::mutex mLock;
|
||||
static Diagnostics* mInstance;
|
||||
std::vector<wp<Device>> mDevices;
|
||||
};
|
||||
|
||||
std::mutex Diagnostics::mLock;
|
||||
Diagnostics* Diagnostics::mInstance{nullptr};
|
||||
|
||||
} // namespace
|
||||
|
||||
Device::Device(audio_hw_device_t* device, const char* type)
|
||||
: mDevice{device}, mType{type} {
|
||||
Diagnostics::getInstance().registerDevice(this);
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
|
@ -68,10 +119,12 @@ void Device::closeOutputStream(audio_stream_out_t* stream) {
|
|||
}
|
||||
|
||||
char* Device::halGetParameters(const char* keys) {
|
||||
Diagnostics::getInstance().checkForErasedHalCblk(this);
|
||||
return mDevice->get_parameters(mDevice, keys);
|
||||
}
|
||||
|
||||
int Device::halSetParameters(const char* keysAndValues) {
|
||||
Diagnostics::getInstance().checkForErasedHalCblk(this);
|
||||
return mDevice->set_parameters(mDevice, keysAndValues);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ using ::android::hardware::hidl_string;
|
|||
using ::android::sp;
|
||||
|
||||
struct Device : public IDevice, public ParametersUtil {
|
||||
explicit Device(audio_hw_device_t* device);
|
||||
Device(audio_hw_device_t* device, const char* type);
|
||||
|
||||
// Methods from ::android::hardware::audio::V2_0::IDevice follow.
|
||||
Return<Result> initCheck() override;
|
||||
|
@ -101,17 +101,18 @@ struct Device : public IDevice, public ParametersUtil {
|
|||
void closeInputStream(audio_stream_in_t* stream);
|
||||
void closeOutputStream(audio_stream_out_t* stream);
|
||||
audio_hw_device_t* device() const { return mDevice; }
|
||||
const char* type() const { return mType; }
|
||||
uint32_t version() const { return mDevice->common.version; }
|
||||
|
||||
private:
|
||||
audio_hw_device_t *mDevice;
|
||||
const char* mType;
|
||||
|
||||
virtual ~Device();
|
||||
|
||||
// Methods from ParametersUtil.
|
||||
char* halGetParameters(const char* keys) override;
|
||||
int halSetParameters(const char* keysAndValues) override;
|
||||
|
||||
uint32_t version() const { return mDevice->common.version; }
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
|
|
@ -86,7 +86,7 @@ Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevi
|
|||
result = new PrimaryDevice(halDevice);
|
||||
} else {
|
||||
result = new ::android::hardware::audio::V2_0::implementation::
|
||||
Device(halDevice);
|
||||
Device(halDevice, moduleName);
|
||||
}
|
||||
retval = Result::OK;
|
||||
} else if (halStatus == -EINVAL) {
|
||||
|
|
|
@ -25,8 +25,7 @@ namespace V2_0 {
|
|||
namespace implementation {
|
||||
|
||||
PrimaryDevice::PrimaryDevice(audio_hw_device_t* device)
|
||||
: mDevice(new Device(device)) {
|
||||
}
|
||||
: mDevice{new Device(device, AUDIO_HARDWARE_MODULE_ID_PRIMARY)} {}
|
||||
|
||||
PrimaryDevice::~PrimaryDevice() {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue