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
diff --git a/audio/2.0/default/Device.cpp b/audio/2.0/default/Device.cpp
index b696d94..da79238 100644
--- a/audio/2.0/default/Device.cpp
+++ b/audio/2.0/default/Device.cpp
@@ -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 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 @@
}
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);
}
diff --git a/audio/2.0/default/Device.h b/audio/2.0/default/Device.h
index 7738361..55bd0ab 100644
--- a/audio/2.0/default/Device.h
+++ b/audio/2.0/default/Device.h
@@ -56,7 +56,7 @@
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 @@
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:
+ 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
diff --git a/audio/2.0/default/DevicesFactory.cpp b/audio/2.0/default/DevicesFactory.cpp
index b913bc7..b344968 100644
--- a/audio/2.0/default/DevicesFactory.cpp
+++ b/audio/2.0/default/DevicesFactory.cpp
@@ -86,7 +86,7 @@
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) {
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/2.0/default/PrimaryDevice.cpp
index 905203b..af0b249 100644
--- a/audio/2.0/default/PrimaryDevice.cpp
+++ b/audio/2.0/default/PrimaryDevice.cpp
@@ -25,8 +25,7 @@
namespace implementation {
PrimaryDevice::PrimaryDevice(audio_hw_device_t* device)
- : mDevice(new Device(device)) {
-}
+ : mDevice{new Device(device, AUDIO_HARDWARE_MODULE_ID_PRIMARY)} {}
PrimaryDevice::~PrimaryDevice() {}