diff options
author | Erwin Jansen <jansene@google.com> | 2023-12-06 15:20:49 -0800 |
---|---|---|
committer | Bo Hu <bohu@google.com> | 2024-03-13 07:07:25 -0700 |
commit | 7973c720c6d4b8e7cf0faa58bccd2c74e11b5fe3 (patch) | |
tree | 6e1de56e33266dc9084312a9b2cd64e029a8f380 | |
parent | 2f07781fb357632a5d51431c04505b05f1ff89e4 (diff) | |
download | qemu-7973c720c6d4b8e7cf0faa58bccd2c74e11b5fe3.tar.gz |
Deadlock fix in sensors via event mechanism change
The SensorAPI was using the CallbackRegistry for event registration,
which relies on processing events on a single thread at a high frequency
and in order. This caused the registration buffer to overflow quickly,
leading to deadlocks.
This commit switches the hardware sensors to a different event mechanism that
does not have these limitations, resolving the deadlocks.
Bug: 312677259
Change-Id: I2acfa5e0811eae620a39d9a495eb88030a4fc83e
(cherry picked from commit 58c0478c55b05f1a61ab26255df24609b1b673b6)
-rw-r--r-- | android/android-emu/android-emu.cmake | 1 | ||||
-rw-r--r-- | android/android-emu/android/hw-sensors.cpp | 171 |
2 files changed, 121 insertions, 51 deletions
diff --git a/android/android-emu/android-emu.cmake b/android/android-emu/android-emu.cmake index 70c146a6db..44f692626f 100644 --- a/android/android-emu/android-emu.cmake +++ b/android/android-emu/android-emu.cmake @@ -279,6 +279,7 @@ target_link_libraries( webrtc-yuv android-emu-curl picosha2 + android-grpc-event-waiter # Protobuf dependencies android-emu-protos protobuf::libprotobuf diff --git a/android/android-emu/android/hw-sensors.cpp b/android/android-emu/android/hw-sensors.cpp index 0ffe5609ff..1549febef8 100644 --- a/android/android-emu/android/hw-sensors.cpp +++ b/android/android-emu/android/hw-sensors.cpp @@ -20,7 +20,9 @@ #include <stdlib.h> #include <initializer_list> +#include <memory> #include <string> +#include <unordered_map> #include <vector> #include "aemu/base/async/CallbackRegistry.h" @@ -32,6 +34,7 @@ #include "android/console.h" #include "android/emulation/android_qemud.h" #include "android/emulation/control/adb/AdbInterface.h" +#include "android/emulation/control/utils/EventSupport.h" #include "android/emulation/resizable_display_config.h" #include "android/physics/PhysicalModel.h" #include "android/sensors-port.h" @@ -43,7 +46,6 @@ namespace fc = android::featurecontrol; - #define E(...) derror(__VA_ARGS__) #define W(...) dwarning(__VA_ARGS__) #define D(...) VERBOSE_PRINT(sensors, __VA_ARGS__) @@ -201,9 +203,34 @@ struct HwSensorClient { int32_t delay_ms; }; -static android::base::LazyInstance<android::base::CallbackRegistry> +static android::base::LazyInstance< + android::emulation::control::EventChangeSupport<void>> sSensorChangeCallbackReg = LAZY_INSTANCE_INIT; +class HwSensorChangedCallbackListener + : public android::emulation::control::EventListener<void> { +public: + explicit HwSensorChangedCallbackListener(HwSensorChangedCallback callback, + void* opaque) + : mCallback(callback), mOpaque(opaque) { + sSensorChangeCallbackReg->addListener(this); + } + + ~HwSensorChangedCallbackListener() override { + sSensorChangeCallbackReg->removeListener(this); + } + + void eventArrived() override { mCallback(mOpaque); } + +private: + HwSensorChangedCallback mCallback; + void* mOpaque; +}; + +static std::unordered_map<void*, + std::unique_ptr<HwSensorChangedCallbackListener>> + gSensorListeners; + static void _hwSensorClient_free(HwSensorClient* cl) { /* remove from sensors's list */ if (cl->sensors) { @@ -311,7 +338,8 @@ static void _hwSensorClient_sanitizeSensorString(char* string, int maxlen) { static void serializeValue_float(Sensor* sensor, const char* format, - float value, long measurement_id) { + float value, + long measurement_id) { sensor->serialized.length = snprintf(sensor->serialized.value, sizeof(sensor->serialized.value), format, value, measurement_id); @@ -319,7 +347,8 @@ static void serializeValue_float(Sensor* sensor, static void serializeValue_vec3(Sensor* sensor, const char* format, - vec3 value, long measurement_id) { + vec3 value, + long measurement_id) { sensor->serialized.length = snprintf(sensor->serialized.value, sizeof(sensor->serialized.value), format, value.x, value.y, value.z, measurement_id); @@ -327,10 +356,11 @@ static void serializeValue_vec3(Sensor* sensor, static void serializeValue_vec4(Sensor* sensor, const char* format, - vec4 value, long measurement_id) { - sensor->serialized.length = - snprintf(sensor->serialized.value, sizeof(sensor->serialized.value), - format, value.x, value.y, value.z, value.w, measurement_id); + vec4 value, + long measurement_id) { + sensor->serialized.length = snprintf( + sensor->serialized.value, sizeof(sensor->serialized.value), format, + value.x, value.y, value.z, value.w, measurement_id); } // a function to serialize the sensor value based on its ID @@ -348,8 +378,8 @@ static void serializeSensorValue(PhysicalModel* physical_model, const v current_value = \ GET_FUNCTION_NAME(z)(physical_model, &measurement_id); \ if (measurement_id != sensor->serialized.measurement_id) { \ - SERIALIZE_VALUE_NAME(v)(sensor, w":%ld", current_value, \ - measurement_id); \ + SERIALIZE_VALUE_NAME(v) \ + (sensor, w ":%ld", current_value, measurement_id); \ } \ break; \ } @@ -753,7 +783,7 @@ static void _hwSensors_setPhysicalParameterValue(HwSensors* h, break; } - sSensorChangeCallbackReg->invokeCallbacks(); + sSensorChangeCallbackReg->fireEvent(); } /* get the value of the physical parameter */ @@ -894,12 +924,14 @@ static void _hwSensors_setCoarseOrientation(HwSensors* h, break; case ANDROID_COARSE_REVERSE_LANDSCAPE: - VERBOSE_INFO(rotation, "Setting coarse orientation to reverse landscape"); + VERBOSE_INFO(rotation, + "Setting coarse orientation to reverse landscape"); rotation = {0.f, -tilt_degrees, -90.f}; break; case ANDROID_COARSE_REVERSE_PORTRAIT: - VERBOSE_INFO(rotation, "Setting coarse orientation to reverse portrait"); + VERBOSE_INFO(rotation, + "Setting coarse orientation to reverse portrait"); rotation = {tilt_degrees, 0.f, 180.f}; break; @@ -950,7 +982,9 @@ static void _hwSensors_init(HwSensors* h) { h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD].enabled = true; } - if (getConsoleAgents()->settings->hw()->hw_sensors_magnetic_field_uncalibrated) { + if (getConsoleAgents() + ->settings->hw() + ->hw_sensors_magnetic_field_uncalibrated) { h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD_UNCALIBRATED].enabled = true; } @@ -993,16 +1027,17 @@ static void _hwSensors_init(HwSensors* h) { } } - if (getConsoleAgents()->settings->hw()->hw_sensors_heart_rate || - (avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()) == AVD_WEAR - && avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) >= 28)) { + (avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()) == + AVD_WEAR && + avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) >= 28)) { h->sensors[ANDROID_SENSOR_HEART_RATE].enabled = true; } if (getConsoleAgents()->settings->hw()->hw_sensors_wrist_tilt || - (avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()) == AVD_WEAR - && avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) >= 28)) { + (avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()) == + AVD_WEAR && + avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) >= 28)) { h->sensors[ANDROID_SENSOR_WRIST_TILT].enabled = true; } @@ -1334,11 +1369,13 @@ int android_foldable_get_posture() { } int android_foldable_get_state(struct FoldableState* state) { - return physicalModel_getFoldableState(android_physical_model_instance(), state); + return physicalModel_getFoldableState(android_physical_model_instance(), + state); } bool android_foldable_hinge_configured() { - return (getConsoleAgents()->settings->hw()->hw_sensor_hinge && getConsoleAgents()->settings->hw()->hw_sensor_hinge_count > 0); + return (getConsoleAgents()->settings->hw()->hw_sensor_hinge && + getConsoleAgents()->settings->hw()->hw_sensor_hinge_count > 0); } bool android_foldable_is_pixel_fold() { @@ -1346,7 +1383,8 @@ bool android_foldable_is_pixel_fold() { return true; } const auto devname = getConsoleAgents()->settings->hw()->hw_device_name; - return (devname && "pixel_fold" == std::string(devname) && fc::isEnabled(fc::SupportPixelFold)); + return (devname && "pixel_fold" == std::string(devname) && + fc::isEnabled(fc::SupportPixelFold)); } int android_foldable_pixel_fold_second_display_id() { @@ -1379,32 +1417,54 @@ bool android_foldable_folded_area_configured(int area) { int xOffset, yOffset, width, height; switch (area) { case 0: - xOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_1_xOffset; - yOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_1_yOffset; - width = getConsoleAgents()->settings->hw()->hw_displayRegion_0_1_width; - height = getConsoleAgents()->settings->hw()->hw_displayRegion_0_1_height; + xOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_1_xOffset; + yOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_1_yOffset; + width = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_1_width; + height = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_1_height; break; case 1: - xOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_2_xOffset; - yOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_2_yOffset; - width = getConsoleAgents()->settings->hw()->hw_displayRegion_0_2_width; - height = getConsoleAgents()->settings->hw()->hw_displayRegion_0_2_height; + xOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_2_xOffset; + yOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_2_yOffset; + width = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_2_width; + height = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_2_height; break; case 2: - xOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_3_xOffset; - yOffset = getConsoleAgents()->settings->hw()->hw_displayRegion_0_3_yOffset; - width = getConsoleAgents()->settings->hw()->hw_displayRegion_0_3_width; - height = getConsoleAgents()->settings->hw()->hw_displayRegion_0_3_height; + xOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_3_xOffset; + yOffset = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_3_yOffset; + width = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_3_width; + height = getConsoleAgents() + ->settings->hw() + ->hw_displayRegion_0_3_height; break; default: E("Invalid area %d", area); } - bool enableFoldableByDefault = - !(xOffset < 0 || xOffset > 9999 || - yOffset < 0 || yOffset > 9999 || - width < 1 || width > 9999 || - height < 1 || height > 9999 || - avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) < 28); + bool enableFoldableByDefault = !( + xOffset < 0 || xOffset > 9999 || yOffset < 0 || yOffset > 9999 || + width < 1 || width > 9999 || height < 1 || height > 9999 || + avdInfo_getApiLevel(getConsoleAgents()->settings->avdInfo()) < 28); return enableFoldableByDefault; } @@ -1467,9 +1527,9 @@ bool android_foldable_set_posture(int posture) { bool android_foldable_posture_name(int posture, char* name) { if (!name) { - return false; + return false; } - switch(posture) { + switch (posture) { case 0: strcpy(name, "UNKNOWN"); return true; @@ -1494,16 +1554,19 @@ bool android_foldable_posture_name(int posture, char* name) { } bool android_foldable_get_folded_area(int* x, int* y, int* w, int* h) { - return physicalModel_getFoldedArea(android_physical_model_instance(), x, y, w, h); + return physicalModel_getFoldedArea(android_physical_model_instance(), x, y, + w, h); } bool android_foldable_rollable_configured() { - return (getConsoleAgents()->settings->hw()->hw_sensor_roll && getConsoleAgents()->settings->hw()->hw_sensor_roll_count > 0); + return (getConsoleAgents()->settings->hw()->hw_sensor_roll && + getConsoleAgents()->settings->hw()->hw_sensor_roll_count > 0); } bool android_is_automotive() { if (getConsoleAgents()->settings->android_qemu_mode()) { - AvdFlavor flavor = avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()); + AvdFlavor flavor = + avdInfo_getAvdFlavor(getConsoleAgents()->settings->avdInfo()); return flavor == AVD_ANDROID_AUTO; } return false; @@ -1513,18 +1576,24 @@ bool android_hw_sensors_is_loading_snapshot() { return physicalModel_isLoadingSnapshot(android_physical_model_instance()); } -bool android_heart_rate_sensor_configured(){ - return getConsoleAgents()->settings->hw()->hw_sensors_heart_rate; +bool android_heart_rate_sensor_configured() { + return getConsoleAgents()->settings->hw()->hw_sensors_heart_rate; } void* android_get_posture_listener() { - return physicalModel_getPostureListener(android_physical_model_instance()); + return physicalModel_getPostureListener(android_physical_model_instance()); } -void android_hw_sensors_register_callback(HwSensorChangedCallback callback, void* opaque) { - sSensorChangeCallbackReg->registerCallback(callback, opaque); +void android_hw_sensors_register_callback(HwSensorChangedCallback callback, + void* opaque) { + auto oldSize = gSensorListeners.size(); + gSensorListeners[opaque] = + std::make_unique<HwSensorChangedCallbackListener>(callback, opaque); + assert(oldSize == gSensorListeners.size() - 1); } void android_hw_sensors_unregister_callback(void* opaque) { - sSensorChangeCallbackReg->unregisterCallback(opaque); + auto oldSize = gSensorListeners.size(); + gSensorListeners.erase(opaque); + assert(oldSize == gSensorListeners.size() + 1); } |