Merge "audioservice: fix not able to disconnect VoIP call" into rvc-dev am: 30fd5e4553

Change-Id: I9ee56fc32c883f33236ce35c32ac2091771c5e3c
This commit is contained in:
Eric Laurent
2020-04-01 23:20:49 +00:00
committed by Automerger Merge Worker
2 changed files with 52 additions and 97 deletions

View File

@@ -324,7 +324,7 @@ import java.io.PrintWriter;
} }
/*package*/ void setBluetoothScoOn(boolean on, String eventSource) { /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
//Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); //Log.i(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
synchronized (mDeviceStateLock) { synchronized (mDeviceStateLock) {
if (on) { if (on) {
// do not accept SCO ON if SCO audio is not connected // do not accept SCO ON if SCO audio is not connected

View File

@@ -58,6 +58,7 @@ public class BtHelper {
} }
// List of clients having issued a SCO start request // List of clients having issued a SCO start request
@GuardedBy("BtHelper.this")
private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>(); private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>();
// BluetoothHeadset API to control SCO connection // BluetoothHeadset API to control SCO connection
@@ -356,9 +357,8 @@ public class BtHelper {
// client is created. // client is created.
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
eventSource += " client count before=" + client.getCount();
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource)); AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
client.incCount(scoAudioMode); client.requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
} catch (NullPointerException e) { } catch (NullPointerException e) {
Log.e(TAG, "Null ScoClient", e); Log.e(TAG, "Null ScoClient", e);
} }
@@ -375,9 +375,15 @@ public class BtHelper {
// and this must be done on behalf of system server to make sure permissions are granted. // and this must be done on behalf of system server to make sure permissions are granted.
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
if (client != null) { if (client != null) {
eventSource += " client count before=" + client.getCount();
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource)); AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
client.decCount(); client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
SCO_MODE_VIRTUAL_CALL);
// If a disconnection is pending, the client will be removed whne clearAllScoClients()
// is called form receiveBtEvent()
if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ
&& mScoAudioState != SCO_STATE_DEACTIVATING) {
client.remove(false /*stop */, true /*unregister*/);
}
} }
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
} }
@@ -657,25 +663,33 @@ public class BtHelper {
@GuardedBy("AudioDeviceBroker.mDeviceStateLock") @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void scoClientDied(Object obj) { /*package*/ synchronized void scoClientDied(Object obj) {
final ScoClient client = (ScoClient) obj; final ScoClient client = (ScoClient) obj;
client.remove(true /*stop*/, false /*unregister*/);
Log.w(TAG, "SCO client died"); Log.w(TAG, "SCO client died");
int index = mScoClients.indexOf(client);
if (index < 0) {
Log.w(TAG, "unregistered SCO client died");
} else {
client.clearCount(true);
mScoClients.remove(client);
}
} }
private class ScoClient implements IBinder.DeathRecipient { private class ScoClient implements IBinder.DeathRecipient {
private IBinder mCb; // To be notified of client's death private IBinder mCb; // To be notified of client's death
private int mCreatorPid; private int mCreatorPid;
private int mStartcount; // number of SCO connections started by this client
ScoClient(IBinder cb) { ScoClient(IBinder cb) {
mCb = cb; mCb = cb;
mCreatorPid = Binder.getCallingPid(); mCreatorPid = Binder.getCallingPid();
mStartcount = 0; }
public void registerDeathRecipient() {
try {
mCb.linkToDeath(this, 0);
} catch (RemoteException e) {
Log.w(TAG, "ScoClient could not link to " + mCb + " binder death");
}
}
public void unregisterDeathRecipient() {
try {
mCb.unlinkToDeath(this, 0);
} catch (NoSuchElementException e) {
Log.w(TAG, "ScoClient could not not unregistered to binder");
}
} }
@Override @Override
@@ -685,70 +699,6 @@ public class BtHelper {
mDeviceBroker.postScoClientDied(this); mDeviceBroker.postScoClientDied(this);
} }
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void incCount(int scoAudioMode) {
if (!requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode)) {
Log.e(TAG, "Request sco connected with scoAudioMode("
+ scoAudioMode + ") failed");
return;
}
if (mStartcount == 0) {
try {
mCb.linkToDeath(this, 0);
} catch (RemoteException e) {
// client has already died!
Log.w(TAG, "ScoClient incCount() could not link to "
+ mCb + " binder death");
}
}
mStartcount++;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void decCount() {
if (mStartcount == 0) {
Log.w(TAG, "ScoClient.decCount() already 0");
} else {
mStartcount--;
if (mStartcount == 0) {
try {
mCb.unlinkToDeath(this, 0);
} catch (NoSuchElementException e) {
Log.w(TAG, "decCount() going to 0 but not registered to binder");
}
}
if (!requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0)) {
Log.w(TAG, "Request sco disconnected with scoAudioMode(0) failed");
}
}
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void clearCount(boolean stopSco) {
if (mStartcount != 0) {
try {
mCb.unlinkToDeath(this, 0);
} catch (NoSuchElementException e) {
Log.w(TAG, "clearCount() mStartcount: "
+ mStartcount + " != 0 but not registered to binder");
}
}
mStartcount = 0;
if (stopSco) {
requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
}
}
int getCount() {
return mStartcount;
}
IBinder getBinder() { IBinder getBinder() {
return mCb; return mCb;
} }
@@ -757,23 +707,14 @@ public class BtHelper {
return mCreatorPid; return mCreatorPid;
} }
private int totalCount() {
int count = 0;
for (ScoClient mScoClient : mScoClients) {
count += mScoClient.getCount();
}
return count;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock") // @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock") //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this") @GuardedBy("BtHelper.this")
private boolean requestScoState(int state, int scoAudioMode) { private boolean requestScoState(int state, int scoAudioMode) {
checkScoAudioState(); checkScoAudioState();
int clientCount = totalCount(); if (mScoClients.size() != 1) {
if (clientCount != 0) {
Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode
+ ", clientCount=" + clientCount); + ", num SCO clients=" + mScoClients.size());
return true; return true;
} }
if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
@@ -842,12 +783,14 @@ public class BtHelper {
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
break; break;
case SCO_STATE_ACTIVE_INTERNAL:
Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return");
break;
default: default:
Log.w(TAG, "requestScoState: failed to connect in state " Log.w(TAG, "requestScoState: failed to connect in state "
+ mScoAudioState + ", scoAudioMode=" + scoAudioMode); + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
return false; return false;
} }
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
switch (mScoAudioState) { switch (mScoAudioState) {
@@ -893,6 +836,18 @@ public class BtHelper {
} }
return true; return true;
} }
@GuardedBy("BtHelper.this")
void remove(boolean stop, boolean unregister) {
if (unregister) {
unregisterDeathRecipient();
}
if (stop) {
requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
SCO_MODE_VIRTUAL_CALL);
}
mScoClients.remove(this);
}
} }
//----------------------------------------------------- //-----------------------------------------------------
@@ -946,6 +901,7 @@ public class BtHelper {
} }
@GuardedBy("BtHelper.this")
private ScoClient getScoClient(IBinder cb, boolean create) { private ScoClient getScoClient(IBinder cb, boolean create) {
for (ScoClient existingClient : mScoClients) { for (ScoClient existingClient : mScoClients) {
if (existingClient.getBinder() == cb) { if (existingClient.getBinder() == cb) {
@@ -954,6 +910,7 @@ public class BtHelper {
} }
if (create) { if (create) {
ScoClient newClient = new ScoClient(cb); ScoClient newClient = new ScoClient(cb);
newClient.registerDeathRecipient();
mScoClients.add(newClient); mScoClients.add(newClient);
return newClient; return newClient;
} }
@@ -964,18 +921,16 @@ public class BtHelper {
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock") //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this") @GuardedBy("BtHelper.this")
private void clearAllScoClients(int exceptPid, boolean stopSco) { private void clearAllScoClients(int exceptPid, boolean stopSco) {
ScoClient savedClient = null; final ArrayList<ScoClient> clients = new ArrayList<ScoClient>();
for (ScoClient cl : mScoClients) { for (ScoClient cl : mScoClients) {
if (cl.getPid() != exceptPid) { if (cl.getPid() != exceptPid) {
cl.clearCount(stopSco); clients.add(cl);
} else {
savedClient = cl;
} }
} }
mScoClients.clear(); for (ScoClient cl : clients) {
if (savedClient != null) { cl.remove(stopSco, true /*unregister*/);
mScoClients.add(savedClient);
} }
} }
private boolean getBluetoothHeadset() { private boolean getBluetoothHeadset() {