Spatializer: Cumulative headtracking fixes
Add thread name for proper debugging.
Raise headtracking event thread priority from normal to highest non-realtime.
Raise spatializer looper thread priority from audio to highest non-realtime.
Prevent logspam on error.
Add sensor start / stop logging.
Test: Validate HT works
Bug: 258737281
Merged-In: Idd80929c43a06eaf6480b569384245b8f66f806f
Change-Id: Idd80929c43a06eaf6480b569384245b8f66f806f
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index 3dee40a..31d469c 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -42,6 +42,7 @@
// Identifier to use for our event queue on the loop.
// The number 19 is arbitrary, only useful if using multiple objects on the same looper.
+// Note: Instead of a fixed number, the SensorEventQueue's fd could be used instead.
constexpr int kIdent = 19;
static inline Looper* ALooper_to_Looper(ALooper* alooper) {
@@ -60,7 +61,8 @@
EventQueueGuard(const sp<SensorEventQueue>& queue, Looper* looper) : mQueue(queue) {
mQueue->looper = Looper_to_ALooper(looper);
mQueue->requestAdditionalInfo = false;
- looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT, nullptr, nullptr);
+ looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT,
+ nullptr /* callback */, nullptr /* data */);
}
~EventQueueGuard() {
@@ -75,7 +77,7 @@
[[nodiscard]] SensorEventQueue* get() const { return mQueue.get(); }
private:
- sp<SensorEventQueue> mQueue;
+ const sp<SensorEventQueue> mQueue;
};
/**
@@ -95,10 +97,7 @@
}
}
- SensorEnableGuard(const SensorEnableGuard&) = delete;
- SensorEnableGuard& operator=(const SensorEnableGuard&) = delete;
-
- // Enable moving.
+ // Enable move and delete default copy-ctor/copy-assignment.
SensorEnableGuard(SensorEnableGuard&& other) : mQueue(other.mQueue), mSensor(other.mSensor) {
other.mSensor = SensorPoseProvider::INVALID_HANDLE;
}
@@ -131,7 +130,7 @@
// Figure out the sensor's data format.
DataFormat format = getSensorFormat(sensor);
if (format == DataFormat::kUnknown) {
- ALOGE("Unknown format for sensor %" PRId32, sensor);
+ ALOGE("%s: Unknown format for sensor %" PRId32, __func__, sensor);
return false;
}
@@ -145,17 +144,19 @@
// Enable the sensor.
if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
- ALOGE("Failed to enable sensor");
+ ALOGE("%s: Failed to enable sensor %" PRId32, __func__, sensor);
std::lock_guard lock(mMutex);
mEnabledSensorsExtra.erase(sensor);
return false;
}
- mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue.get(), sensor));
+ mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue, sensor));
+ ALOGD("%s: Sensor %" PRId32 " started", __func__, sensor);
return true;
}
void stopSensor(int handle) override {
+ ALOGD("%s: Sensor %" PRId32 " stopped", __func__, handle);
mEnabledSensors.erase(handle);
std::lock_guard lock(mMutex);
mEnabledSensorsExtra.erase(handle);
@@ -223,9 +224,9 @@
Listener* const mListener;
SensorManager* const mSensorManager;
std::timed_mutex mMutex;
+ sp<SensorEventQueue> mQueue;
std::map<int32_t, SensorEnableGuard> mEnabledSensors;
std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
- sp<SensorEventQueue> mQueue;
// We must do some of the initialization operations on the worker thread, because the API relies
// on the thread-local looper. In addition, as a matter of convenience, we store some of the
@@ -246,7 +247,13 @@
bool waitInitFinished() { return mInitPromise.get_future().get(); }
void threadFunc() {
- // Obtain looper.
+ // Name our std::thread to help identification. As is, canCallJava == false.
+ androidSetThreadName("SensorPoseProvider-looper");
+
+ // Run at the highest non-realtime priority.
+ androidSetThreadPriority(gettid(), PRIORITY_URGENT_AUDIO);
+
+ // The looper is started on the created std::thread.
mLooper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
// Create event queue.
@@ -263,7 +270,8 @@
initFinished(true);
while (!mQuit) {
- int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr, nullptr, nullptr);
+ const int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr /* outFd */,
+ nullptr /* outEvents */, nullptr /* outData */);
switch (ret) {
case ALOOPER_POLL_WAKE:
@@ -276,7 +284,13 @@
break;
default:
- ALOGE("Unexpected status out of Looper::pollOnce: %d", ret);
+ // Besides WAKE and kIdent, there should be no timeouts, callbacks,
+ // ALOOPER_POLL_ERROR, or other events.
+ // Exit now to avoid high frequency log spam on error,
+ // e.g. if the fd becomes invalid (b/31093485).
+ ALOGE("%s: Unexpected status out of Looper::pollOnce: %d", __func__, ret);
+ mQuit = true;
+ continue;
}
// Process an event.
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index ad76202..277c91b 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -263,7 +263,7 @@
mLooper->start(
/*runOnCallingThread*/false,
/*canCallJava*/ false,
- PRIORITY_AUDIO);
+ PRIORITY_URGENT_AUDIO);
mHandler = new EngineCallbackHandler(this);
mLooper->registerHandler(mHandler);