Add playback mute notifications for mmap tracks
Added the portId callback to the aaudio client which is registering it
with the AudioService similar to the AudioTrack clients logic.
MMap tracks have a different way of computing the volume. Some volume
components are computed in the aaudioservice. Note that AppOps mute,
client mute and volume shaper mute are not available for AAudio MMap tracks.
Test: dumpsys audio
Bug: 235521198
Change-Id: I05edaa6646cd21647f1602c1ce695be2233a08fc
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 2de878d..07a96b7 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -647,6 +647,8 @@
if (getState() == AAUDIO_STREAM_STATE_STARTING) {
setState(AAUDIO_STREAM_STATE_STARTED);
}
+ mPlayerBase->triggerPortIdUpdate(static_cast<audio_port_handle_t>(
+ message->event.dataLong));
break;
case AAUDIO_SERVICE_EVENT_PAUSED:
ALOGD("%s - got AAUDIO_SERVICE_EVENT_PAUSED", __func__);
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index 446a58c..651255a 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -58,6 +58,20 @@
}
}
+void PlayerBase::triggerPortIdUpdate(audio_port_handle_t portId) const {
+ if (mAudioManager == nullptr) {
+ ALOGE("%s: no audio service, player %d will not update portId %d",
+ __func__,
+ mPIId,
+ portId);
+ return;
+ }
+
+ if (mPIId != PLAYER_PIID_INVALID && portId != AUDIO_PORT_HANDLE_NONE) {
+ mAudioManager->playerEvent(mPIId, android::PLAYER_UPDATE_PORT_ID, portId);
+ }
+}
+
void PlayerBase::baseDestroy() {
serviceReleasePlayer();
if (mAudioManager != 0) {
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 23b6bfd..5475f76 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -53,6 +53,10 @@
void baseUpdateDeviceId(audio_port_handle_t deviceId);
+ /**
+ * Updates the mapping in the AudioService between portId and piid
+ */
+ void triggerPortIdUpdate(audio_port_handle_t portId) const;
protected:
void init(player_type_t playerType, audio_usage_t usage, audio_session_t sessionId);
@@ -74,7 +78,6 @@
// player interface ID, uniquely identifies the player in the system
// effectively const after PlayerBase::init().
audio_unique_id_t mPIId;
-
private:
// report events to AudioService
void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index eb640bb..cb46c52 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -54,6 +54,14 @@
bool getAndSetSilencedNotified_l() { bool silencedNotified = mSilencedNotified;
mSilencedNotified = true;
return silencedNotified; }
+
+ /**
+ * Updates the mute state and notifies the audio service. Call this only when holding player
+ * thread lock.
+ */
+ void processMuteEvent_l(const sp<IAudioManager>& audioManager,
+ mute_state_t muteState)
+ REQUIRES(AudioFlinger::MmapPlaybackThread::mLock);
private:
friend class MmapThread;
@@ -71,5 +79,12 @@
pid_t mPid;
bool mSilenced; // protected by MMapThread::mLock
bool mSilencedNotified; // protected by MMapThread::mLock
+
+ // TODO: replace PersistableBundle with own struct
+ // access these two variables only when holding player thread lock.
+ std::unique_ptr<os::PersistableBundle> mMuteEventExtras
+ GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
+ mute_state_t mMuteState
+ GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
}; // end of Track
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 745dbf2..71c24f3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -10465,6 +10465,14 @@
}
for (const sp<MmapTrack> &track : mActiveTracks) {
track->setMetadataHasChanged();
+ track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ mStreamVolume == 0.f,
+ mStreamMute,
+ // TODO(b/241533526): adjust logic to include mute from AppOps
+ false /*muteFromPlaybackRestricted*/,
+ false /*muteFromClientVolume*/,
+ false /*muteFromVolumeShaper*/});
}
}
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3f9c306..44a93c1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -3140,6 +3140,38 @@
{
}
+void AudioFlinger::MmapThread::MmapTrack::processMuteEvent_l(const sp<
+ IAudioManager>& audioManager, mute_state_t muteState)
+{
+ if (mMuteState == muteState) {
+ // mute state did not change, do nothing
+ return;
+ }
+
+ status_t result = UNKNOWN_ERROR;
+ if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
+ if (mMuteEventExtras == nullptr) {
+ mMuteEventExtras = std::make_unique<os::PersistableBundle>();
+ }
+ mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
+ static_cast<int>(muteState));
+
+ result = audioManager->portEvent(mPortId,
+ PLAYER_UPDATE_MUTED,
+ mMuteEventExtras);
+ }
+
+ if (result == OK) {
+ mMuteState = muteState;
+ } else {
+ ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
+ __func__,
+ id(),
+ mPortId,
+ result);
+ }
+}
+
void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
{
result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 9f48f80..d395c25 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -278,7 +278,7 @@
if (result != AAUDIO_OK) goto error;
// This should happen at the end of the start.
- sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
+ sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED, static_cast<int64_t>(mClientHandle));
setState(AAUDIO_STREAM_STATE_STARTED);
return result;