audio: support custom acdb for external device

add the specific external device setting in audio_platform_info.xml

For example:
<external_specific_dev>
    <ext_device name="SND_DEVICE_OUT_USB_HEADSET" usbid="18d1:5034" acdb_id="10" />
</external_specific_dev>

Bug: 117336751
Test: manual test ok
Change-Id: Ie9abcadd9bcd6d06c5d8f0a9807c3935ee4a1d35
Signed-off-by: Carter Hsu <carterhsu@google.com>
Signed-off-by: Robert Lee <lerobert@google.com>
(cherry picked from commit 017c63ae09841070e587d0f9f5c396efcb07e46d)
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 24ed4c5..1688b9d 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1105,6 +1105,7 @@
 bool usb_is_tunnel_supported();
 bool usb_alive(int card);
 bool usb_connected(struct str_parms *parms);
+char *usb_usbid(void);
 unsigned long usb_find_service_interval(bool min, bool playback);
 int usb_altset_for_service_interval(bool is_playback,
                                                unsigned long service_interval,
@@ -1265,6 +1266,15 @@
     return ret_val;
 }
 
+char *audio_extn_usb_usbid(void)
+{
+    char *ret_val = NULL;
+    if (is_usb_offload_enabled)
+        ret_val = usb_usbid();
+
+    return ret_val;
+}
+
 unsigned long audio_extn_usb_find_service_interval(bool min, bool playback)
 {
     unsigned long ret_val = 0;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e1e3ca0..60b2610 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -283,6 +283,7 @@
                                                uint32_t *bit_width,
                                                uint32_t *sample_rate,
                                                uint32_t *channel_count);
+char *audio_extn_usb_usbid(void);
 int audio_extn_usb_set_service_interval(bool playback,
                                         unsigned long service_interval,
                                         bool *reconfig);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 9981ef0..e6859fe 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -55,6 +55,7 @@
 #define SAMPLE_RATE_11025         11025
 #define SAMPLE_RATE_192000        192000
 // Supported sample rates for USB
+#define USBID_SIZE                16
 static uint32_t supported_sample_rates[] =
     {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
 static uint32_t supported_sample_rates_mask[2];
@@ -97,6 +98,7 @@
     int usb_sidetone_vol_min;
     int usb_sidetone_vol_max;
     int endian;
+    char usbid[USBID_SIZE];
 };
 
 struct usb_module {
@@ -620,6 +622,48 @@
     return ret;
 }
 
+static int usb_get_usbid(struct usb_card_config *usb_card_info,
+                              int card)
+{
+    int32_t fd=-1;
+    char path[128];
+    int ret = 0;
+
+    memset(usb_card_info->usbid, 0, sizeof(usb_card_info->usbid));
+
+    ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid",
+             card);
+
+    if (ret < 0) {
+        ALOGE("%s: failed on snprintf (%d) to path %s\n",
+          __func__, ret, path);
+        goto done;
+    }
+
+    fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        ALOGE("%s: error failed to open file %s error: %d\n",
+              __func__, path, errno);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (read(fd, usb_card_info->usbid, USBID_SIZE - 1) < 0) {
+        ALOGE("file read error\n");
+        ret = -EINVAL;
+        usb_card_info->usbid[0] = '\0';
+        goto done;
+    }
+
+    strtok(usb_card_info->usbid, "\n");
+
+done:
+    if (fd >= 0)
+        close(fd);
+
+    return ret;
+}
+
 static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
                                       int card)
 {
@@ -1164,6 +1208,10 @@
     }
     list_init(&usb_card_info->usb_device_conf_list);
     if (usb_output_device(device)) {
+        if (usb_get_usbid(usb_card_info, card) < 0) {
+            ALOGE("parse card %d usbid fail", card);
+        }
+
         if (!usb_get_device_pb_config(usb_card_info, card)){
             usb_card_info->usb_card = card;
             usb_card_info->usb_device_type = device;
@@ -1172,6 +1220,10 @@
             goto exit;
         }
     } else if (usb_input_device(device)) {
+        if (usb_get_usbid(usb_card_info, card) < 0) {
+            ALOGE("parse card %d usbid fail", card);
+        }
+
         if (!usb_get_device_cap_config(usb_card_info, card)) {
             usb_card_info->usb_card = card;
             usb_card_info->usb_device_type = device;
@@ -1485,6 +1537,22 @@
     return usb_connected;
 }
 
+char *usb_usbid()
+{
+    struct usb_card_config *card_info;
+
+    if (usbmod == NULL)
+        return NULL;
+
+    if (list_empty(&usbmod->usb_card_conf_list))
+        return NULL;
+
+    card_info = node_to_item(list_head(&usbmod->usb_card_conf_list),\
+                             struct usb_card_config, list);
+
+    return strdup(card_info->usbid);
+}
+
 void usb_init(void *adev)
 {
     if (usbmod == NULL) {