audio policy: added rules for USB audio devices

Change-Id: If712b0c7fcf281d66d34614529f3433e56e058fb
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp
index 6c1e424..076a593 100644
--- a/audio/AudioPolicyManagerBase.cpp
+++ b/audio/AudioPolicyManagerBase.cpp
@@ -53,6 +53,10 @@
             ALOGE("setDeviceConnectionState() invalid device: %x", device);
             return BAD_VALUE;
         }
+        if (!mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
+            ALOGE("setDeviceConnectionState() invalid device: %x", device);
+            return BAD_VALUE;
+        }
 
         switch (state)
         {
@@ -83,6 +87,9 @@
                 ALOGV("setDeviceConnectionState() BT SCO  device, address %s", device_address);
                 // keep track of SCO device address
                 mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
+            } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
+                mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
+                mpClientInterface->setParameters(output, mUsbCardAndDevice);
             }
             break;
         // handle output device disconnection
@@ -104,6 +111,8 @@
                 mA2dpSuspended = false;
             } else if (AudioSystem::isBluetoothScoDevice(device)) {
                 mScoDeviceAddress = "";
+            } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) {
+                mUsbCardAndDevice = "";
             }
             } break;
 
@@ -199,6 +208,11 @@
                 address != "" && mScoDeviceAddress != address) {
                 return state;
             }
+            if (audio_is_usb_device((audio_devices_t)device) &&
+                (!mHasUsb || (address != "" && mUsbCardAndDevice != address))) {
+                ALOGE("setDeviceConnectionState() invalid device: %x", device);
+                return state;
+            }
             state = AudioSystem::DEVICE_STATE_AVAILABLE;
         }
     } else if (AudioSystem::isInputDevice(device)) {
@@ -1095,6 +1109,8 @@
     result.append(buffer);
     snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
     result.append(buffer);
+    snprintf(buffer, SIZE, " USB audio ALSA %s\n", mUsbCardAndDevice.string());
+    result.append(buffer);
     snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
     result.append(buffer);
     snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
@@ -1177,7 +1193,7 @@
     mPhoneState(AudioSystem::MODE_NORMAL),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
-    mA2dpSuspended(false), mHasA2dp(false)
+    mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false)
 {
     mpClientInterface = clientInterface;
 
@@ -1189,6 +1205,7 @@
 
     mA2dpDeviceAddress = String8("");
     mScoDeviceAddress = String8("");
+    mUsbCardAndDevice = String8("");
 
     if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
         ALOGE("could not load audio policy configuration file");
@@ -1911,6 +1928,10 @@
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
                 if (device) break;
             }
+            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+            if (device) break;
+            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+            if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
             if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
@@ -1932,6 +1953,10 @@
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                 if (device) break;
             }
+            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+            if (device) break;
+            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+            if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
             if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
@@ -1986,6 +2011,12 @@
             }
         }
         if (device2 == 0) {
+            device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+        }
+        if (device2 == 0) {
+            device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+        }
+        if (device2 == 0) {
             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
         }
         if (device2 == 0) {
@@ -2244,6 +2275,8 @@
         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
         case AUDIO_DEVICE_OUT_AUX_DIGITAL:
+        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+        case AUDIO_DEVICE_OUT_USB_DEVICE:
         default:
             return DEVICE_CATEGORY_SPEAKER;
     }
@@ -2379,7 +2412,9 @@
     if (stream == AudioSystem::MUSIC &&
         index != mStreams[stream].mIndexMin &&
         (device == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
-        device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
+         device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ||
+         device == AUDIO_DEVICE_OUT_USB_ACCESSORY ||
+         device == AUDIO_DEVICE_OUT_USB_DEVICE)) {
         return 1.0;
     }
 
@@ -2863,12 +2898,16 @@
     if (mOutputProfiles.size()) {
         write(fd, "  - outputs:\n", sizeof("  - outputs:\n"));
         for (size_t i = 0; i < mOutputProfiles.size(); i++) {
+            snprintf(buffer, SIZE, "    output %d:\n", i);
+            write(fd, buffer, strlen(buffer));
             mOutputProfiles[i]->dump(fd);
         }
     }
     if (mInputProfiles.size()) {
         write(fd, "  - inputs:\n", sizeof("  - inputs:\n"));
         for (size_t i = 0; i < mInputProfiles.size(); i++) {
+            snprintf(buffer, SIZE, "    input %d:\n", i);
+            write(fd, buffer, strlen(buffer));
             mInputProfiles[i]->dump(fd);
         }
     }
@@ -2993,6 +3032,10 @@
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
@@ -3236,7 +3279,10 @@
     if (node != NULL) {
         if (strcmp(root->name, AUDIO_HARDWARE_MODULE_ID_A2DP) == 0) {
             mHasA2dp = true;
+        } else if (strcmp(root->name, AUDIO_HARDWARE_MODULE_ID_USB) == 0) {
+            mHasUsb = true;
         }
+
         node = node->first_child;
         while (node) {
             ALOGV("loadHwModule() loading output %s", node->name);
diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h
index 6f6451b..bdfa753 100644
--- a/include/hardware_legacy/AudioPolicyManagerBase.h
+++ b/include/hardware_legacy/AudioPolicyManagerBase.h
@@ -487,6 +487,8 @@
         StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES];           // stream descriptors for volume control
         String8 mA2dpDeviceAddress;                                         // A2DP device MAC address
         String8 mScoDeviceAddress;                                          // SCO device MAC address
+        String8 mUsbCardAndDevice; // USB audio ALSA card and device numbers:
+                                   // card=<card_number>;device=<><device_number>
         bool    mLimitRingtoneVolume;                                       // limit ringtone volume to music volume if headset connected
         audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
         float   mLastVoiceVolume;                                           // last voice volume value sent to audio HAL
@@ -500,6 +502,7 @@
         KeyedVector<int, EffectDescriptor *> mEffects;  // list of registered audio effects
         bool    mA2dpSuspended;  // true if A2DP output is suspended
         bool mHasA2dp; // true on platforms with support for bluetooth A2DP
+        bool mHasUsb; // true on platforms with support for USB audio
         audio_devices_t mAttachedOutputDevices; // output devices always available on the platform
         audio_devices_t mDefaultOutputDevice; // output device selected by default at boot time
                                               // (must be in mAttachedOutputDevices)