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/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 385ffbf..1fea100 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -479,14 +479,17 @@
// Mix ports:
// * "test output", 1 max open, 1 max active stream
// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
+// * "test fast output", 1 max open, 1 max active stream
+// - profile PCM 24-bit; STEREO; 44100, 48000
+// * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
+// stream
// - profile MP3; MONO, STEREO; 44100, 48000
// * "test input", 2 max open, 2 max active streams
// - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
//
// Routes:
-// "test output", "compressed offload" -> "Test Out"
+// "test output", "test fast output", "test compressed offload" -> "Test Out"
// "Test In" -> "test input"
//
// Initial port configs:
@@ -525,8 +528,15 @@
{8000, 11025, 16000, 32000, 44100, 48000}));
c.ports.push_back(testOutMix);
+ AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
+ makeBitPositionFlagMask({AudioOutputFlags::FAST}),
+ false, createPortMixExt(1, 1));
+ testFastOutMix.profiles.push_back(createProfile(
+ PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
+ c.ports.push_back(testFastOutMix);
+
AudioPort compressedOffloadOutMix =
- createPort(c.nextPortId++, "compressed offload",
+ createPort(c.nextPortId++, "test compressed offload",
makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
AudioOutputFlags::COMPRESS_OFFLOAD,
AudioOutputFlags::NON_BLOCKING}),
@@ -551,7 +561,8 @@
{8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
c.ports.push_back(testInMIx);
- c.routes.push_back(createRoute({testOutMix, compressedOffloadOutMix}, testOutDevice));
+ c.routes.push_back(
+ createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
c.routes.push_back(createRoute({testInDevice}, testInMIx));
c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 7a617c9..64d53b5 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -27,12 +27,16 @@
using aidl::android::hardware::audio::common::AudioOffloadMetadata;
using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDualMonoMode;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPlaybackRate;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
@@ -610,8 +614,30 @@
ndk::ScopedAStatus StreamCommonImpl::initInstance(
const std::shared_ptr<StreamCommonInterface>& delegate) {
mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
- return mWorker->start() ? ndk::ScopedAStatus::ok()
- : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ if (!mWorker->start()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (auto flags = getContext().getFlags();
+ (flags.getTag() == AudioIoFlags::Tag::input &&
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::input>(),
+ AudioInputFlags::FAST)) ||
+ (flags.getTag() == AudioIoFlags::Tag::output &&
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::FAST))) {
+ // FAST workers should be run with a SCHED_FIFO scheduler, however the host process
+ // might be lacking the capability to request it, thus a failure to set is not an error.
+ pid_t workerTid = mWorker->getTid();
+ if (workerTid > 0) {
+ struct sched_param param;
+ param.sched_priority = 3; // Must match SchedulingPolicyService.PRIORITY_MAX (Java).
+ if (sched_setscheduler(workerTid, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
+ PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler for a fast thread";
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
+ }
+ }
+ return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
index 2068735..757976f 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
@@ -3,7 +3,7 @@
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
- capabilities BLOCK_SUSPEND
+ capabilities BLOCK_SUSPEND SYS_NICE
# setting RLIMIT_RTPRIO allows binder RT priority inheritance
rlimit rtprio 10 10
ioprio rt 4
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index a2edb6f..e74c3ba 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -262,6 +262,7 @@
virtual void setIsConnected(bool isConnected) = 0;
virtual StreamDescriptor::State setClosed() = 0;
virtual bool start() = 0;
+ virtual pid_t getTid() = 0;
virtual void stop() = 0;
};
@@ -277,8 +278,10 @@
void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
StreamDescriptor::State setClosed() override { return WorkerImpl::setClosed(); }
bool start() override {
- return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_AUDIO);
+ // This is an "audio service thread," must have elevated priority.
+ return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}
+ pid_t getTid() override { return WorkerImpl::getTid(); }
void stop() override { return WorkerImpl::stop(); }
};