policy_hal: Enable Direct PCM for 24 bit PCM playback

-Pass correct bit width when creating a direct pcm output.
-Control 16 bit and 24 bit PCM offload request based on
properties.

Change-Id: I1d1c038acb6fd97a228df098383710eb4d27794d
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 24d8f74..839f1eb 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -460,80 +460,43 @@
         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
-
-        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;
-        }
+    //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;
     }
-#endif
-    if (!pcmOffload) {
-
-        bool compressedOffloadDisabled = property_get_bool("audio.offload.compress.disable", false);
-        if (compressedOffloadDisabled) {
-            ALOGI("compressed offload disabled by audio.offload.compress.disable=%d", compressedOffloadDisabled);
-            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)) ||
-            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS))) {
-                ALOGD("offload disabled for multi-channel FLAC/ALAC/WMA/AAC_ADTS clips with sample rate > 48kHz");
-            return false;
-        }
+    //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)) ||
+        ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS))) {
+            ALOGD("offload disabled for multi-channel FLAC/ALAC/WMA/AAC_ADTS 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;
-        }
+    //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;
+    }
 
-        const bool allowOffloadStreamingWithVideo = property_get_bool("av.streaming.offload.enable",
-                                                                   false /*default value*/);
-        if(offloadInfo.has_video && offloadInfo.is_streaming && !allowOffloadStreamingWithVideo) {
-            ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
-            return false;
-        }
-
+    const bool allowOffloadStreamingWithVideo = property_get_bool("av.streaming.offload.enable",
+                                                               false /*default value*/);
+    if (offloadInfo.has_video && offloadInfo.is_streaming && !allowOffloadStreamingWithVideo) {
+        ALOGW("offload disabled by av.streaming.offload.enable %d",allowOffloadStreamingWithVideo);
+        return false;
     }
 
     //If duration is less than minimum value defined in property, return false
+    char propValue[PROPERTY_VALUE_MAX];
     if (property_get("audio.offload.min.duration.secs", propValue, NULL)) {
         if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) {
             ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue);
@@ -545,18 +508,18 @@
         //do not check duration for other audio formats, e.g. dolby AAC/AC3 and amrwb+ formats
         if ((offloadInfo.format == AUDIO_FORMAT_MP3) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) ||
-            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_VORBIS) ||
-#ifdef AUDIO_EXTN_FORMATS_ENABLED
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_FLAC) ||
-            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA) ||
+            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_VORBIS))
+            return false;
+
+#ifdef AUDIO_EXTN_FORMATS_ENABLED
+        if (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA_PRO) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_ALAC) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_APE) ||
-            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS) ||
-#endif
-            pcmOffload)
+            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS))
             return false;
-
+#endif
     }
 
     // Do not allow offloading if one non offloadable effect is enabled. This prevents from
@@ -1334,6 +1297,19 @@
     return false;
 }
 
+bool static isDirectPCMEnabled(int bitWidth)
+{
+    bool directPCMEnabled = false;
+    if (bitWidth == 24 || bitWidth == 32)
+        directPCMEnabled =
+             property_get_bool("audio.offload.pcm.24bit.enable", false);
+    else
+        directPCMEnabled =
+             property_get_bool("audio.offload.pcm.16bit.enable", false);
+
+    return directPCMEnabled;
+}
+
 status_t AudioPolicyManagerCustom::getOutputForAttr(const audio_attributes_t *attr,
                                               audio_io_handle_t *output,
                                               audio_session_t session,
@@ -1349,23 +1325,21 @@
     audio_offload_info_t tOffloadInfo = AUDIO_INFO_INITIALIZER;
 
     bool offloadDisabled = property_get_bool("audio.offload.disable", false);
-    bool pcmOffloadEnabled = false;
+    uint32_t bitWidth = (audio_bytes_per_sample(format) * 8);
 
     if (offloadDisabled) {
         ALOGI("offload disabled by audio.offload.disable=%d", offloadDisabled);
     }
 
-    //read track offload property only if the global offload switch is off.
-    if (!offloadDisabled) {
-         pcmOffloadEnabled = property_get_bool("audio.offload.track.enable", false);
-    }
+    if (!offloadDisabled && (offloadInfo == NULL) &&
+        isDirectPCMEnabled(bitWidth) &&
+        (flags == AUDIO_OUTPUT_FLAG_NONE)) {
 
-    if (offloadInfo == NULL && pcmOffloadEnabled) {
         tOffloadInfo.sample_rate  = samplingRate;
         tOffloadInfo.channel_mask = channelMask;
         tOffloadInfo.format = format;
         tOffloadInfo.stream_type = *stream;
-        tOffloadInfo.bit_width = 16;    //hard coded for PCM_16
+        tOffloadInfo.bit_width = bitWidth;
         if (attr != NULL) {
             ALOGV("found attribute .. setting usage %d ", attr->usage);
             tOffloadInfo.usage = attr->usage;