Merge "hal : Avoid use of small buf flag and bit width info."
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 4f6c83d..858db85 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1033,7 +1033,9 @@
     struct audio_device *adev = in->dev;
     int snd_card_status = get_snd_card_state(adev);
 
-    in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
+    int usecase = platform_update_usecase_from_source(in->source,in->usecase);
+    if (get_usecase_from_list(adev, usecase) == NULL)
+        in->usecase = usecase;
     ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
           __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
 
@@ -1049,8 +1051,13 @@
     if (ret)
         goto error_config;
     else
-        ALOGD("%s: Updated usecase(%d: %s)",
-              __func__, in->usecase, use_case_table[in->usecase]);
+        ALOGV("%s: usecase(%d)", __func__, in->usecase);
+
+    if (get_usecase_from_list(adev, in->usecase) != NULL) {
+        ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
+            __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
+        goto error_config;
+    }
 
     in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
     if (in->pcm_device_id < 0) {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index dfdcf7d..b995883 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -2637,8 +2637,7 @@
                 }
             }
         }
-    } else if (source == AUDIO_SOURCE_FM_RX ||
-               source == AUDIO_SOURCE_FM_RX_A2DP) {
+    } else if (source == AUDIO_SOURCE_FM_TUNER) {
         snd_device = SND_DEVICE_IN_CAPTURE_FM;
     } else if (source == AUDIO_SOURCE_DEFAULT) {
         goto exit;
@@ -2681,7 +2680,7 @@
         } else if (in_device & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET ||
                    in_device & AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET) {
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
-        } else if (in_device & AUDIO_DEVICE_IN_FM_RX) {
+        } else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
             snd_device = SND_DEVICE_IN_CAPTURE_FM;
         } else {
             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
@@ -3359,7 +3358,7 @@
 int platform_update_usecase_from_source(int source, int usecase)
 {
     ALOGV("%s: input source :%d", __func__, source);
-    if(source == AUDIO_SOURCE_FM_RX_A2DP)
+    if(source == AUDIO_SOURCE_FM_TUNER)
         usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
     return usecase;
 }
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 8c1a768..d62d5d3 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -2399,8 +2399,7 @@
                 }
             }
         }
-    } else if (source == AUDIO_SOURCE_FM_RX ||
-               source == AUDIO_SOURCE_FM_RX_A2DP) {
+    } else if (source == AUDIO_SOURCE_FM_TUNER) {
         snd_device = SND_DEVICE_IN_CAPTURE_FM;
     } else if (source == AUDIO_SOURCE_DEFAULT) {
         goto exit;
@@ -2443,7 +2442,7 @@
         } else if (in_device & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET ||
                    in_device & AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET) {
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
-        } else if (in_device & AUDIO_DEVICE_IN_FM_RX) {
+        } else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
             snd_device = SND_DEVICE_IN_CAPTURE_FM;
         } else {
             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
@@ -3124,7 +3123,7 @@
 int platform_update_usecase_from_source(int source, int usecase)
 {
     ALOGV("%s: input source :%d", __func__, source);
-    if(source == AUDIO_SOURCE_FM_RX_A2DP)
+    if(source == AUDIO_SOURCE_FM_TUNER)
         usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
     return usecase;
 }
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index b806bab..960b46e 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -22,6 +22,7 @@
 #define LOG_NDDEBUG 0
 
 #include <errno.h>
+#include <stdlib.h>
 #include <math.h>
 #include <cutils/log.h>
 #include <cutils/str_parms.h>
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 9df7f93..04f58f9 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -35,6 +35,14 @@
 LOCAL_CFLAGS += -DRECORD_PLAY_CONCURRENCY
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD)),true)
+    LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD_24)),true)
+       LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED_24
+endif
+
 LOCAL_MODULE := libaudiopolicymanager
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
old mode 100644
new mode 100755
index 39386bb..381f394
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -351,45 +351,74 @@
         return false;
     }
 #endif
-    // Check if offload has been disabled
-    char propValue[PROPERTY_VALUE_MAX];
-    if (property_get("audio.offload.disable", propValue, "0")) {
-        if (atoi(propValue) != 0) {
-            ALOGV("offload disabled by audio.offload.disable=%s", propValue );
-            return false;
-        }
-    }
-
     // Check if stream type is music, then only allow offload as of now.
     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
     {
         ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
         return false;
     }
