diff options
| author | 2012-05-29 09:24:28 -0700 | |
|---|---|---|
| committer | 2012-05-30 14:44:43 -0700 | |
| commit | b1fbaaccb656ef09a8770c28df15e3e91a452e64 (patch) | |
| tree | 200c9e04729844783efdf360375297483113d6cc | |
| parent | 48c22c84c089213dda6495fbdeb384e400c7c5c5 (diff) | |
Send device connection intents from AudioService
AudioService is currently notified of wired headset and A2DP
sink connection states via broadcast intents from WiredAccessoryObserver
and BluetoothA2dpService. This is a problem as there is no guaranty that
AudioService can take actions upon the change before other apps are notified.
For instance, the Play On feature requires the UI to be refreshed when a device
is inserted/removed and we must guaranty that the UI component can read
new A2DP enable state from AudioManager after it receives a device connection state
change intent.
- Added hidden methods to AudioManager so that WiredAccessoryObserver
and BluetoothA2dpService can notify AudioService of device connection directly.
- The wired accessories connection intents are now sent by AudioService.
- The A2DP state change intent is delayed by BluetoothA2DPService when
ACTION_AUDIO_BECOMING_NOISY is sent by AudioService
- ACTION_AUDIO_BECOMING_NOISY intent is not sent when disconnecting A2DP
while a wired headset is present and vice versa.
Bug 6485897.
Change-Id: Ie160b3ee5f451132065530772b868593c90afd94
| -rw-r--r-- | core/java/android/server/BluetoothA2dpService.java | 59 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 37 | ||||
| -rw-r--r-- | media/java/android/media/AudioService.java | 175 | ||||
| -rw-r--r-- | media/java/android/media/IAudioService.aidl | 4 | ||||
| -rw-r--r-- | services/java/com/android/server/WiredAccessoryObserver.java | 110 |
5 files changed, 251 insertions, 134 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 300bc686eddb..08a99d2fb9e6 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -33,7 +33,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; import android.os.ParcelUuid; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.provider.Settings; import android.util.Log; @@ -65,6 +69,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private final BluetoothAdapter mAdapter; private int mTargetA2dpState; private BluetoothDevice mPlayingA2dpDevice; + private IntentBroadcastHandler mIntentBroadcastHandler; + private final WakeLock mWakeLock; + + private static final int MSG_CONNECTION_STATE_CHANGED = 0; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -131,6 +139,11 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { public BluetoothA2dpService(Context context, BluetoothService bluetoothService) { mContext = context; + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService"); + + mIntentBroadcastHandler = new IntentBroadcastHandler(); + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mBluetoothService = bluetoothService; @@ -514,17 +527,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { adjustOtherSinkPriorities(device); } - Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, state); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); + int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state); - if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state); - - mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state, - prevState); + mWakeLock.acquire(); + mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage( + MSG_CONNECTION_STATE_CHANGED, + prevState, + state, + device), + delay); } } @@ -586,6 +597,34 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } } + /** Handles A2DP connection state change intent broadcasts. */ + private class IntentBroadcastHandler extends Handler { + + private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) { + Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothProfile.EXTRA_STATE, state); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + + if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state); + + mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state, + prevState); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_CONNECTION_STATE_CHANGED: + onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2); + mWakeLock.release(); + break; + } + } + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 6c7c160b14d2..6b9522b39e86 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -19,6 +19,7 @@ package android.media; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -2376,6 +2377,42 @@ public class AudioManager { } } + /** + * Indicate wired accessory connection state change. + * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) + * @param state new connection state: 1 connected, 0 disconnected + * @param name device name + * {@hide} + */ + public void setWiredDeviceConnectionState(int device, int state, String name) { + IAudioService service = getService(); + try { + service.setWiredDeviceConnectionState(device, state, name); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e); + } + } + + /** + * Indicate A2DP sink connection state change. + * @param device Bluetooth device connected/disconnected + * @param state new connection state (BluetoothProfile.STATE_xxx) + * @return a delay in ms that the caller should wait before broadcasting + * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. + * {@hide} + */ + public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) { + IAudioService service = getService(); + int delay = 0; + try { + delay = service.setBluetoothA2dpDeviceConnectionState(device, state); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e); + } finally { + return delay; + } + } + /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 5e338abf46c0..84856bfb81bd 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -135,6 +135,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished { private static final int MSG_RCDISPLAY_UPDATE = 13; private static final int MSG_SET_ALL_VOLUMES = 14; private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 15; + private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 16; + private static final int MSG_SET_A2DP_CONNECTION_STATE = 17; // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be @@ -442,15 +444,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished { // Register for device connection intent broadcasts. IntentFilter intentFilter = - new IntentFilter(Intent.ACTION_HEADSET_PLUG); - - intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); + new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); intentFilter.addAction(Intent.ACTION_DOCK_EVENT); - 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); @@ -1961,7 +1957,19 @@ public class AudioService extends IAudioService.Stub implements OnFinished { deviceList = a2dp.getConnectedDevices(); if (deviceList.size() > 0) { btDevice = deviceList.get(0); - handleA2dpConnectionStateChange(btDevice, a2dp.getConnectionState(btDevice)); + synchronized (mConnectedDevices) { + int state = a2dp.getConnectionState(btDevice); + int delay = checkSendBecomingNoisyIntent( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); + sendMsg(mAudioHandler, + MSG_SET_A2DP_CONNECTION_STATE, + SENDMSG_QUEUE, + state, + 0, + btDevice, + delay); + } } break; @@ -2262,6 +2270,36 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return device; } + public void setWiredDeviceConnectionState(int device, int state, String name) { + synchronized (mConnectedDevices) { + int delay = checkSendBecomingNoisyIntent(device, state); + sendMsg(mAudioHandler, + MSG_SET_WIRED_DEVICE_CONNECTION_STATE, + SENDMSG_QUEUE, + device, + state, + name, + delay); + } + } + + public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) + { + int delay; + synchronized (mConnectedDevices) { + delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); + sendMsg(mAudioHandler, + MSG_SET_A2DP_CONNECTION_STATE, + SENDMSG_QUEUE, + state, + 0, + device, + delay); + } + return delay; + } + /////////////////////////////////////////////////////////////////////////// // Inner classes /////////////////////////////////////////////////////////////////////////// @@ -2959,6 +2997,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished { case MSG_BT_HEADSET_CNCT_FAILED: resetBluetoothSco(); break; + + case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: + onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); + break; + + case MSG_SET_A2DP_CONNECTION_STATE: + onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1); + break; } } } @@ -3020,7 +3066,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { // must be called synchronized on mConnectedDevices private void makeA2dpDeviceUnavailableNow(String address) { - sendBecomingNoisyIntent(); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_UNAVAILABLE, address); @@ -3050,7 +3095,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); } - private void handleA2dpConnectionStateChange(BluetoothDevice btDevice, int state) + private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state) { if (btDevice == null) { return; @@ -3116,6 +3161,76 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return false; } + // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only + // sent if none of these devices is connected. + int mBecomingNoisyIntentDevices = + AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | + AudioSystem.DEVICE_OUT_ALL_A2DP; + + // must be called before removing the device from mConnectedDevices + private int checkSendBecomingNoisyIntent(int device, int state) { + int delay = 0; + if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { + int devices = 0; + for (int dev : mConnectedDevices.keySet()) { + if ((dev & mBecomingNoisyIntentDevices) != 0) { + devices |= dev; + } + } + if (devices == device) { + delay = 1000; + sendBecomingNoisyIntent(); + } + } + + if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) || + mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { + delay = 1000; + } + return delay; + } + + private void sendDeviceConnectionIntent(int device, int state, String name) + { + Intent intent = new Intent(); + + intent.putExtra("state", state); + intent.putExtra("name", name); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + + if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { + intent.setAction(Intent.ACTION_HEADSET_PLUG); + intent.putExtra("microphone", 1); + } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { + intent.setAction(Intent.ACTION_HEADSET_PLUG); + intent.putExtra("microphone", 0); + } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { + intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); + } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { + intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); + } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) { + intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); + } + + ActivityManagerNative.broadcastStickyIntent(intent, null); + } + + private void onSetWiredDeviceConnectionState(int device, int state, String name) + { + synchronized (mConnectedDevices) { + if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || + (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { + setBluetoothA2dpOnInt(true); + } + handleDeviceConnection((state == 1), device, ""); + if ((state != 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || + (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { + setBluetoothA2dpOnInt(false); + } + sendDeviceConnectionIntent(device, state, name); + } + } + /* cache of the address of the last dock the device was connected to */ private String mDockAddress; @@ -3151,12 +3266,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { config = AudioSystem.FORCE_NONE; } AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); - } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { - 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)) { state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); @@ -3197,43 +3306,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished { } } } - } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) { - state = intent.getIntExtra("state", 0); - int microphone = intent.getIntExtra("microphone", 0); - - if (microphone != 0) { - device = AudioSystem.DEVICE_OUT_WIRED_HEADSET; - } else { - device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; - } - // enable A2DP before notifying headset disconnection to avoid glitches - if (state == 0) { - setBluetoothA2dpOnInt(true); - } - handleDeviceConnection((state == 1), device, ""); - // disable A2DP after notifying headset connection to avoid glitches - if (state != 0) { - setBluetoothA2dpOnInt(false); - } - } 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)) { - state = intent.getIntExtra("state", 0); - Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state); - 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); - if (state == 0) { - sendBecomingNoisyIntent(); - } int alsaCard = intent.getIntExtra("card", -1); int alsaDevice = intent.getIntExtra("device", -1); String params = (alsaCard == -1 && alsaDevice == -1 ? "" diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 7fbe28c5e6a0..133f30be5254 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -17,6 +17,7 @@ package android.media; import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.media.IAudioFocusDispatcher; import android.media.IRemoteControlClient; @@ -133,4 +134,7 @@ interface IAudioService { void setRingtonePlayer(IRingtonePlayer player); IRingtonePlayer getRingtonePlayer(); int getMasterStreamType(); + + void setWiredDeviceConnectionState(int device, int state, String name); + int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state); } diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 53d1f0e6ad33..96ac493f680d 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -139,11 +139,14 @@ class WiredAccessoryObserver extends UEventObserver { private final Context mContext; private final WakeLock mWakeLock; // held while there is a pending route change + private final AudioManager mAudioManager; + public WiredAccessoryObserver(Context context) { mContext = context; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver"); mWakeLock.setReferenceCounted(false); + mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); context.registerReceiver(new BootCompletedReceiver(), new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); @@ -250,106 +253,65 @@ class WiredAccessoryObserver extends UEventObserver { mPrevHeadsetState = mHeadsetState; mHeadsetState = headsetState; - if (headsetState == 0) { - if (mContext.getResources().getBoolean( - com.android.internal.R.bool.config_sendAudioBecomingNoisy)) { - Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY); - mContext.sendBroadcast(intent); - } - - // It can take hundreds of ms flush the audio pipeline after - // apps pause audio playback, but audio route changes are - // immediate, so delay the route change by 1000ms. - // This could be improved once the audio sub-system provides an - // interface to clear the audio pipeline. - delay = 1000; - } else { - // Insert the same delay for headset connection so that the connection event is not - // broadcast before the disconnection event in case of fast removal/insertion - if (mHandler.hasMessages(0)) { - delay = 1000; - } - } mWakeLock.acquire(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(0, - mHeadsetState, - mPrevHeadsetState, - mHeadsetName), - delay); + mHandler.sendMessage(mHandler.obtainMessage(0, + mHeadsetState, + mPrevHeadsetState, + mHeadsetName)); } - private synchronized final void sendIntents(int headsetState, int prevHeadsetState, String headsetName) { + private synchronized final void setDevicesState(int headsetState, + int prevHeadsetState, + String headsetName) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { - sendIntent(curHeadset, headsetState, prevHeadsetState, headsetName); + setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } - private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) { + private final void setDeviceState(int headset, + int headsetState, + int prevHeadsetState, + String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { + int device; + int state; - int state = 0; if ((headsetState & headset) != 0) { state = 1; + } else { + state = 0; } - if((headset == BIT_USB_HEADSET_ANLG) || (headset == BIT_USB_HEADSET_DGTL) || - (headset == BIT_HDMI_AUDIO)) { - Intent intent; - - // Pack up the values and broadcast them to everyone - if (headset == BIT_USB_HEADSET_ANLG) { - 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_DIGITAL_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_HDMI_AUDIO) { - intent = new Intent(Intent.ACTION_HDMI_AUDIO_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - ActivityManagerNative.broadcastStickyIntent(intent, null); - } - if (LOG) Slog.v(TAG, "Intent.ACTION_USB_HEADSET_PLUG: state: "+state+" name: "+headsetName); - // TODO: Should we require a permission? + if (headset == BIT_HEADSET) { + device = AudioManager.DEVICE_OUT_WIRED_HEADSET; + } else if (headset == BIT_HEADSET_NO_MIC){ + device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE; + } else if (headset == BIT_USB_HEADSET_ANLG) { + device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET; + } else if (headset == BIT_USB_HEADSET_DGTL) { + device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET; + } else if (headset == BIT_HDMI_AUDIO) { + device = AudioManager.DEVICE_OUT_AUX_DIGITAL; + } else { + Slog.e(TAG, "setDeviceState() invalid headset type: "+headset); + return; } - if((headset == BIT_HEADSET) || (headset == BIT_HEADSET_NO_MIC)) { - // Pack up the values and broadcast them to everyone - Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - //int state = 0; - int microphone = 0; + if (LOG) + Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected")); - if ((headset & HEADSETS_WITH_MIC) != 0) { - microphone = 1; - } - - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - intent.putExtra("microphone", microphone); - - if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone); - // TODO: Should we require a permission? - ActivityManagerNative.broadcastStickyIntent(intent, null); - } + mAudioManager.setWiredDeviceConnectionState(device, state, headsetName); } } private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { - sendIntents(msg.arg1, msg.arg2, (String)msg.obj); + setDevicesState(msg.arg1, msg.arg2, (String)msg.obj); mWakeLock.release(); } }; |