Bug 1257738 - part2 : modify logic of requesting audio focus in Android. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 01 Jun 2016 10:13:41 +0800
changeset 373688 061e8ca103c5f26e1cc95e54bf1f1848fb1e46b7
parent 373687 61b9af089703c6c1223c436c68a6ad53c3207dfb
child 373689 280d161c1b386be777f9f642653454d424fec118
push id19809
push useralwu@mozilla.com
push dateWed, 01 Jun 2016 02:14:07 +0000
bugs1257738
milestone49.0a1
Bug 1257738 - part2 : modify logic of requesting audio focus in Android. MozReview-Commit-ID: A1pFlPr6YVA
mobile/android/base/java/org/mozilla/gecko/media/AudioFocusAgent.java
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
--- a/mobile/android/base/java/org/mozilla/gecko/media/AudioFocusAgent.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/AudioFocusAgent.java
@@ -11,17 +11,18 @@ import android.media.AudioManager.OnAudi
 import android.util.Log;
 
 public class AudioFocusAgent {
     private static final String LOGTAG = "AudioFocusAgent";
 
     private static Context mContext;
     private AudioManager mAudioManager;
     private OnAudioFocusChangeListener mAfChangeListener;
-    private int mAudibleElementCounts;
+
+    private boolean mIsOwningAudioFocus = false;
 
     @WrapForJNI
     public static void notifyStartedPlaying() {
         if (!isAttachedToContext()) {
             return;
         }
         Log.d(LOGTAG, "NotifyStartedPlaying");
         AudioFocusAgent.getInstance().requestAudioFocusIfNeeded();
@@ -78,44 +79,38 @@ public class AudioFocusAgent {
     private static boolean isAttachedToContext() {
         return (mContext != null);
     }
 
     private void notifyObservers(String topic, String data) {
         GeckoAppShell.notifyObservers(topic, data);
     }
 
-    private AudioFocusAgent() {
-        mAudibleElementCounts = 0;
-    }
+    private AudioFocusAgent() {}
 
     private void requestAudioFocusIfNeeded() {
-        if (!isFirstAudibleElement()) {
+        if (mIsOwningAudioFocus) {
             return;
         }
 
         int result = mAudioManager.requestAudioFocus(mAfChangeListener,
                                                      AudioManager.STREAM_MUSIC,
                                                      AudioManager.AUDIOFOCUS_GAIN);
 
         String focusMsg = (result == AudioManager.AUDIOFOCUS_GAIN) ?
             "AudioFocus request granted" : "AudioFoucs request failed";
         Log.d(LOGTAG, focusMsg);
         // TODO : Enable media control when get the AudioFocus, see bug1240423.
+        if (result == AudioManager.AUDIOFOCUS_GAIN) {
+            mIsOwningAudioFocus = true;
+        }
     }
 
     private void abandonAudioFocusIfNeeded() {
-        if (!isLastAudibleElement()) {
+        if (!mIsOwningAudioFocus) {
             return;
         }
 
         Log.d(LOGTAG, "Abandon AudioFocus");
         mAudioManager.abandonAudioFocus(mAfChangeListener);
-    }
-
-    private boolean isFirstAudibleElement() {
-        return (++mAudibleElementCounts == 1);
-    }
-
-    private boolean isLastAudibleElement() {
-        return (--mAudibleElementCounts == 0);
+        mIsOwningAudioFocus = false;
     }
 }
\ No newline at end of file
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -1641,25 +1641,47 @@ NS_IMETHODIMP nsAndroidBridge::IsContent
 NS_IMETHODIMP
 nsAndroidBridge::Observe(nsISupports* aSubject, const char* aTopic,
                          const char16_t* aData)
 {
   if (!strcmp(aTopic, "xpcom-shutdown")) {
     RemoveObservers();
   } else if (!strcmp(aTopic, "audio-playback")) {
     ALOG_BRIDGE("nsAndroidBridge::Observe, get audio-playback event.");
+
+    nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aSubject);
+    MOZ_ASSERT(window);
+
     nsAutoString activeStr(aData);
-    if (activeStr.EqualsLiteral("active")) {
+    bool isPlaying = activeStr.EqualsLiteral("active");
+
+    UpdateAudioPlayingWindows(window, isPlaying);
+  }
+  return NS_OK;
+}
+
+void
+nsAndroidBridge::UpdateAudioPlayingWindows(nsPIDOMWindowOuter* aWindow,
+                                           bool aPlaying)
+{
+  // Request audio focus for the first audio playing window and abandon focus
+  // for the last audio playing window.
+  if (aPlaying && !mAudioPlayingWindows.Contains(aWindow)) {
+    mAudioPlayingWindows.AppendElement(aWindow);
+    if (mAudioPlayingWindows.Length() == 1) {
+      ALOG_BRIDGE("nsAndroidBridge, request audio focus.");
       AudioFocusAgent::NotifyStartedPlaying();
-    } else {
+    }
+  } else if (!aPlaying && mAudioPlayingWindows.Contains(aWindow)) {
+    mAudioPlayingWindows.RemoveElement(aWindow);
+    if (mAudioPlayingWindows.Length() == 0) {
+      ALOG_BRIDGE("nsAndroidBridge, abandon audio focus.");
       AudioFocusAgent::NotifyStoppedPlaying();
     }
   }
-
-  return NS_OK;
 }
 
 void
 nsAndroidBridge::AddObservers()
 {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->AddObserver(this, "xpcom-shutdown", false);
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -595,12 +595,16 @@ public:
   nsAndroidBridge();
 
 private:
   ~nsAndroidBridge();
 
   void AddObservers();
   void RemoveObservers();
 
+  void UpdateAudioPlayingWindows(nsPIDOMWindowOuter* aWindow, bool aPlaying);
+
+  nsTArray<nsPIDOMWindowOuter*> mAudioPlayingWindows;
+
 protected:
 };
 
 #endif /* AndroidBridge_h__ */