do not merge - Fix for issue 2184627 cherry picked from eclair-mr2

Bluetooth A2DP suspend-resume improvements.

This change will reduce the occurence rate of A2DP sink suspend resume failures observed in issues 2184627, 2181005 and possibly 2189628.

More robust suspend/resume logic.
Use only the suspend request to audio hardware to avoid having two concurent suspend resume control paths.
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 9a2d6d9..ec3b2ff 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -72,8 +72,7 @@
     private final AudioManager mAudioManager;
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
-    private boolean mSuspending;
-    private boolean mResuming;
+    private int   mTargetA2dpState;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -151,8 +150,7 @@
 
         if (mBluetoothService.isEnabled())
             onBluetoothEnable();
-        mSuspending = false;
-        mResuming = false;
+        mTargetA2dpState = -1;
     }
 
     @Override
@@ -341,10 +339,7 @@
     public synchronized boolean suspendSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("suspendSink(" + device + "), mSuspending: "+mSuspending+", mResuming: "+mResuming);
-        if (mSuspending) {
-            return true;
-        }
+        if (DBG) log("suspendSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -353,28 +348,15 @@
         if (path == null || state == null) {
             return false;
         }
-        switch (state.intValue()) {
-        case BluetoothA2dp.STATE_CONNECTED:
-            if (mResuming) {
-                mSuspending = true;
-            }
-            return true;
-        case BluetoothA2dp.STATE_PLAYING:
-            mAudioManager.setParameters("A2dpSuspended=true");
-            mSuspending = suspendSinkNative(path);
-            return mSuspending;
-        default:
-            return false;
-        }
+
+        mTargetA2dpState = BluetoothA2dp.STATE_CONNECTED;
+        return checkSinkSuspendState(state.intValue());
     }
 
     public synchronized boolean resumeSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("resumeSink(" + device + "), mResuming: "+mResuming+", mSuspending: "+mSuspending);
-        if (mResuming) {
-            return true;
-        }
+        if (DBG) log("resumeSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -383,19 +365,8 @@
         if (path == null || state == null) {
             return false;
         }
-        switch (state.intValue()) {
-        case BluetoothA2dp.STATE_PLAYING:
-            if (mSuspending) {
-                mResuming = true;
-            }
-            return true;
-        case BluetoothA2dp.STATE_CONNECTED:
-            mResuming = resumeSinkNative(path);
-            mAudioManager.setParameters("A2dpSuspended=false");
-            return mResuming;
-        default:
-            return false;
-        }
+        mTargetA2dpState = BluetoothA2dp.STATE_PLAYING;
+        return checkSinkSuspendState(state.intValue());
     }
 
     public synchronized BluetoothDevice[] getConnectedSinks() {
@@ -458,10 +429,6 @@
     }
 
     private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
-        if (state == BluetoothA2dp.STATE_DISCONNECTED) {
-            mSuspending = false;
-            mResuming = false;
-        }
         if (state != prevState) {
             if (state == BluetoothA2dp.STATE_DISCONNECTED ||
                     state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -477,28 +444,11 @@
             }
             mAudioDevices.put(device, state);
 
-            if (state == BluetoothA2dp.STATE_CONNECTED && prevState == BluetoothA2dp.STATE_PLAYING) {
-                if (DBG) log("handleSinkStateChange() STATE_PLAYING -> STATE_CONNECTED: mSuspending: "
-                        +mSuspending+", mResuming: "+mResuming);
-                if (mSuspending) {
-                    mSuspending = false;
-                    if (mResuming) {
-                        mResuming = false;
-                        resumeSink(device);
-                    }
-                }
-            }
-            if (state == BluetoothA2dp.STATE_PLAYING && prevState == BluetoothA2dp.STATE_CONNECTED) {
-                if (DBG) log("handleSinkStateChange() STATE_CONNECTED -> STATE_PLAYING: mSuspending: "
-                        +mSuspending+", mResuming: "+mResuming);
+            checkSinkSuspendState(state);
+            mTargetA2dpState = -1;
 
-                if (mResuming) {
-                    mResuming = false;
-                    if (mSuspending) {
-                        mSuspending = false;
-                        suspendSink(device);
-                    }
-                }
+            if (state == BluetoothA2dp.STATE_CONNECTING) {
+                mAudioManager.setParameters("A2dpSuspended=false");
             }
             Intent intent = new Intent(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
@@ -527,6 +477,23 @@
         return sinks;
     }
 
+    private boolean checkSinkSuspendState(int state) {
+        boolean result = true;
+
+        if (state != mTargetA2dpState) {
+            if (state == BluetoothA2dp.STATE_PLAYING &&
+                mTargetA2dpState == BluetoothA2dp.STATE_CONNECTED) {
+                mAudioManager.setParameters("A2dpSuspended=true");
+            } else if (state == BluetoothA2dp.STATE_CONNECTED &&
+                mTargetA2dpState == BluetoothA2dp.STATE_PLAYING) {
+                mAudioManager.setParameters("A2dpSuspended=false");
+            } else {
+                result = false;
+            }
+        }
+        return result;
+    }
+
     @Override
     protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mAudioDevices.isEmpty()) return;