Automated import from //branches/donutburger/...@141909,141909
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 3c50707..5c4e56d 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -58,6 +58,7 @@
private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
private static final int MESSAGE_CONNECT_TO = 1;
+ private static final int MESSAGE_DISCONNECT = 2;
private final Context mContext;
private final IntentFilter mIntentFilter;
@@ -65,6 +66,11 @@
private final AudioManager mAudioManager;
private final BluetoothDevice mBluetooth;
+ // list of disconnected sinks to process after a delay
+ private final ArrayList<String> mPendingDisconnects = new ArrayList<String>();
+ // number of active sinks
+ private int mSinkCount = 0;
+
private class SinkState {
public String address;
public int state;
@@ -164,6 +170,9 @@
connectSink(address);
}
break;
+ case MESSAGE_DISCONNECT:
+ handleDeferredDisconnect((String)msg.obj);
+ break;
}
}
};
@@ -338,6 +347,9 @@
}
private synchronized void onSinkConnected(String path) {
+ // if we are reconnected, do not process previous disconnect event.
+ mPendingDisconnects.remove(path);
+
if (mAudioDevices == null) return;
// bluez 3.36 quietly disconnects the previous sink when a new sink
// is connected, so we need to mark all previously connected sinks as
@@ -363,8 +375,23 @@
}
private synchronized void onSinkDisconnected(String path) {
- mAudioManager.setBluetoothA2dpOn(false);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
+ // This is to work around a problem in bluez that results
+ // sink disconnect events being sent, immediately followed by a reconnect.
+ // To avoid unnecessary audio routing changes, we defer handling
+ // sink disconnects until after a short delay.
+ mPendingDisconnects.add(path);
+ Message msg = Message.obtain(mHandler, MESSAGE_DISCONNECT, path);
+ mHandler.sendMessageDelayed(msg, 2000);
+ }
+
+ private synchronized void handleDeferredDisconnect(String path) {
+ if (mPendingDisconnects.contains(path)) {
+ mPendingDisconnects.remove(path);
+ if (mSinkCount == 1) {
+ mAudioManager.setBluetoothA2dpOn(false);
+ }
+ updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
+ }
}
private synchronized void onSinkPlaying(String path) {
@@ -432,6 +459,13 @@
if (state != prevState) {
if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state);
+
+ // keep track of the number of active sinks
+ if (prevState == BluetoothA2dp.STATE_DISCONNECTED) {
+ mSinkCount++;
+ } else if (state == BluetoothA2dp.STATE_DISCONNECTED) {
+ mSinkCount--;
+ }
Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
intent.putExtra(BluetoothIntent.ADDRESS, address);
@@ -441,7 +475,8 @@
if ((prevState == BluetoothA2dp.STATE_CONNECTED ||
prevState == BluetoothA2dp.STATE_PLAYING) &&
- (state != BluetoothA2dp.STATE_CONNECTED &&
+ (state != BluetoothA2dp.STATE_CONNECTING &&
+ state != BluetoothA2dp.STATE_CONNECTED &&
state != BluetoothA2dp.STATE_PLAYING)) {
// disconnected
intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);