Merge changes I01ad15fa,I428e9f0c,I49ea4d01,I4dcc9f6d,Ibfeb9ae3, ... into sc-dev
* changes:
audiopolicy: avoid unnecessary closure of HOTWORD recording.
audiopolicy: Add support for multiple display ports.
audiopolicy: Wrong device selection for music during concurrency.
audiopolicy: fix voice volume mismatch after headset removal.
nuplayer: handle setPlaybackSettings on direct tracks.
libmedia: modify conditions to reuse track.
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index d2696c7..e60ed55 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -662,9 +662,7 @@
* handle on audio hardware output, or AUDIO_IO_HANDLE_NONE if the
* track needed to be re-created but that failed
*/
-private:
audio_io_handle_t getOutput() const;
-public:
/* Selects the audio device to use for output of this AudioTrack. A value of
* AUDIO_PORT_HANDLE_NONE indicates default (AudioPolicyManager) routing.
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 4d90d98..1d5ccca 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2246,6 +2246,12 @@
mRecycledTrack->frameCount(), t->frameCount());
reuse = false;
}
+ // If recycled and new tracks are not on the same output,
+ // don't reuse the recycled one.
+ if (mRecycledTrack->getOutput() != t->getOutput()) {
+ ALOGV("output has changed, don't reuse track");
+ reuse = false;
+ }
}
if (reuse) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index b2f1b9b..aca4369 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -100,6 +100,7 @@
virtual audio_session_t getSessionId() const;
virtual uint32_t getSampleRate() const;
virtual int64_t getBufferDurationInUs() const;
+ virtual audio_output_flags_t getFlags() const { return mFlags; }
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 8d94698..1cbd8a0 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -108,6 +108,7 @@
virtual audio_stream_type_t getAudioStreamType() const = 0;
virtual uint32_t getSampleRate() const = 0;
virtual int64_t getBufferDurationInUs() const = 0;
+ virtual audio_output_flags_t getFlags() const = 0;
// If no callback is specified, use the "write" API below to submit
// audio data.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 47362ef..344ee0b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -871,10 +871,12 @@
readFromAMessage(msg, &rate);
status_t err = OK;
if (mRenderer != NULL) {
- // AudioSink allows only 1.f and 0.f for offload mode.
- // For other speed, switch to non-offload mode.
- if (mOffloadAudio && ((rate.mSpeed != 0.f && rate.mSpeed != 1.f)
- || rate.mPitch != 1.f)) {
+ // AudioSink allows only 1.f and 0.f for offload and direct modes.
+ // For other speeds, restart audio to fallback to supported paths
+ bool audioDirectOutput = (mAudioSink->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0;
+ if ((mOffloadAudio || audioDirectOutput) &&
+ ((rate.mSpeed != 0.f && rate.mSpeed != 1.f) || rate.mPitch != 1.f)) {
+
int64_t currentPositionUs;
if (getCurrentPosition(¤tPositionUs) != OK) {
currentPositionUs = mPreviousSeekTimeUs;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 82cd6cf..05ec69e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -278,6 +278,8 @@
void dump(String8 *dst, const String8 &tag, int spaces = 0, bool verbose = true) const;
+protected:
+ int do_compare(const void* lhs, const void* rhs) const;
private:
void refreshTypes();
void refreshAudioProfiles();
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 3cfceba..a92d31e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -279,6 +279,23 @@
return ret;
}
+int DeviceVector::do_compare(const void* lhs, const void* rhs) const {
+ const auto ldevice = *reinterpret_cast<const sp<DeviceDescriptor>*>(lhs);
+ const auto rdevice = *reinterpret_cast<const sp<DeviceDescriptor>*>(rhs);
+ int ret = 0;
+
+ // sort by type.
+ ret = compare_type(ldevice->type(), rdevice->type());
+ if (ret != 0)
+ return ret;
+ // for same type higher priority for latest device.
+ ret = compare_type(rdevice->getId(), ldevice->getId());
+ if (ret != 0)
+ return ret;
+ // fallback to default sort using pointer address
+ return SortedVector::do_compare(lhs, rhs);
+}
+
ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
{
ssize_t ret = indexOf(item);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e721a78..340eca4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -272,7 +272,8 @@
mEngine->getActiveMediaDevices(mAvailableOutputDevices);
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
+ if (desc->isActive() && ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) ||
+ (desc != mPrimaryOutput))) {
DeviceVector newDevices = getNewOutputDevices(desc, true /*fromCache*/);
// do not force device change on duplicated output because if device is 0, it will
// also force a device 0 for the two outputs it is duplicated to which may override
@@ -3303,6 +3304,11 @@
void AudioPolicyManager::updateInputRouting() {
for (const auto& activeDesc : mInputs.getActiveInputs()) {
+ // Skip for hotword recording as the input device switch
+ // is handled within sound trigger HAL
+ if (activeDesc->isSoundTrigger() && activeDesc->source() == AUDIO_SOURCE_HOTWORD) {
+ continue;
+ }
auto newDevice = getNewInputDevice(activeDesc);
// Force new input selection if the new device can not be reached via current input
if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
@@ -5720,13 +5726,27 @@
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
StreamTypeVector streams = mEngine->getStreamTypesForProductStrategy(productStrategy);
auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
+ auto hasStreamActive = [&](auto stream) {
+ return hasStream(streams, stream) && isStreamActive(stream, 0);
+ };
- if ((hasVoiceStream(streams) &&
- (isInCall() || mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc)) &&
- !isStreamActive(AUDIO_STREAM_ENFORCED_AUDIBLE, 0)) ||
- ((hasStream(streams, AUDIO_STREAM_ALARM) || hasStream(streams, AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
- mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc)) ||
- outputDesc->isStrategyActive(productStrategy)) {
+ auto doGetOutputDevicesForVoice = [&]() {
+ return hasVoiceStream(streams) && (outputDesc == mPrimaryOutput ||
+ outputDesc->isActive(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) &&
+ (isInCall() ||
+ mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc));
+ };
+
+ // With low-latency playing on speaker, music on WFD, when the first low-latency
+ // output is stopped, getNewOutputDevices checks for a product strategy
+ // from the list, as STRATEGY_SONIFICATION comes prior to STRATEGY_MEDIA.
+ // If an ALARM or ENFORCED_AUDIBLE stream is supported by the product strategy,
+ // devices are returned for STRATEGY_SONIFICATION without checking whether the
+ // stream is associated to the output descriptor.
+ if (doGetOutputDevicesForVoice() || outputDesc->isStrategyActive(productStrategy) ||
+ ((hasStreamActive(AUDIO_STREAM_ALARM) ||
+ hasStreamActive(AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
+ mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) {
// Retrieval of devices for voice DL is done on primary output profile, cannot
// check the route (would force modifying configuration file for this profile)
devices = mEngine->getOutputDevicesForAttributes(attr, nullptr, fromCache);