Revert^2 "Reapply "AudioFlinger: Control volume using Port ID""
This reverts commit d3e99d20da87b3a8f0bae64e16f916c0fde85098.
Reason for revert: Internal project fixed with ag/28965993
Test: Treehugger
Bug: 361842578
Change-Id: I76427c29383fa1676de2c3635803a4f16ad9d552
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 2abf682..e5ec5d8 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -146,6 +146,7 @@
"audioflinger-aidl-cpp",
"av-types-aidl-cpp",
"com.android.media.audio-aconfig-cc",
+ "com.android.media.audioserver-aconfig-cc",
"effect-aidl-cpp",
"libactivitymanager_aidl",
"libaudioclient",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 20cd40c..b2c9e32 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -187,6 +187,7 @@
BINDER_METHOD_ENTRY(masterMute) \
BINDER_METHOD_ENTRY(setStreamVolume) \
BINDER_METHOD_ENTRY(setStreamMute) \
+BINDER_METHOD_ENTRY(setPortsVolume) \
BINDER_METHOD_ENTRY(setMode) \
BINDER_METHOD_ENTRY(setMicMute) \
BINDER_METHOD_ENTRY(getMicMute) \
@@ -617,6 +618,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
bool isBitPerfect;
+ float volume;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, adjAttributionSource,
@@ -624,7 +626,8 @@
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs, &isSpatialized,
- &isBitPerfect);
+ &isBitPerfect,
+ &volume);
if (ret != NO_ERROR) {
config->sample_rate = fullConfig.sample_rate;
config->channel_mask = fullConfig.channel_mask;
@@ -1061,6 +1064,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized = false;
bool isBitPerfect = false;
+ float volume;
audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
std::vector<int> effectIds;
@@ -1121,7 +1125,7 @@
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
adjAttributionSource, &input.config, input.flags,
&output.selectedDeviceId, &portId, &secondaryOutputs,
- &isSpatialized, &isBitPerfect);
+ &isSpatialized, &isBitPerfect, &volume);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
@@ -1178,7 +1182,7 @@
if (effectThread == nullptr) {
effectChain = getOrphanEffectChain_l(sessionId);
}
- ALOGV("createTrack() sessionId: %d", sessionId);
+ ALOGV("createTrack() sessionId: %d volume: %f", sessionId, volume);
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
@@ -1193,7 +1197,7 @@
input.sharedBuffer, sessionId, &output.flags,
callingPid, adjAttributionSource, input.clientInfo.clientTid,
&lStatus, portId, input.audioTrackCallback, isSpatialized,
- isBitPerfect, &output.afTrackFlags);
+ isBitPerfect, &output.afTrackFlags, volume);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1644,6 +1648,33 @@
return NO_ERROR;
}
+status_t AudioFlinger::setPortsVolume(
+ const std::vector<audio_port_handle_t>& ports, float volume, audio_io_handle_t output)
+{
+ for (const auto& port : ports) {
+ if (port == AUDIO_PORT_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ }
+ if (isnan(volume) || volume > 1.0f || volume < 0.0f) {
+ return BAD_VALUE;
+ }
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ audio_utils::lock_guard lock(mutex());
+ IAfPlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread != nullptr) {
+ return thread->setPortsVolume(ports, volume);
+ }
+ const sp<IAfMmapThread> mmapThread = checkMmapThread_l(output);
+ if (mmapThread != nullptr && mmapThread->isOutput()) {
+ IAfMmapPlaybackThread *mmapPlaybackThread = mmapThread->asIAfMmapPlaybackThread().get();
+ return mmapPlaybackThread->setPortsVolume(ports, volume);
+ }
+ return BAD_VALUE;
+}
+
status_t AudioFlinger::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
if (output == AUDIO_IO_HANDLE_NONE) {
@@ -3824,8 +3855,7 @@
// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
-sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
-{
+sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const {
sp<VolumeInterface> volumeInterface = mPlaybackThreads.valueFor(output).get();
if (volumeInterface == nullptr) {
IAfMmapThread* const mmapThread = mMmapThreads.valueFor(output).get();
@@ -4020,7 +4050,8 @@
outputFlags,
0ns /* timeout */,
frameCountToBeReady,
- track->getSpeed());
+ track->getSpeed(),
+ track->getPortVolume());
status = patchTrack->initCheck();
if (status != NO_ERROR) {
ALOGE("Secondary output patchTrack init failed: %d", status);
@@ -5119,6 +5150,7 @@
case TransactionCode::GET_AUDIO_MIX_PORT:
case TransactionCode::SET_TRACKS_INTERNAL_MUTE:
case TransactionCode::RESET_REFERENCES_FOR_TEST:
+ case TransactionCode::SET_PORTS_VOLUME:
ALOGW("%s: transaction %d received from PID %d",
__func__, static_cast<int>(code), IPCThreadState::self()->getCallingPid());
// return status only for non void methods
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index adec4aa..902df0a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -96,6 +96,9 @@
status_t setStreamMute(audio_stream_type_t stream, bool muted) final
EXCLUDES_AudioFlinger_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+
status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
status_t setMicMute(bool state) final EXCLUDES_AudioFlinger_Mutex;
@@ -551,6 +554,7 @@
IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const REQUIRES(mutex());
sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const REQUIRES(mutex());
+
std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const REQUIRES(mutex());
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index 4d26aa0..8596acb 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -26,6 +26,7 @@
#include <datapath/AudioStreamIn.h>
#include <datapath/AudioStreamOut.h>
#include <datapath/VolumeInterface.h>
+#include <datapath/VolumePortInterface.h>
#include <fastpath/FastMixerDumpState.h>
#include <media/DeviceDescriptorBase.h>
#include <media/MmapStreamInterface.h>
@@ -479,7 +480,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags)
+ audio_output_flags_t* afTrackFlags,
+ float volume)
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
@@ -555,6 +557,9 @@
virtual void setTracksInternalMute(std::map<audio_port_handle_t, bool>* tracksInternalMute)
EXCLUDES_ThreadBase_Mutex = 0;
+
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfDirectOutputThread : public virtual IAfPlaybackThread {
@@ -694,6 +699,9 @@
AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
+
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index a9c87ad..ee834d6 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -21,6 +21,7 @@
#include <audio_utils/mutex.h>
#include <audiomanager/IAudioManager.h>
#include <binder/IMemory.h>
+#include <datapath/VolumePortInterface.h>
#include <fastpath/FastMixerDumpState.h>
#include <media/AudioSystem.h>
#include <media/VolumeShaper.h>
@@ -254,7 +255,7 @@
};
// Common interface for Playback tracks.
-class IAfTrack : public virtual IAfTrackBase {
+class IAfTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
public:
// FillingStatus is used for suppressing volume ramp at begin of playing
enum FillingStatus { FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE };
@@ -289,7 +290,8 @@
size_t frameCountToBeReady = SIZE_MAX,
float speed = 1.0f,
bool isSpatialized = false,
- bool isBitPerfect = false);
+ bool isBitPerfect = false,
+ float volume = 0.0f);
virtual void pause() = 0;
virtual void flush() = 0;
@@ -452,7 +454,7 @@
virtual ExtendedTimestamp getClientProxyTimestamp() const = 0;
};
-class IAfMmapTrack : public virtual IAfTrackBase {
+class IAfMmapTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
public:
static sp<IAfMmapTrack> create(IAfThreadBase* thread,
const audio_attributes_t& attr,
@@ -463,7 +465,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ float volume = 0.0f);
// protected by MMapThread::mLock
virtual void setSilenced_l(bool silenced) = 0;
@@ -583,7 +586,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed = 1.0f);
+ float speed = 1.0f,
+ float volume = 1.0f);
};
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 85ce142..8758bd0 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -35,7 +35,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ float volume = 0.0f);
~MmapTrack() override;
status_t initCheck() const final;
@@ -65,6 +66,13 @@
void processMuteEvent_l(const sp<IAudioManager>& audioManager,
mute_state_t muteState)
/* REQUIRES(MmapPlaybackThread::mLock) */ final;
+
+ // VolumePortInterface implementation
+ void setPortVolume(float volume) override {
+ mVolume = volume;
+ }
+ float getPortVolume() const override { return mVolume; }
+
private:
DISALLOW_COPY_AND_ASSIGN(MmapTrack);
@@ -87,6 +95,8 @@
/* GUARDED_BY(MmapPlaybackThread::mLock) */;
mute_state_t mMuteState
/* GUARDED_BY(MmapPlaybackThread::mLock) */;
+
+ float mVolume = 0.0f;
}; // end of Track
} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index f57470f..06f7887 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -647,7 +647,8 @@
outputFlags,
{} /*timeout*/,
frameCountToBeReady,
- 1.0f);
+ 1.0f /*speed*/,
+ 1.0f /*volume*/);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 2cc6236..3edeee3 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -96,7 +96,8 @@
size_t frameCountToBeReady = SIZE_MAX,
float speed = 1.0f,
bool isSpatialized = false,
- bool isBitPerfect = false);
+ bool isBitPerfect = false,
+ float volume = 0.0f);
~Track() override;
status_t initCheck() const final;
void appendDumpHeader(String8& result) const final;
@@ -222,6 +223,13 @@
bool getInternalMute() const final { return mInternalMute; }
void setInternalMute(bool muted) final { mInternalMute = muted; }
+
+ // VolumePortInterface implementation
+ void setPortVolume(float volume) override {
+ mVolume = volume;
+ }
+ float getPortVolume() const override { return mVolume; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(Track);
@@ -362,6 +370,8 @@
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
+ void populateUsageAndContentTypeFromStreamType();
+
size_t mPresentationCompleteFrames = 0; // (Used for Mixed tracks)
// The number of frames written to the
// audio HAL when this track is considered fully rendered.
@@ -403,8 +413,8 @@
// access these two variables only when holding player thread lock.
std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
mute_state_t mMuteState;
-
bool mInternalMute = false;
+ float mVolume = 0.0f;
}; // end of Track
@@ -501,7 +511,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed = 1.0f);
+ float speed = 1.0f,
+ float volume = 1.0f);
~PatchTrack() override;
size_t framesReady() const final;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7c7d812..6359846 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -49,6 +49,7 @@
#include <binder/IServiceManager.h>
#include <binder/PersistableBundle.h>
#include <com_android_media_audio.h>
+#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <fastpath/AutoPark.h>
@@ -122,6 +123,7 @@
}
using com::android::media::permission::ValidatedAttributionSourceState;
+namespace audioserver_flags = com::android::media::audioserver;
namespace android {
@@ -2217,17 +2219,18 @@
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
}
-
- for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
- const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
- mStreamTypes[stream].volume = 0.0f;
- mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ if (!audioserver_flags::portid_volume_management()) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+ const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
+ mStreamTypes[stream].volume = 0.0f;
+ mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ }
+ // Audio patch and call assistant volume are always max
+ mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
- // Audio patch and call assistant volume are always max
- mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
PlaybackThread::~PlaybackThread()
@@ -2278,16 +2281,17 @@
void PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
{
String8 result;
-
- result.appendFormat(" Stream volumes in dB: ");
- for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
- const stream_type_t *st = &mStreamTypes[i];
- if (i > 0) {
- result.appendFormat(", ");
- }
- result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
- if (st->mute) {
- result.append("M");
+ if (!audioserver_flags::portid_volume_management()) {
+ result.appendFormat(" Stream volumes in dB: ");
+ for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
+ const stream_type_t *st = &mStreamTypes[i];
+ if (i > 0) {
+ result.appendFormat(", ");
+ }
+ result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
+ if (st->mute) {
+ result.append("M");
+ }
}
}
result.append("\n");
@@ -2395,7 +2399,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t *afTrackFlags)
+ audio_output_flags_t *afTrackFlags,
+ float volume)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2724,7 +2729,7 @@
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
- speed, isSpatialized, isBitPerfect);
+ speed, isSpatialized, isBitPerfect, volume);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2852,6 +2857,22 @@
return mStreamTypes[stream].volume;
}
+status_t PlaybackThread::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume) {
+ audio_utils::lock_guard _l(mutex());
+ for (const auto& portId : portIds) {
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ sp<IAfTrack> track = mTracks[i].get();
+ if (portId == track->portId()) {
+ track->setPortVolume(volume);
+ break;
+ }
+ }
+ }
+ broadcast_l();
+ return NO_ERROR;
+}
+
void PlaybackThread::setVolumeForOutput_l(float left, float right) const
{
mOutput->stream->setVolume(left, right);
@@ -5783,12 +5804,19 @@
}
sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
float volume;
- if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
- volume = 0.f;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
+ volume = 0.f;
+ } else {
+ volume = masterVolume * mStreamTypes[track->streamType()].volume;
+ }
} else {
- volume = masterVolume * mStreamTypes[track->streamType()].volume;
+ if (track->isPlaybackRestricted()) {
+ volume = 0.f;
+ } else {
+ volume = masterVolume * track->getPortVolume();
+ }
}
-
handleVoipVolume_l(&volume);
// cache the combined master volume and stream type volume for fast mixer; this
@@ -5800,15 +5828,23 @@
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
-
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{masterVolume == 0.f,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- vlf == 0.f && vrf == 0.f,
- vh == 0.f});
-
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ }
vlf *= volume;
vrf *= volume;
@@ -5959,16 +5995,22 @@
uint32_t vl, vr; // in U8.24 integer format
float vlf, vrf, vaf; // in [0.0, 1.0] float format
// read original volumes with volume control
- float v = masterVolume * mStreamTypes[track->streamType()].volume;
// Always fetch volumeshaper volume to ensure state is updated.
const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
const float vh = track->getVolumeHandler()->getVolume(
track->audioTrackServerProxy()->framesReleased()).first;
-
- if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
- v = 0;
+ float v;
+ if (!audioserver_flags::portid_volume_management()) {
+ v = masterVolume * mStreamTypes[track->streamType()].volume;
+ if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
+ v = 0;
+ }
+ } else {
+ v = masterVolume * track->getPortVolume();
+ if (track->isPlaybackRestricted()) {
+ v = 0;
+ }
}
-
handleVoipVolume_l(&v);
if (track->isPausing()) {
@@ -5988,15 +6030,23 @@
ALOGV("Track right volume out of range: %.3g", vrf);
vrf = GAIN_FLOAT_UNITY;
}
-
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{masterVolume == 0.f,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- vlf == 0.f && vrf == 0.f,
- vh == 0.f});
-
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ }
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
vrf *= v * vh;
@@ -6722,34 +6772,64 @@
const bool clientVolumeMute = (left == 0.f && right == 0.f);
- if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
- left = right = 0;
- } else {
- float typeVolume = mStreamTypes[track->streamType()].volume;
- const float v = mMasterVolume * typeVolume * shaperVolume;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (mMasterMute || mStreamTypes[track->streamType()].mute ||
+ track->isPlaybackRestricted()) {
+ left = right = 0;
+ } else {
+ float typeVolume = mStreamTypes[track->streamType()].volume;
+ const float v = mMasterVolume * typeVolume * shaperVolume;
- if (left > GAIN_FLOAT_UNITY) {
- left = GAIN_FLOAT_UNITY;
- }
- if (right > GAIN_FLOAT_UNITY) {
- right = GAIN_FLOAT_UNITY;
- }
- left *= v;
- right *= v;
- if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ if (left > GAIN_FLOAT_UNITY) {
+ left = GAIN_FLOAT_UNITY;
+ }
+ if (right > GAIN_FLOAT_UNITY) {
+ right = GAIN_FLOAT_UNITY;
+ }
+ left *= v;
+ right *= v;
+ if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
|| audio_channel_count_from_out_mask(mChannelMask) > 1) {
- left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
- right *= mMasterBalanceRight;
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
}
- }
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ clientVolumeMute,
+ shaperVolume == 0.f});
+ } else {
+ if (mMasterMute || track->isPlaybackRestricted()) {
+ left = right = 0;
+ } else {
+ float typeVolume = track->getPortVolume();
+ const float v = mMasterVolume * typeVolume * shaperVolume;
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{mMasterMute,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- clientVolumeMute,
- shaperVolume == 0.f});
+ if (left > GAIN_FLOAT_UNITY) {
+ left = GAIN_FLOAT_UNITY;
+ }
+ if (right > GAIN_FLOAT_UNITY) {
+ right = GAIN_FLOAT_UNITY;
+ }
+ left *= v;
+ right *= v;
+ if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ || audio_channel_count_from_out_mask(mChannelMask) > 1) {
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
+ }
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ clientVolumeMute,
+ shaperVolume == 0.f});
+ }
if (lastTrack) {
track->setFinalVolume(left, right);
@@ -7843,7 +7923,9 @@
ALOGE("addOutputTrack() initCheck failed %d", status);
return;
}
- thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ if (!audioserver_flags::portid_volume_management()) {
+ thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ }
mOutputTracks.add(outputTrack);
ALOGV("addOutputTrack() track %p, on thread %p", outputTrack.get(), thread);
updateWaitTime_l();
@@ -10330,6 +10412,7 @@
const auto localSessionId = mSessionId;
auto localAttr = mAttr;
+ float volume = 0.0f;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
@@ -10353,7 +10436,8 @@
&portId,
&secondaryOutputs,
&isSpatialized,
- &isBitPerfect);
+ &isBitPerfect,
+ &volume);
mutex().lock();
mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
@@ -10422,7 +10506,8 @@
this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
mChannelMask, mSessionId, isOutput(),
client.attributionSource,
- IPCThreadState::self()->getCallingPid(), portId);
+ IPCThreadState::self()->getCallingPid(), portId,
+ volume);
if (!isOutput()) {
track->setSilenced_l(isClientSilenced_l(portId));
}
@@ -11007,18 +11092,18 @@
mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
mMasterVolume = afThreadCallback->masterVolume_l();
mMasterMute = afThreadCallback->masterMute_l();
-
- for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
- const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
- mStreamTypes[stream].volume = 0.0f;
- mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ if (!audioserver_flags::portid_volume_management()) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+ const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
+ mStreamTypes[stream].volume = 0.0f;
+ mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ }
+ // Audio patch and call assistant volume are always max
+ mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
- // Audio patch and call assistant volume are always max
- mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
-
if (mAudioHwDev) {
if (mAudioHwDev->canSetMasterVolume()) {
mMasterVolume = 1.0;
@@ -11097,6 +11182,21 @@
}
}
+status_t MmapPlaybackThread::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume) {
+ audio_utils::lock_guard _l(mutex());
+ for (const auto& portId : portIds) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
+ if (portId == track->portId()) {
+ track->setPortVolume(volume);
+ break;
+ }
+ }
+ }
+ broadcast_l();
+ return NO_ERROR;
+}
+
void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
audio_utils::lock_guard _l(mutex());
@@ -11130,14 +11230,26 @@
void MmapPlaybackThread::processVolume_l()
NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
- float volume;
-
- if (mMasterMute || streamMuted_l()) {
- volume = 0;
+ float volume = 0;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (mMasterMute || streamMuted_l()) {
+ volume = 0;
+ } else {
+ volume = mMasterVolume * streamVolume_l();
+ }
} else {
- volume = mMasterVolume * streamVolume_l();
+ if (mMasterMute) {
+ volume = 0;
+ } else {
+ // All mmap tracks are declared with the same audio attributes to the audio policy
+ // manager. Hence, they follow the same routing / volume group. Any change of volume
+ // will be broadcasted to all tracks. Thus, take arbitrarily first track volume.
+ size_t numtracks = mActiveTracks.size();
+ if (numtracks) {
+ volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ }
+ }
}
-
if (volume != mHalVolFloat) {
// Convert volumes from float to 8.24
uint32_t vol = (uint32_t)(volume * (1 << 24));
@@ -11170,14 +11282,25 @@
}
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->setMetadataHasChanged();
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{mMasterMute,
- streamVolume_l() == 0.f,
- streamMuted_l(),
- // TODO(b/241533526): adjust logic to include mute from AppOps
- false /*muteFromPlaybackRestricted*/,
- false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ streamVolume_l() == 0.f,
+ streamMuted_l(),
+ // TODO(b/241533526): adjust logic to include mute from AppOps
+ false /*muteFromPlaybackRestricted*/,
+ false /*muteFromClientVolume*/,
+ false /*muteFromVolumeShaper*/});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ // TODO(b/241533526): adjust logic to include mute from AppOps
+ false /*muteFromPlaybackRestricted*/,
+ false /*muteFromClientVolume*/,
+ false /*muteFromVolumeShaper*/});
+ }
}
}
}
@@ -11284,9 +11407,13 @@
void MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MmapThread::dumpInternals_l(fd, args);
-
- dprintf(fd, " Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n",
- mStreamType, streamVolume_l(), mHalVolFloat, streamMuted_l());
+ if (!audioserver_flags::portid_volume_management()) {
+ dprintf(fd, " Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d",
+ mStreamType, streamVolume_l(), mHalVolFloat, streamMuted_l());
+ } else {
+ dprintf(fd, " HAL volume: %f", mHalVolFloat);
+ }
+ dprintf(fd, "\n");
dprintf(fd, " Master volume: %f Master mute %d\n", mMasterVolume, mMasterMute);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 654b841..89e41c8 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -836,6 +836,12 @@
typename SortedVector<sp<T>>::iterator end() {
return mActiveTracks.end();
}
+ typename SortedVector<const sp<T>>::iterator begin() const {
+ return mActiveTracks.begin();
+ }
+ typename SortedVector<const sp<T>>::iterator end() const {
+ return mActiveTracks.end();
+ }
// Due to Binder recursion optimization, clear() and updatePowerState()
// cannot be called from a Binder thread because they may call back into
@@ -1011,6 +1017,9 @@
void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ final EXCLUDES_ThreadBase_Mutex;
+
void setVolumeForOutput_l(float left, float right) const final;
sp<IAfTrack> createTrack_l(
@@ -1035,7 +1044,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags) final
+ audio_output_flags_t* afTrackFlags,
+ float volume) final
REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isTrackActive(const sp<IAfTrack>& track) const final {
@@ -2385,6 +2395,8 @@
void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ final EXCLUDES_ThreadBase_Mutex;
void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index a0b85f7..1342b7b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -347,7 +347,7 @@
size_t mBufferSize; // size of mBuffer in bytes
// we don't really need a lock for these
MirroredVariable<track_state> mState;
- const audio_attributes_t mAttr;
+ audio_attributes_t mAttr;
const uint32_t mSampleRate; // initial sample rate only; for tracks which
// support dynamic rates, the current value is in control block
const audio_format_t mFormat;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f5f11cc..51e140d 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -715,7 +715,8 @@
size_t frameCountToBeReady,
float speed,
bool isSpatialized,
- bool isBitPerfect) {
+ bool isBitPerfect,
+ float volume) {
return sp<Track>::make(thread,
client,
streamType,
@@ -736,7 +737,8 @@
frameCountToBeReady,
speed,
isSpatialized,
- isBitPerfect);
+ isBitPerfect,
+ volume);
}
// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
@@ -761,7 +763,8 @@
size_t frameCountToBeReady,
float speed,
bool isSpatialized,
- bool isBitPerfect)
+ bool isBitPerfect,
+ float volume)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -797,7 +800,8 @@
mFlags(flags),
mSpeed(speed),
mIsSpatialized(isSpatialized),
- mIsBitPerfect(isBitPerfect)
+ mIsBitPerfect(isBitPerfect),
+ mVolume(volume)
{
// client == 0 implies sharedBuffer == 0
ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
@@ -843,6 +847,14 @@
thread->fastTrackAvailMask_l() &= ~(1 << i);
}
+ populateUsageAndContentTypeFromStreamType();
+
+ // Audio patch and call assistant volume are always max
+ if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
+ || mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+ mVolume = 1.0f;
+ }
+
mServerLatencySupported = checkServerLatencySupported(format, flags);
#ifdef TEE_SINK
mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
@@ -865,6 +877,62 @@
mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
+// When attributes are undefined, derive default values from stream type.
+// See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
+void Track::populateUsageAndContentTypeFromStreamType() {
+ if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
+ switch (mStreamType) {
+ case AUDIO_STREAM_VOICE_CALL:
+ mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_SYSTEM:
+ mAttr.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_RING:
+ mAttr.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_MUSIC:
+ mAttr.usage = AUDIO_USAGE_MEDIA;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ break;
+ case AUDIO_STREAM_ALARM:
+ mAttr.usage = AUDIO_USAGE_ALARM;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_NOTIFICATION:
+ mAttr.usage = AUDIO_USAGE_NOTIFICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_DTMF:
+ mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ mAttr.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_ASSISTANT:
+ mAttr.usage = AUDIO_USAGE_ASSISTANT;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_REROUTING:
+ case AUDIO_STREAM_PATCH:
+ mAttr.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
+ // unknown content type
+ break;
+ case AUDIO_STREAM_CALL_ASSISTANT:
+ mAttr.usage = AUDIO_USAGE_CALL_ASSISTANT;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
Track::~Track()
{
ALOGV("%s(%d)", __func__, mId);
@@ -923,7 +991,7 @@
result.appendFormat("Type Id Active Client Session Port Id S Flags "
" Format Chn mask SRate "
"ST Usg CT "
- " G db L dB R dB VS dB "
+ " G db L dB R dB VS dB PortVol dB "
" Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
"%s\n",
isServerLatencySupported() ? " Latency" : "");
@@ -1009,7 +1077,7 @@
result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
"%08X %08X %6u "
"%2u %3x %2x "
- "%5.2g %5.2g %5.2g %5.2g%c "
+ "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
"%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
active ? "yes" : "no",
(mClient == 0) ? getpid() : mClient->pid(),
@@ -1031,6 +1099,7 @@
20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
+ 20.0 * log10(mVolume),
mCblk->mServer,
bufferSizeInFrames,
@@ -1587,59 +1656,6 @@
.gain = mFinalVolume,
};
- // When attributes are undefined, derive default values from stream type.
- // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
- if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
- switch (mStreamType) {
- case AUDIO_STREAM_VOICE_CALL:
- metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_SYSTEM:
- metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_RING:
- metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_MUSIC:
- metadata.base.usage = AUDIO_USAGE_MEDIA;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
- break;
- case AUDIO_STREAM_ALARM:
- metadata.base.usage = AUDIO_USAGE_ALARM;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_NOTIFICATION:
- metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_DTMF:
- metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_ACCESSIBILITY:
- metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_ASSISTANT:
- metadata.base.usage = AUDIO_USAGE_ASSISTANT;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_REROUTING:
- metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
- // unknown content type
- break;
- case AUDIO_STREAM_CALL_ASSISTANT:
- metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- default:
- break;
- }
- }
-
metadata.channel_mask = mChannelMask;
strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
*backInserter++ = metadata;
@@ -2191,14 +2207,13 @@
size_t frameCount,
const AttributionSourceState& attributionSource)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
- audio_attributes_t{} /* currently unused for output track */,
+ AUDIO_ATTRIBUTES_INITIALIZER ,
sampleRate, format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread)
{
-
if (mCblk != NULL) {
mOutBuffer.frameCount = 0;
playbackThread->addOutputTrack_l(this);
@@ -2464,7 +2479,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed)
+ float speed,
+ float volume)
{
return sp<PatchTrack>::make(
playbackThread,
@@ -2478,7 +2494,8 @@
flags,
timeout,
frameCountToBeReady,
- speed);
+ speed,
+ volume);
}
PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
@@ -2492,13 +2509,15 @@
audio_output_flags_t flags,
const Timeout& timeout,
size_t frameCountToBeReady,
- float speed)
+ float speed,
+ float volume)
: Track(playbackThread, NULL, streamType,
- audio_attributes_t{} /* currently unused for patch track */,
+ AUDIO_ATTRIBUTES_INITIALIZER,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
- TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
+ TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
+ false /*isSpatialized*/, false /*isBitPerfect*/, volume),
PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
true /*clientInServer*/) : nullptr,
playbackThread, timeout)
@@ -3482,7 +3501,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ float volume)
{
return sp<MmapTrack>::make(
thread,
@@ -3494,7 +3514,8 @@
isOut,
attributionSource,
creatorPid,
- portId);
+ portId,
+ volume);
}
MmapTrack::MmapTrack(IAfThreadBase* thread,
@@ -3506,7 +3527,8 @@
bool isOut,
const AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ float volume)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
@@ -3517,10 +3539,15 @@
TYPE_DEFAULT, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
- mSilenced(false), mSilencedNotified(false)
+ mSilenced(false), mSilencedNotified(false), mVolume(volume)
{
// Once this item is logged by the server, the client can add properties.
mTrackMetrics.logConstructor(creatorPid, uid(), id());
+ if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
+ || attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
+ // Audio patch and call assistant volume are always max
+ mVolume = 1.0f;
+ }
}
MmapTrack::~MmapTrack()
@@ -3599,8 +3626,8 @@
void MmapTrack::appendDumpHeader(String8& result) const
{
- result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
- isOut() ? "Usg CT": "Source");
+ result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s %s\n",
+ isOut() ? "Usg CT": "Source", isOut() ? "PortVol dB" : "");
}
void MmapTrack::appendDump(String8& result, bool active __unused) const
@@ -3615,6 +3642,7 @@
mAttr.flags);
if (isOut()) {
result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
+ result.appendFormat("%11.2g", 20.0 * log10(mVolume));
} else {
result.appendFormat("%6x", mAttr.source);
}
diff --git a/services/audioflinger/datapath/VolumePortInterface.h b/services/audioflinger/datapath/VolumePortInterface.h
new file mode 100644
index 0000000..fb1c463
--- /dev/null
+++ b/services/audioflinger/datapath/VolumePortInterface.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+
+namespace android {
+
+class VolumePortInterface : public virtual RefBase {
+public:
+ virtual void setPortVolume(float volume) = 0;
+ virtual float getPortVolume() const = 0;
+};
+
+} // namespace android