Bug 1257738 - part2 : modify logic of requesting audio focus in Android.
authorAlastor Wu <alwu@mozilla.com>
Wed, 01 Jun 2016 10:21:58 +0800
changeset 338851 476e1a1c0ef24aeae3d9382c3cb8700dade99bc6
parent 338850 15ba5d12b73b122aaad76aeeac2f7648d442a31f
child 338852 30d59f3fb7e85ed4eb924aeb1253d9abb714c101
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1257738
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1257738 - part2 : modify logic of requesting audio focus in Android. MozReview-Commit-ID: AG095CIgnA5
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__ */