Bug 749053 - FM radio support: AudioManager implementation. r=jlebar,mwu
authorSteven Lee <slee@mozilla.com>
Wed, 19 Sep 2012 13:51:35 -0400
changeset 107632 fa535ebebed4a86bbfad0dee4bbdadc13d8543f8
parent 107631 4e0709603af603ce900d2f3922443c2a99218cfd
child 107633 75923725b2fc72927458f6281a78ebaab8f6bc71
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersjlebar, mwu
bugs749053
milestone18.0a1
Bug 749053 - FM radio support: AudioManager implementation. r=jlebar,mwu
dom/system/gonk/AudioManager.cpp
dom/system/gonk/AudioManager.h
dom/system/gonk/nsIAudioManager.idl
media/libsydneyaudio/src/gonk/AudioSystem.h
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -28,16 +28,29 @@ using namespace mozilla;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args) 
 
 #define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
 #define HEADPHONES_STATUS_ON      NS_LITERAL_STRING("on").get()
 #define HEADPHONES_STATUS_OFF     NS_LITERAL_STRING("off").get()
 #define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
 
+static bool
+IsFmRadioAudioOn()
+{
+  if (static_cast<
+      audio_policy_dev_state_t (*) (audio_devices_t, const char *)
+      >(AudioSystem::getDeviceConnectionState)) {
+    return AudioSystem::getDeviceConnectionState(AUDIO_DEVICE_OUT_FM, "") == 
+           AUDIO_POLICY_DEVICE_STATE_AVAILABLE ? true : false;
+  } else {
+    return false;
+  }
+}
+
 NS_IMPL_ISUPPORTS1(AudioManager, nsIAudioManager)
 
 static AudioSystem::audio_devices
 GetRoutingMode(int aType) {
   if (aType == nsIAudioManager::FORCE_SPEAKER) {
     return AudioSystem::DEVICE_OUT_SPEAKER;
   } else if (aType == nsIAudioManager::FORCE_HEADPHONES) {
     return AudioSystem::DEVICE_OUT_WIRED_HEADSET;
@@ -128,16 +141,21 @@ AudioManager::SetMasterVolume(float aMas
 {
   if (AudioSystem::setMasterVolume(aMasterVolume)) {
     return NS_ERROR_FAILURE;
   }
   // For now, just set the voice volume at the same level
   if (AudioSystem::setVoiceVolume(aMasterVolume)) {
     return NS_ERROR_FAILURE;
   }
+
+  if (IsFmRadioAudioOn() && AudioSystem::setFmVolume(aMasterVolume)) {
+    return NS_ERROR_FAILURE;
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AudioManager::GetMasterMuted(bool* aMasterMuted)
 {
   if (AudioSystem::getMasterMute(aMasterMuted)) {
     return NS_ERROR_FAILURE;
@@ -229,10 +247,41 @@ AudioManager::SetAudioRoute(int aRoutes)
     AudioSystem::setParameters(handle, cmd);
   } else if (static_cast<
              status_t (*)(audio_devices_t, audio_policy_dev_state_t, const char*)
              >(AudioSystem::setDeviceConnectionState)) {
     AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET, 
         GetRoutingMode(aRoutes) == AudioSystem::DEVICE_OUT_WIRED_HEADSET ? 
         AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
         "");
+
+    // The audio volume is not consistent when we plug and unplug the headset.
+    // Set the fm volume again here.
+    if (IsFmRadioAudioOn()) {
+      float masterVolume;
+      AudioSystem::getMasterVolume(&masterVolume);
+      AudioSystem::setFmVolume(masterVolume);
+    }
   }
 }
+
+NS_IMETHODIMP
+AudioManager::GetFmRadioAudioEnabled(bool *aFmRadioAudioEnabled)
+{
+  *aFmRadioAudioEnabled = IsFmRadioAudioOn();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
+{
+  if (static_cast<
+      status_t (*) (AudioSystem::audio_devices, AudioSystem::device_connection_state, const char *)
+      >(AudioSystem::setDeviceConnectionState)) {
+    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_FM,
+      aFmRadioAudioEnabled ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : 
+      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
+    InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
+    return NS_OK;
+  } else {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+}
--- a/dom/system/gonk/AudioManager.h
+++ b/dom/system/gonk/AudioManager.h
@@ -40,16 +40,17 @@ class AudioManager : public nsIAudioMana
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIAUDIOMANAGER
 
   AudioManager();
   ~AudioManager();
 
   static void SetAudioRoute(int aRoutes);
+
 protected:
   int32_t mPhoneState;
 
 private:
   nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
 };
 
 } /* namespace gonk */
--- a/dom/system/gonk/nsIAudioManager.idl
+++ b/dom/system/gonk/nsIAudioManager.idl
@@ -18,16 +18,21 @@ interface nsIAudioManager : nsISupports
   attribute float masterVolume;
 
   /**
    * Master volume muted?
    */
   attribute boolean masterMuted;
 
   /**
+   * Are we playing audio from the FM radio?
+   */
+  attribute boolean fmRadioAudioEnabled;
+ 
+  /**
    * Set the phone's audio mode.
    */
   const long PHONE_STATE_INVALID          = -2;
   const long PHONE_STATE_CURRENT          = -1;
   const long PHONE_STATE_NORMAL           = 0;
   const long PHONE_STATE_RINGTONE         = 1;
   const long PHONE_STATE_IN_CALL          = 2;
   const long PHONE_STATE_IN_COMMUNICATION = 3;
--- a/media/libsydneyaudio/src/gonk/AudioSystem.h
+++ b/media/libsydneyaudio/src/gonk/AudioSystem.h
@@ -653,16 +653,18 @@ public:
     static status_t setForceUse(force_use usage, forced_config config);
     static forced_config getForceUse(force_use usage);
     static audio_io_handle_t getOutput(stream_type stream,
                                         uint32_t samplingRate = 0,
                                         uint32_t format = FORMAT_DEFAULT,
                                         uint32_t channels = CHANNEL_OUT_STEREO,
                                         output_flags flags = OUTPUT_FLAG_INDIRECT);
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
+    static status_t setFmVolume(float volume);
+    static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
 #else
     static status_t setForceUse(force_use usage, forced_config config) __attribute__((weak));
     static forced_config getForceUse(force_use usage) __attribute__((weak));
     static audio_io_handle_t getOutput(stream_type stream,
                                         uint32_t samplingRate = 0,
                                         uint32_t format = FORMAT_DEFAULT,
                                         uint32_t channels = CHANNEL_OUT_STEREO,
                                         output_flags flags = OUTPUT_FLAG_INDIRECT) __attribute__((weak));
@@ -670,16 +672,18 @@ public:
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) __attribute__((weak));
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) __attribute__((weak));
     static audio_io_handle_t getOutput(audio_stream_type_t stream,
                                         uint32_t samplingRate = 0,
                                         uint32_t format = AUDIO_FORMAT_DEFAULT,
                                         uint32_t channels = AUDIO_CHANNEL_OUT_STEREO,
                                         audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_INDIRECT) __attribute__((weak));
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) __attribute__((weak));
+    static status_t setFmVolume(float volume) __attribute__((weak));
+    static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address) __attribute__((weak));
 
 #endif
     static status_t startOutput(audio_io_handle_t output,
                                 AudioSystem::stream_type stream,
                                 int session = 0);
     static status_t stopOutput(audio_io_handle_t output,
                                AudioSystem::stream_type stream,
                                int session = 0);