Merge "Merge 7bc4841db198e3b2d8420301626d89d4e2943c06 on remote branch"
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8e5d64e..e0f9883 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -48,7 +48,7 @@
 #define audio_is_offload_pcm(format) (0)
 #define OFFLOAD_USE_SMALL_BUFFER false
 #else
-#define OFFLOAD_USE_SMALL_BUFFER (info->use_small_bufs)
+#define OFFLOAD_USE_SMALL_BUFFER ((info->format & AUDIO_FORMAT_PCM_OFFLOAD) == AUDIO_FORMAT_PCM_OFFLOAD)
 #endif
 
 #ifndef AFE_PROXY_ENABLED
@@ -97,7 +97,8 @@
 #endif
 
 #ifdef PCM_OFFLOAD_ENABLED_24
-#define PCM_OUTPUT_BIT_WIDTH (config->offload_info.bit_width)
+#define PCM_OUTPUT_BIT_WIDTH (((config->offload_info.format & AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) ==  \
+                             (AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)) ? 24 : CODEC_BACKEND_DEFAULT_BIT_WIDTH)
 #else
 #define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
 #endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
old mode 100644
new mode 100755
index 4b8871d..d0d4dac
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2889,7 +2889,7 @@
         else
             out->compr_config.codec->id =
                 get_snd_codec_id(config->offload_info.format);
-        if (audio_is_offload_pcm(config->offload_info.format)) {
+        if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
             out->compr_config.fragment_size =
                platform_get_pcm_offload_buffer_size(&config->offload_info);
         } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
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,