audio: Ensure proper priority and scheduler for service threads
Change audio worker threads priority to ..._URGENT_AUDIO to match
the coupled thread in the audio flinger.
Set SCHED_FIFO scheduler for FAST threads (also to match AF fast
mixer/capture threads). In order to enable that, grand SYS_NICE
capability to the HAL service process and provide "getTid"
function in the StreamWorker class. For testing, add a "FAST"
output to the "stub" module in the HAL configuration.
Bug: 286914845
Test: atest libaudioaidlcommon_test
Test: atest VtsHalAudioCoreTargetTest
Test: adb shell ps -A -T -o PID,TID,NI,PCY,PRI,RTPRIO,SCHED,CMD
for the HAL service process during VTS test. For regular
"reader"/"writer" threads should see 'NI 19, PRI 38',
for FAST "writer" should see 'NI -19, PRI 43, RTPRIO 3, SCH 1'
Change-Id: Iab7e21ebc139ff11cf9b7f4a1645960db8dadd43
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
index 0d2121c..8107655 100644
--- a/audio/aidl/common/StreamWorker.cpp
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -106,6 +106,9 @@
std::lock_guard<std::mutex> lock(mWorkerLock);
mWorkerState = error.empty() ? WorkerState::RUNNING : WorkerState::STOPPED;
mError = error;
+#if defined(__ANDROID__)
+ mTid = pthread_gettid_np(pthread_self());
+#endif
}
mWorkerCv.notify_one();
if (!error.empty()) return;
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
index e9c1070..efdcc81 100644
--- a/audio/aidl/common/include/StreamWorker.h
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -16,6 +16,8 @@
#pragma once
+#include <sys/types.h>
+
#include <atomic>
#include <condition_variable>
#include <mutex>
@@ -52,6 +54,10 @@
std::lock_guard<std::mutex> lock(mWorkerLock);
return mError;
}
+ pid_t getTid() {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ return mTid;
+ }
void stop();
// Direct use of 'join' assumes that the StreamLogic is not intended
// to run forever, and is guaranteed to exit by itself. This normally
@@ -78,6 +84,7 @@
std::condition_variable mWorkerCv;
WorkerState mWorkerState GUARDED_BY(mWorkerLock) = WorkerState::INITIAL;
std::string mError GUARDED_BY(mWorkerLock);
+ pid_t mTid GUARDED_BY(mWorkerLock) = -1;
// The atomic lock-free variable is used to prevent priority inversions
// that can occur when a high priority worker tries to acquire the lock
// which has been taken by a lower priority control thread which in its turn
@@ -143,6 +150,7 @@
void resume() { mThread.resume(); }
bool hasError() { return mThread.hasError(); }
std::string getError() { return mThread.getError(); }
+ pid_t getTid() { return mThread.getTid(); }
void stop() { mThread.stop(); }
void join() { mThread.join(); }
bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
index f7a30b9..2b65740 100644
--- a/audio/aidl/common/tests/streamworker_tests.cpp
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -87,6 +87,7 @@
TEST_P(StreamWorkerInvalidTest, Uninitialized) {
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_FALSE(worker.hasError());
+ EXPECT_LE(worker.getTid(), 0);
}
TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
@@ -105,6 +106,9 @@
EXPECT_FALSE(worker.start());
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_TRUE(worker.hasError());
+#if defined(__ANDROID__)
+ EXPECT_GT(worker.getTid(), 0);
+#endif
}
TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
@@ -136,12 +140,16 @@
TEST_P(StreamWorkerTest, Uninitialized) {
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_FALSE(worker.hasError());
+ EXPECT_LE(worker.getTid(), 0);
}
TEST_P(StreamWorkerTest, Start) {
ASSERT_TRUE(worker.start());
EXPECT_TRUE(worker.waitForAtLeastOneCycle());
EXPECT_FALSE(worker.hasError());
+#if defined(__ANDROID__)
+ EXPECT_GT(worker.getTid(), 0);
+#endif
}
TEST_P(StreamWorkerTest, StartStop) {