qcom-fm: audio: add support for FM feature

Change-Id: Idd5c7a0364710d54809ef5d4c7b2404b22dc4cf6

Conflicts:

	include/media/IAudioFlinger.h
	media/libmediaplayerservice/StagefrightRecorder.cpp
	media/libstagefright/Android.mk
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 7dd46f2..388ad6c 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -1,5 +1,9 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -730,6 +734,18 @@
                     }
                     delete data;
                     }break;
+#ifdef QCOM_FM_ENABLED
+                case SET_FM_VOLUME: {
+                    FmVolumeData *data = (FmVolumeData *)command->mParam;
+                    ALOGV("AudioCommandThread() processing set fm volume volume %f", data->mVolume);
+                    command->mStatus = AudioSystem::setFmVolume(data->mVolume);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+#endif
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
@@ -885,6 +901,34 @@
     return status;
 }
 
+#ifdef QCOM_FM_ENABLED
+status_t AudioPolicyService::AudioCommandThread::fmVolumeCommand(float volume, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_FM_VOLUME;
+    FmVolumeData *data = new FmVolumeData();
+    data->mVolume = volume;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    ALOGV("AudioCommandThread() adding set fm volume volume %f", volume);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+#endif
+
 // insertCommand_l() must be called with mLock held
 void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
 {
@@ -950,6 +994,12 @@
             removedCommands.add(command2);
             time = command2->mTime;
         } break;
+#ifdef QCOM_FM_ENABLED
+        case SET_FM_VOLUME: {
+            removedCommands.add(command2);
+            time = command2->mTime;
+        } break;
+#endif
         case START_TONE:
         case STOP_TONE:
         default:
@@ -1026,6 +1076,13 @@
                                                    output, delayMs);
 }
 
+#ifdef QCOM_FM_ENABLED
+status_t AudioPolicyService::setFmVolume(float volume, int delayMs)
+{
+    return mAudioCommandThread->fmVolumeCommand(volume, delayMs);
+}
+#endif
+
 int AudioPolicyService::startTone(audio_policy_tone_t tone,
                                   audio_stream_type_t stream)
 {
@@ -1546,6 +1603,15 @@
     return audioPolicyService->setVoiceVolume(volume, delay_ms);
 }
 
+#ifdef QCOM_FM_ENABLED
+static int aps_set_fm_volume(void *service, float volume, int delay_ms)
+{
+    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+    return audioPolicyService->setFmVolume(volume, delay_ms);
+}
+#endif
+
 }; // extern "C"
 
 namespace {
@@ -1565,6 +1631,9 @@
         stop_tone             : aps_stop_tone,
         set_voice_volume      : aps_set_voice_volume,
         move_effects          : aps_move_effects,
+#ifdef QCOM_FM_ENABLED
+        set_fm_volume         : aps_set_fm_volume,
+#endif
         load_hw_module        : aps_load_hw_module,
         open_output_on_module : aps_open_output_on_module,
         open_input_on_module  : aps_open_input_on_module,