Bug 1235612 - part3 : implement the logic of audible state notification for agent owners.
MozReview-Commit-ID: 6CueLPpuXWm
--- a/dom/fmradio/FMRadio.cpp
+++ b/dom/fmradio/FMRadio.cpp
@@ -9,16 +9,17 @@
#include "mozilla/Hal.h"
#include "mozilla/HalTypes.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/FMRadioBinding.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PFMRadioChild.h"
#include "mozilla/dom/FMRadioService.h"
#include "mozilla/dom/TypedArray.h"
+#include "AudioChannelService.h"
#include "DOMRequest.h"
#include "nsDOMClassInfo.h"
#include "nsIDocShell.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIAudioManager.h"
#undef LOG
#define LOG(args...) FM_LOG("FMRadio", args)
@@ -448,17 +449,18 @@ FMRadio::DisableRDS()
}
void
FMRadio::EnableAudioChannelAgent()
{
NS_ENSURE_TRUE_VOID(mAudioChannelAgent);
AudioPlaybackConfig config;
- nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+ nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config,
+ AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
WindowVolumeChanged(config.mVolume, config.mMuted);
WindowSuspendChanged(config.mSuspend);
mAudioChannelAgentEnabled = true;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3362,16 +3362,20 @@ void HTMLMediaElement::UpdateSrcMediaStr
// called and that will remove all listeners/outputs.
mWatchManager.Unwatch(*mMediaStreamListener,
&HTMLMediaElement::UpdateReadyStateInternal);
mMediaStreamListener->Forget();
mMediaStreamListener = nullptr;
}
+
+ // If the input is a media stream, we don't check its data and always regard
+ // it as audible when it's playing.
+ NotifyAudibleStateChanged(shouldPlay);
}
void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
{
NS_ASSERTION(!mSrcStream && !mMediaStreamListener && !mMediaStreamSizeListener,
"Should have been ended already");
mSrcStream = aStream;
@@ -5056,18 +5060,25 @@ void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// This is needed to pass nsContentUtils::IsCallerChrome().
// AudioChannel API should not called from content but it can happen that
// this method has some content JS in its stack.
AutoNoJSAPI nojsapi;
if (aPlaying) {
+ // The reason we don't call NotifyStartedPlaying after the media element
+ // really becomes audible is because there is another case needs to block
+ // element as early as we can, we would hear sound leaking if we block it
+ // too late. In that case (block autoplay in non-visited-tab), we need to
+ // create a connection before decoding, because we don't want user hearing
+ // any sound.
AudioPlaybackConfig config;
- nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+ nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config,
+ mIsAudioTrackAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
WindowVolumeChanged(config.mVolume, config.mMuted);
WindowSuspendChanged(config.mSuspend);
} else {
mAudioChannelAgent->NotifyStoppedPlaying();
@@ -5613,14 +5624,22 @@ HTMLMediaElement::IsCurrentlyPlaying() c
return false;
}
void
HTMLMediaElement::NotifyAudibleStateChanged(bool aAudible)
{
if (mIsAudioTrackAudible != aAudible) {
mIsAudioTrackAudible = aAudible;
- // To do ...
+ NotifyAudioPlaybackChanged();
+ }
+}
+
+void
+HTMLMediaElement::NotifyAudioPlaybackChanged()
+{
+ if (mAudioChannelAgent) {
+ mAudioChannelAgent->NotifyStartedAudible(mIsAudioTrackAudible);
}
}
} // namespace dom
} // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -443,19 +443,23 @@ public:
{
return mNetworkState;
}
// Called by the media decoder object, on the main thread,
// when the connection between Rtsp server and client gets lost.
virtual void ResetConnectionState() final override;
- // Called by media decoder when the audible state changed.
+ // Called by media decoder when the audible state changed or when input is
+ // a media stream.
virtual void NotifyAudibleStateChanged(bool aAudible) final override;
+ // Notify agent when the MediaElement changes its audible state.
+ void NotifyAudioPlaybackChanged();
+
// XPCOM GetPreload() is OK
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::preload, aValue, aRv);
}
already_AddRefed<TimeRanges> Buffered() const;
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -660,17 +660,18 @@ AudioDestinationNode::InputMuted(bool aM
}
if (aMuted) {
mAudioChannelAgent->NotifyStoppedPlaying();
return;
}
AudioPlaybackConfig config;
- nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+ nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config,
+ AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
WindowVolumeChanged(config.mVolume, config.mMuted);
WindowSuspendChanged(config.mSuspend);
}
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -709,17 +709,18 @@ nsSpeechTask::CreateAudioChannelAgent()
}
mAudioChannelAgent = new AudioChannelAgent();
mAudioChannelAgent->InitWithWeakCallback(mUtterance->GetOwner(),
static_cast<int32_t>(AudioChannelService::GetDefaultAudioChannel()),
this);
AudioPlaybackConfig config;
- nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+ nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config,
+ AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
WindowVolumeChanged(config.mVolume, config.mMuted);
WindowSuspendChanged(config.mSuspend);
}
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2287,17 +2287,18 @@ NPError
if (isMuted) {
rv = agent->NotifyStoppedPlaying();
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
} else {
dom::AudioPlaybackConfig config;
- rv = agent->NotifyStartedPlaying(&config);
+ rv = agent->NotifyStartedPlaying(&config,
+ dom::AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
rv = inst->WindowVolumeChanged(config.mVolume, config.mMuted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -557,17 +557,18 @@ Telephony::HandleAudioAgentState()
rv = mAudioAgent->NotifyStoppedPlaying();
mAudioAgent = nullptr;
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else if (!activeCall.IsNull() && !mIsAudioStartPlaying) {
mIsAudioStartPlaying = true;
AudioPlaybackConfig config;
- rv = mAudioAgent->NotifyStartedPlaying(&config);
+ rv = mAudioAgent->NotifyStartedPlaying(&config,
+ AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// In B2G, the system app manages audio playback policy. If there is a new
// sound want to be playback, it must wait for the permission from the
// system app. It means that the sound would be muted first, and then be
// unmuted. For telephony, the behaviors are hold() first, then resume().