Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 079f09c6 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Added support for USB audio devices"

parents d1404465 59f48276
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -2000,8 +2000,8 @@ public class Intent implements Parcelable, Cloneable {
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_ANLG_HEADSET_PLUG =
            "android.intent.action.USB_ANLG_HEADSET_PLUG";
    public static final String ACTION_ANALOG_AUDIO_DOCK_PLUG =
            "android.intent.action.ANALOG_AUDIO_DOCK_PLUG";

    /**
     * Broadcast Action: A digital audio speaker/headset plugged in or unplugged.
@@ -2015,8 +2015,8 @@ public class Intent implements Parcelable, Cloneable {
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_DGTL_HEADSET_PLUG =
            "android.intent.action.USB_DGTL_HEADSET_PLUG";
    public static final String ACTION_DIGITAL_AUDIO_DOCK_PLUG =
            "android.intent.action.DIGITAL_AUDIO_DOCK_PLUG";

    /**
     * Broadcast Action: A HMDI cable was plugged or unplugged
@@ -2034,7 +2034,7 @@ public class Intent implements Parcelable, Cloneable {
            "android.intent.action.HDMI_AUDIO_PLUG";

    /**
     * Broadcast Action: A USB audio device was plugged in or unplugged.
     * Broadcast Action: A USB audio accessory was plugged in or unplugged.
     *
     * <p>The intent will have the following extra values:
     * <ul>
@@ -2046,11 +2046,11 @@ public class Intent implements Parcelable, Cloneable {
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
            "android.intent.action.USB_AUDIO_DEVICE_PLUG";
    public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
            "android.intent.action.USB_AUDIO_ACCESSORY_PLUG";

    /**
     * Broadcast Action: A USB audio accessory was plugged in or unplugged.
     * Broadcast Action: A USB audio device was plugged in or unplugged.
     *
     * <p>The intent will have the following extra values:
     * <ul>
@@ -2062,8 +2062,8 @@ public class Intent implements Parcelable, Cloneable {
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
            "android.intent.action.USB_AUDIO_ACCESSORY_PLUG";
    public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
            "android.intent.action.USB_AUDIO_DEVICE_PLUG";

    /**
     * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
+8 −0
Original line number Diff line number Diff line
@@ -2237,6 +2237,14 @@ public class AudioManager {
     *  docking station
     */
    public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
    /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host
     * mode and the Android device in USB device mode
     */
    public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
    /** {@hide} The audio output device code for a USB audio device. The device is in USB device
     * mode and the Android device in USB host mode
     */
    public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
    /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
     *  used in the future in a set method to select whatever default device is chosen by the
     *  platform-specific implementation.
+71 −118
Original line number Diff line number Diff line
@@ -389,9 +389,11 @@ public class AudioService extends IAudioService.Stub {
        intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
        intentFilter.addAction(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
        intentFilter.addAction(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
        intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
        intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
        intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
        intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
        intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -2800,6 +2802,28 @@ public class AudioService extends IAudioService.Stub {
        }
    }

    private boolean handleDeviceConnection(boolean connected, int device, String params) {
        synchronized (mConnectedDevices) {
            boolean isConnected = (mConnectedDevices.containsKey(device) &&
                    mConnectedDevices.get(device).equals(params));

            if (isConnected && !connected) {
                AudioSystem.setDeviceConnectionState(device,
                                              AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                              params);
                 mConnectedDevices.remove(device);
                 return true;
            } else if (!isConnected && connected) {
                 AudioSystem.setDeviceConnectionState(device,
                                                      AudioSystem.DEVICE_STATE_AVAILABLE,
                                                      params);
                 mConnectedDevices.put(new Integer(device), params);
                 return true;
            }
        }
        return false;
    }

    /* cache of the address of the last dock the device was connected to */
    private String mDockAddress;

@@ -2810,6 +2834,8 @@ public class AudioService extends IAudioService.Stub {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            int device;
            int state;

            if (action.equals(Intent.ACTION_DOCK_EVENT)) {
                int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -2834,15 +2860,15 @@ public class AudioService extends IAudioService.Stub {
                }
                AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
            } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                               BluetoothProfile.STATE_DISCONNECTED);
                BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                handleA2dpConnectionStateChange(btDevice, state);
            } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                               BluetoothProfile.STATE_DISCONNECTED);
                int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
                device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
                String address = null;

                BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
@@ -2868,129 +2894,56 @@ public class AudioService extends IAudioService.Stub {
                    address = "";
                }

                synchronized (mConnectedDevices) {
                    boolean isConnected = (mConnectedDevices.containsKey(device) &&
                                           mConnectedDevices.get(device).equals(address));

                boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
                if (handleDeviceConnection(connected, device, address)) {
                    synchronized (mScoClients) {
                        if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
                            AudioSystem.setDeviceConnectionState(device,
                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                                             address);
                            mConnectedDevices.remove(device);
                        if (connected) {
                            mBluetoothHeadsetDevice = btDevice;
                        } else {
                            mBluetoothHeadsetDevice = null;
                            resetBluetoothSco();
                        } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
                            AudioSystem.setDeviceConnectionState(device,
                                                                 AudioSystem.DEVICE_STATE_AVAILABLE,
                                                                 address);
                            mConnectedDevices.put(new Integer(device), address);
                            mBluetoothHeadsetDevice = btDevice;
                        }
                    }
                }
            } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
                int state = intent.getIntExtra("state", 0);
                state = intent.getIntExtra("state", 0);
                int microphone = intent.getIntExtra("microphone", 0);

                synchronized (mConnectedDevices) {
                if (microphone != 0) {
                        boolean isConnected =
                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
                        if (state == 0 && isConnected) {
                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                    "");
                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
                        } else if (state == 1 && !isConnected)  {
                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
                                    AudioSystem.DEVICE_STATE_AVAILABLE,
                                    "");
                            mConnectedDevices.put(
                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), "");
                        }
                    device = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
                } else {
                        boolean isConnected =
                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
                        if (state == 0 && isConnected) {
                            AudioSystem.setDeviceConnectionState(
                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                    "");
                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
                        } else if (state == 1 && !isConnected)  {
                            AudioSystem.setDeviceConnectionState(
                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
                                    AudioSystem.DEVICE_STATE_AVAILABLE,
                                    "");
                            mConnectedDevices.put(
                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), "");
                        }
                    }
                }
            } else if (action.equals(Intent.ACTION_USB_ANLG_HEADSET_PLUG)) {
                int state = intent.getIntExtra("state", 0);
                Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = "+state);
                synchronized (mConnectedDevices) {
                    boolean isConnected =
                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
                    if (state == 0 && isConnected) {
                        AudioSystem.setDeviceConnectionState(
                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
                                                        AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                                        "");
                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
                    } else if (state == 1 && !isConnected)  {
                        AudioSystem.setDeviceConnectionState(
                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
                                                        AudioSystem.DEVICE_STATE_AVAILABLE,
                                                        "");
                        mConnectedDevices.put(
                                new Integer(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET), "");
                    }
                    device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
                }
                handleDeviceConnection((state == 1), device, "");
            } else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) {
                state = intent.getIntExtra("state", 0);
                Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state);
                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, "");
            } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) {
                int state = intent.getIntExtra("state", 0);
                state = intent.getIntExtra("state", 0);
                Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state);
                synchronized (mConnectedDevices) {
                    boolean isConnected =
                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
                    if (state == 0 && isConnected) {
                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                                             "");
                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
                    } else if (state == 1 && !isConnected)  {
                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
                                                             "");
                        mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_AUX_DIGITAL), "");
                    }
                }
            } else if (action.equals(Intent.ACTION_USB_DGTL_HEADSET_PLUG)) {
                int state = intent.getIntExtra("state", 0);
                Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_DGTL_HEADSET_PLUG, state = "+state);
                synchronized (mConnectedDevices) {
                    boolean isConnected =
                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
                    if (state == 0 && isConnected) {
                        AudioSystem.setDeviceConnectionState(
                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                                         "");
                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
                    } else if (state == 1 && !isConnected)  {
                        AudioSystem.setDeviceConnectionState(
                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
                                                         "");
                        mConnectedDevices.put(
                                new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), "");
                    }
                }
                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, "");
            } else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) {
                state = intent.getIntExtra("state", 0);
                Log.v(TAG,
                      "Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state);
                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, "");
            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
                           action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
                state = intent.getIntExtra("state", 0);
                int alsaCard = intent.getIntExtra("card", -1);
                int alsaDevice = intent.getIntExtra("device", -1);
                String params = "card=" + alsaCard + ";device=" + alsaDevice;
                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                        AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
                Log.v(TAG, "Broadcast Receiver: Got "
                        + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                              "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
                        + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
                handleDeviceConnection((state == 1), device, params);
            } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                boolean broadcast = false;
                int state = AudioManager.SCO_AUDIO_STATE_ERROR;
                int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                synchronized (mScoClients) {
                    int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
                    // broadcast intent if the connection was initated by AudioService
@@ -3002,7 +2955,7 @@ public class AudioService extends IAudioService.Stub {
                    }
                    switch (btState) {
                    case BluetoothHeadset.STATE_AUDIO_CONNECTED:
                        state = AudioManager.SCO_AUDIO_STATE_CONNECTED;
                        scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
                        if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
                            mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
                            mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
@@ -3010,7 +2963,7 @@ public class AudioService extends IAudioService.Stub {
                        }
                        break;
                    case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
                        state = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                        scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                        mScoAudioState = SCO_STATE_INACTIVE;
                        clearAllScoClients(0, false);
                        break;
@@ -3027,11 +2980,11 @@ public class AudioService extends IAudioService.Stub {
                    }
                }
                if (broadcast) {
                    broadcastScoConnectionState(state);
                    broadcastScoConnectionState(scoAudioState);
                    //FIXME: this is to maintain compatibility with deprecated intent
                    // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
                    Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
                    mContext.sendStickyBroadcast(newIntent);
                }
            } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+11 −0
Original line number Diff line number Diff line
@@ -202,6 +202,9 @@ public class AudioSystem
    public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
    public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
    public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
    public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
    public static final int DEVICE_OUT_USB_DEVICE = 0x4000;

    public static final int DEVICE_OUT_DEFAULT = 0x8000;
    public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
                                              DEVICE_OUT_SPEAKER |
@@ -216,10 +219,18 @@ public class AudioSystem
                                              DEVICE_OUT_AUX_DIGITAL |
                                              DEVICE_OUT_ANLG_DOCK_HEADSET |
                                              DEVICE_OUT_DGTL_DOCK_HEADSET |
                                              DEVICE_OUT_USB_ACCESSORY |
                                              DEVICE_OUT_USB_DEVICE |
                                              DEVICE_OUT_DEFAULT);
    public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
                                                   DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                                                   DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
    public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
                                                  DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
                                                  DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
    public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                  DEVICE_OUT_USB_DEVICE);

    // input devices
    public static final int DEVICE_IN_COMMUNICATION = 0x10000;
    public static final int DEVICE_IN_AMBIENT = 0x20000;
+2 −2
Original line number Diff line number Diff line
@@ -301,13 +301,13 @@ class WiredAccessoryObserver extends UEventObserver {

                //  Pack up the values and broadcast them to everyone
                if (headset == BIT_USB_HEADSET_ANLG) {
                    intent = new Intent(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
                    intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                    intent.putExtra("state", state);
                    intent.putExtra("name", headsetName);
                    ActivityManagerNative.broadcastStickyIntent(intent, null);
                } else if (headset == BIT_USB_HEADSET_DGTL) {
                    intent = new Intent(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
                    intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                    intent.putExtra("state", state);
                    intent.putExtra("name", headsetName);