-    //check if it's multi-channel AAC (includes sub formats) and FLAC format
-    if ((popcount(offloadInfo.channel_mask) > 2) &&
-       (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) ||
-        ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_VORBIS))) {
-           ALOGD("offload disabled for multi-channel AAC,FLAC and VORBIS format");
-           return false;
-    }
-#ifdef AUDIO_EXTN_FORMATS_ENABLED
-        //check if it's multi-channel FLAC/ALAC/WMA format with sample rate > 48k
-    if ((popcount(offloadInfo.channel_mask) > 2) &&
-        (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_FLAC) ||
-        (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_ALAC) && offloadInfo.sample_rate > 48000) ||
-        (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA) && offloadInfo.sample_rate > 48000) ||
-        (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA_PRO) && offloadInfo.sample_rate > 48000))) {
-            ALOGD("offload disabled for multi-channel FLAC/ALAC/WMA clips with sample rate > 48kHz");
-        return false;
+
+    char propValue[PROPERTY_VALUE_MAX];
+    bool pcmOffload = false;
+#ifdef PCM_OFFLOAD_ENABLED
+    if ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
+        bool prop_enabled = false;
+        if ((AUDIO_FORMAT_PCM_16_BIT_OFFLOAD == offloadInfo.format) &&
+               property_get("audio.offload.pcm.16bit.enable", propValue, NULL)) {
+            prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+        }
+
+#ifdef PCM_OFFLOAD_ENABLED_24
+        if ((AUDIO_FORMAT_PCM_24_BIT_OFFLOAD == offloadInfo.format) &&
+               property_get("audio.offload.pcm.24bit.enable", propValue, NULL)) {
+            prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
         }
 #endif
-    //TODO: enable audio offloading with video when ready
-    const bool allowOffloadWithVideo =
-            property_get_bool("audio.offload.video", false /* default_value */);
-    if (offloadInfo.has_video && !allowOffloadWithVideo) {
-        ALOGV("isOffloadSupported: has_video == true, returning false");
-        return false;
+
+        if (prop_enabled) {
+            ALOGI("PCM offload property is enabled");
+            pcmOffload = true;
+        }
+
+        if (!pcmOffload) {
+            ALOGD("system property not enabled for PCM offload format[%x]",offloadInfo.format);
+            return false;
+        }
+    }
+#endif
+    if (!pcmOffload) {
+        // Check if offload has been disabled
+        if (property_get("audio.offload.disable", propValue, "0")) {
+            if (atoi(propValue) != 0) {
+                ALOGV("offload disabled by audio.offload.disable=%s", propValue );
+                return false;
+            }
+        }
+        //check if it's multi-channel AAC (includes sub formats) and FLAC format
+        if ((popcount(offloadInfo.channel_mask) > 2) &&
+           (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) ||
+            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_VORBIS))) {
+               ALOGD("offload disabled for multi-channel AAC,FLAC and VORBIS format");
+               return false;
+            }
+#ifdef AUDIO_EXTN_FORMATS_ENABLED
+            //check if it's multi-channel FLAC/ALAC/WMA format with sample rate > 48k
+        if ((popcount(offloadInfo.channel_mask) > 2) &&
+            (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_FLAC) ||
+            (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_ALAC) && offloadInfo.sample_rate > 48000) ||
+            (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA) && offloadInfo.sample_rate > 48000) ||
+            (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA_PRO) && offloadInfo.sample_rate > 48000))) {
+                ALOGD("offload disabled for multi-channel FLAC/ALAC/WMA clips with sample rate > 48kHz");
+            return false;
+        }
+#endif
+        //TODO: enable audio offloading with video when ready
+        const bool allowOffloadWithVideo =
+                property_get_bool("audio.offload.video", false /* default_value */);
+        if (offloadInfo.has_video && !allowOffloadWithVideo) {
+            ALOGV("isOffloadSupported: has_video == true, returning false");
+            return false;
+        }
     }
 
     //If duration is less than minimum value defined in property, return false
@@ -1684,6 +1713,33 @@
     return status;
 }
 
+audio_devices_t AudioPolicyManagerCustom::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
+{
+    audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
+    audio_devices_t device = AUDIO_DEVICE_NONE;
+    switch (strategy) {
+        case STRATEGY_SONIFICATION:
+        case STRATEGY_ENFORCED_AUDIBLE:
+        case STRATEGY_ACCESSIBILITY:
+        case STRATEGY_REROUTING:
+        case STRATEGY_MEDIA:
+            if (strategy != STRATEGY_SONIFICATION){
+                // no sonification on WFD sink
+                device |= availableOutputDeviceTypes & AUDIO_DEVICE_OUT_PROXY;
+                if (device != AUDIO_DEVICE_NONE) {
+                    ALOGV("Found proxy for strategy %d", strategy);
+                    return device;
+                }
+            }
+            break;
+        default:
+            ALOGV("getDeviceForStrategy() unknown strategy: %d", strategy);
+            break;
+    }
+    device = AudioPolicyManager::getDeviceForStrategy(strategy, fromCache);
+    return device;
+}
+
 AudioPolicyManagerCustom::AudioPolicyManagerCustom(AudioPolicyClientInterface *clientInterface)
     : AudioPolicyManager(clientInterface)
 {
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 0959429..c8bdb42 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -79,6 +79,8 @@
         // indicates to the audio policy manager that the input stops being used.
         virtual status_t stopInput(audio_io_handle_t input,
                                    audio_session_t session);
+
+        virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache);
 protected:
 
          status_t checkAndSetVolume(audio_stream_type_t stream,