Merge "audiopolicy: Do not close SoundTrigger input in CloseAllInputs"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index c3dbecc..512a584 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -177,6 +177,7 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
 #endif
+    [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
@@ -1139,7 +1140,10 @@
     }
     audio_extn_perf_lock_release();
 
+    ALOGV("%s: pcm_prepare start", __func__);
+    pcm_prepare(in->pcm);
     ALOGV("%s: exit", __func__);
+
     return ret;
 
 error_open:
@@ -1607,8 +1611,14 @@
             }
             break;
         }
+
         platform_set_stream_channel_map(adev->platform, out->channel_mask,
                                     out->pcm_device_id);
+
+        ALOGV("%s: pcm_prepare start", __func__);
+        if (pcm_is_ready(out->pcm))
+            pcm_prepare(out->pcm);
+
     } else {
         platform_set_stream_channel_map(adev->platform, out->channel_mask,
                                     out->pcm_device_id);
@@ -1651,7 +1661,9 @@
             audio_extn_check_and_set_dts_hpx_state(adev);
         }
     }
+
     ALOGV("%s: exit", __func__);
+
     return 0;
 error_open:
     stop_output_stream(out);
@@ -1787,6 +1799,9 @@
 
     pthread_mutex_lock(&out->lock);
     if (!out->standby) {
+        if (adev->adm_deregister_stream)
+            adev->adm_deregister_stream(adev->adm_data, out->handle);
+
         pthread_mutex_lock(&adev->lock);
         out->standby = true;
         if (!is_offload_usecase(out->usecase)) {
@@ -2139,6 +2154,8 @@
             out->standby = true;
             goto exit;
         }
+        if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
+            adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
     }
 
     if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
@@ -2184,15 +2201,24 @@
         if (out->pcm) {
             if (out->muted)
                 memset((void *)buffer, 0, bytes);
+
             ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+
+            if (adev->adm_request_focus)
+                adev->adm_request_focus(adev->adm_data, out->handle);
+
             if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
                 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
             else
                 ret = pcm_write(out->pcm, (void *)buffer, bytes);
+
             if (ret < 0)
                 ret = -errno;
             else if (ret == 0)
                 out->written += bytes / (out->config.channels * sizeof(short));
+
+            if (adev->adm_abandon_focus)
+                adev->adm_abandon_focus(adev->adm_data, out->handle);
         }
     }
 
@@ -2508,6 +2534,9 @@
     }
 
     if (!in->standby) {
+        if (adev->adm_deregister_stream)
+            adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
+
         pthread_mutex_lock(&adev->lock);
         in->standby = true;
         if (in->pcm) {
@@ -2653,8 +2682,13 @@
             goto exit;
         }
         in->standby = 0;
+        if (adev->adm_register_input_stream)
+            adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
     }
 
+    if (adev->adm_request_focus)
+        adev->adm_request_focus(adev->adm_data, in->capture_handle);
+
     if (in->pcm) {
         if (audio_extn_ssr_get_enabled() &&
                 audio_channel_count_from_in_mask(in->channel_mask) == 6)
@@ -2669,6 +2703,9 @@
             ret = -errno;
     }
 
+    if (adev->adm_abandon_focus)
+        adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
+
     /*
      * Instead of writing zeroes here, we could trust the hardware
      * to always provide zeroes when muted.
@@ -2988,6 +3025,10 @@
         out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
         out->config = pcm_config_afe_proxy_playback;
         adev->voice_tx_output = out;
+    } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
+        out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
+        out->config = pcm_config_low_latency;
+        out->sample_rate = out->config.rate;
     } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
         format = AUDIO_FORMAT_PCM_16_BIT;
         out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
@@ -3457,6 +3498,7 @@
     in->standby = 1;
     in->channel_mask = config->channel_mask;
     in->capture_handle = handle;
+    in->flags = flags;
 
     /* Update config params with the requested sample rate and channels */
     in->usecase = USECASE_AUDIO_RECORD;
@@ -3599,10 +3641,13 @@
         audio_route_free(adev->audio_route);
         free(adev->snd_dev_ref_cnt);
         platform_deinit(adev->platform);
+        if (adev->adm_deinit)
+            adev->adm_deinit(adev->adm_data);
         free(device);
         adev = NULL;
     }
     pthread_mutex_unlock(&adev_init_lock);
+
     return 0;
 }
 
@@ -3614,6 +3659,7 @@
 {
     switch (period_size) {
     case 160:
+    case 192:
     case 240:
     case 320:
     case 480:
@@ -3747,6 +3793,29 @@
         }
     }
 
