BT: Serialize SHO
This change serialize multiple SHO request
triggerred from multiple devices.
CRs-Fixed: 2400666
Change-Id: I3cb10c1b65f3463e744e03b5b95ff9d492f0602a
diff --git a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
index 43aaf77..413ccdb 100644
--- a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
+++ b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
@@ -171,6 +171,7 @@
private byte changePathDirection;
HashMap<BluetoothDevice, Integer> mVolumeMap = new HashMap();
public static final String VOLUME_MAP = "bluetooth_volume_map";
+ private boolean isShoActive = false;
private boolean twsShoEnabled = false;
private static final String playerStateUpdateBlackListedAddr[] = {
@@ -234,6 +235,7 @@
private final static int MESSAGE_UPDATE_ABS_VOLUME_STATUS = 31;
private final static int MESSAGE_UPDATE_ABSOLUTE_VOLUME = 32;
private static final int MSG_PLAY_STATUS_CMD_TIMEOUT = 33;
+ private final static int MESSAGE_START_SHO = 34;
private static final int STACK_CLEANUP = 0;
private static final int APP_CLEANUP = 1;
@@ -406,6 +408,11 @@
};
DeviceDependentFeature[] deviceFeatures;
+ private static class SHOQueue {
+ static BluetoothDevice device;
+ static boolean PlayReq;
+ }
+
static {
classInitNative();
}
@@ -1353,9 +1360,28 @@
// This is for some remote devices, which send PLAY/PAUSE based on AVRCP State.
BATService mBatService = BATService.getBATService();
if ((mBatService == null) || !mBatService.isA2dpSuspendFromBA()) {
- // if this suspend was triggered by BA, then don't update AVRCP state
+ // if this suspend was triggered by BA, then don't update AVRCP states
updateCurrentMediaState((BluetoothDevice)msg.obj);
}
+
+ if (mA2dpState == BluetoothA2dp.STATE_PLAYING) {
+ boolean shoComplete = false;
+ synchronized(Avrcp_ext.this) {
+ if(isShoActive) {
+ isShoActive = false;
+ shoComplete = true;
+ Log.e(TAG, "1: SHO complete");
+ }
+
+ if(mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ if(shoComplete == true) {
+ CompleteSHO();
+ }
+ }
}
break;
@@ -1520,6 +1546,36 @@
deviceFeatures[deviceIndex].isPlayStatusTimeOut = true;
break;
+ case MESSAGE_START_SHO:
+ if (mA2dpService != null)
+ break;
+
+ synchronized (Avrcp_ext.this) {
+ if(mHandler.hasMessages(MESSAGE_START_SHO)) {
+ Log.e(TAG, "Queue already has another SHO pending");
+ break;
+ }
+ isShoActive = true;
+ Log.d(TAG, "2: SHO started. PlayReq = " + msg.arg1);
+ }
+
+ BluetoothDevice dev = (BluetoothDevice)msg.obj;
+ boolean PlayReq = (msg.arg1 == 1);
+ mA2dpService.startSHO(dev);
+
+ if(!PlayReq) {
+ synchronized (Avrcp_ext.this) {
+ isShoActive = false;
+ Log.d(TAG, "3: SHO complete");
+ if (mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ CompleteSHO();
+ }
+ break;
+
default:
Log.e(TAG, "unknown message! msg.what=" + msg.what);
break;
@@ -4645,7 +4701,7 @@
if((rspStatus == AvrcpConstants.RSP_NO_ERROR) && ((mA2dpService != null) &&
!Objects.equals(mA2dpService.getActiveDevice(), device))) {
Log.d(TAG, "Trigger Handoff by playItem");
- mA2dpService.setActiveDevice(device);
+ startSHO(device, true);
}
if (!playItemRspNative(address, rspStatus)) {
Log.e(TAG, "playItemRspNative failed!");
@@ -4817,7 +4873,43 @@
}
public boolean startSHO(BluetoothDevice device, boolean PlayReq) {
- return false;
+ synchronized (Avrcp_ext.this) {
+ if(isShoActive) {
+ mHandler.removeMessages (MESSAGE_START_SHO);
+ Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
+ SHOQueue.device = device;
+ SHOQueue.PlayReq = PlayReq;
+ mHandler.sendMessageDelayed(msg, 3000);
+ Log.d(TAG, "4: SHO Queued");
+ return true;
+ } else {
+ isShoActive = true;
+ Log.d(TAG, "5: SHO started: PlayReq = " + PlayReq);
+ }
+ }
+ boolean ret = mA2dpService.startSHO(device);
+ synchronized (Avrcp_ext.this) {
+ if (!PlayReq) {
+ isShoActive = false;
+ Log.d(TAG, "6: SHO complete");
+
+ if (mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ }
+ CompleteSHO();
+ return ret;
+ }
+
+ private void triggerSHO(BluetoothDevice device, boolean PlayReq) {
+ Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
+ mHandler.sendMessage(msg);
+ }
+
+ public void CompleteSHO() {
+ /*For device setup after SHO*/
}
public void setActiveDevice(BluetoothDevice device) {
@@ -5018,7 +5110,7 @@
}
if (action == KeyEvent.ACTION_DOWN) {
Log.d(TAG, "AVRCP Trigger Handoff");
- mA2dpService.setActiveDevice(device);
+ startSHO(device, true);
} else {
Log.d(TAG, "release for play PT from inactive device");
}