+    if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
+        adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
+        if (adev->adm_lib == NULL) {
+            ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
+        } else {
+            ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
+            adev->adm_init = (adm_init_t)
+                                    dlsym(adev->adm_lib, "adm_init");
+            adev->adm_deinit = (adm_deinit_t)
+                                    dlsym(adev->adm_lib, "adm_deinit");
+            adev->adm_register_input_stream = (adm_register_input_stream_t)
+                                    dlsym(adev->adm_lib, "adm_register_input_stream");
+            adev->adm_register_output_stream = (adm_register_output_stream_t)
+                                    dlsym(adev->adm_lib, "adm_register_output_stream");
+            adev->adm_deregister_stream = (adm_deregister_stream_t)
+                                    dlsym(adev->adm_lib, "adm_deregister_stream");
+            adev->adm_request_focus = (adm_request_focus_t)
+                                    dlsym(adev->adm_lib, "adm_request_focus");
+            adev->adm_abandon_focus = (adm_abandon_focus_t)
+                                    dlsym(adev->adm_lib, "adm_abandon_focus");
+        }
+    }
+
     adev->bt_wb_speech_enabled = false;
 
     audio_extn_ds2_enable(adev);
@@ -3777,6 +3846,9 @@
 
     pthread_mutex_unlock(&adev_init_lock);
 
+    if (adev->adm_init)
+        adev->adm_data = adev->adm_init();
+
     ALOGV("%s: exit", __func__);
     return 0;
 }
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index f01d38d..983a89e 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -49,6 +49,7 @@
 
 #define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
 #define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
+#define ADM_LIBRARY_PATH "/system/vendor/lib/libadm.so"
 
 /* Flags used to initialize acdb_settings variable that goes to ACDB library */
 #define NONE_FLAG            0x00000000
@@ -93,6 +94,7 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
 #endif
+    USECASE_AUDIO_PLAYBACK_ULL,
 
     /* FM usecase */
     USECASE_AUDIO_PLAYBACK_FM,
@@ -233,6 +235,7 @@
     bool enable_ns;
     audio_format_t format;
     audio_io_handle_t capture_handle;
+    audio_input_flags_t flags;
     bool is_st_session;
     bool is_st_session_active;
 
@@ -285,6 +288,14 @@
     struct stream_app_type_cfg app_type_cfg;
 };
 
+typedef void* (*adm_init_t)();
+typedef void (*adm_deinit_t)(void *);
+typedef void (*adm_register_output_stream_t)(void *, audio_io_handle_t, audio_output_flags_t);
+typedef void (*adm_register_input_stream_t)(void *, audio_io_handle_t, audio_input_flags_t);
+typedef void (*adm_deregister_stream_t)(void *, audio_io_handle_t);
+typedef void (*adm_request_focus_t)(void *, audio_io_handle_t);
+typedef void (*adm_abandon_focus_t)(void *, audio_io_handle_t);
+
 struct audio_device {
     struct audio_hw_device device;
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -326,6 +337,16 @@
     void (*offload_effects_get_parameters)(struct str_parms *,
                                            struct str_parms *);
     void (*offload_effects_set_parameters)(struct str_parms *);
+
+    void *adm_data;
+    void *adm_lib;
+    adm_init_t adm_init;
+    adm_deinit_t adm_deinit;
+    adm_register_input_stream_t adm_register_input_stream;
+    adm_register_output_stream_t adm_register_output_stream;
+    adm_deregister_stream_t adm_deregister_stream;
+    adm_request_focus_t adm_request_focus;
+    adm_abandon_focus_t adm_abandon_focus;
 };
 
 int select_devices(struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 6592c35..934850f 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -281,6 +281,7 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = {-1, -1},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = {-1, -1},
 #endif
+    [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE, MULTIMEDIA3_PCM_DEVICE},
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -664,6 +665,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
 #endif
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index bf5e834..5d0ad2d 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -236,6 +236,7 @@
 #define DEEP_BUFFER_PCM_DEVICE 0
 #define AUDIO_RECORD_PCM_DEVICE 0
 #define MULTIMEDIA2_PCM_DEVICE 1
+#define MULTIMEDIA3_PCM_DEVICE 4
 #define FM_PLAYBACK_PCM_DEVICE 5
 #define FM_CAPTURE_PCM_DEVICE  6
 #define HFP_PCM_RX 5
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 2a3ddba..5a89f16 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -224,7 +224,7 @@
     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
                                            LOWLATENCY_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
-                                        MULTIMEDIA2_PCM_DEVICE},
+                                         MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
 #ifdef MULTIPLE_OFFLOAD_ENABLED
@@ -245,6 +245,9 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] =
                      {PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9},
 #endif
+    [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
+                                    MULTIMEDIA3_PCM_DEVICE},
+
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -596,6 +599,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
 #endif
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 79e0816..4787b86 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -217,6 +217,7 @@
 #define DEEP_BUFFER_PCM_DEVICE 0
 #define AUDIO_RECORD_PCM_DEVICE 0
 #define MULTIMEDIA2_PCM_DEVICE 1
+#define MULTIMEDIA3_PCM_DEVICE 4
 #define FM_PLAYBACK_PCM_DEVICE 5
 #define FM_CAPTURE_PCM_DEVICE  6
 #define HFP_PCM_RX 5