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

This commit is contained in:
Eric Laurent
2020-04-01 23:11:07 +00:00
committed by Android (Google) Code Review
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) {
//Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
//Log.i(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
synchronized (mDeviceStateLock) {
if (on) {
// 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
@GuardedBy("BtHelper.this")
private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>();
// BluetoothHeadset API to control SCO connection
@@ -356,9 +357,8 @@ public class BtHelper {
// client is created.
final long ident = Binder.clearCallingIdentity();
try {
eventSource += " client count before=" + client.getCount();
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
client.incCount(scoAudioMode);
client.requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
} catch (NullPointerException 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.
final long ident = Binder.clearCallingIdentity();
if (client != null) {
eventSource += " client count before=" + client.getCount();
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);
}
@@ -657,25 +663,33 @@ public class BtHelper {
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void scoClientDied(Object obj) {
final ScoClient client = (ScoClient) obj;
client.remove(true /*stop*/, false /*unregister*/);
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 IBinder mCb; // To be notified of client's death
private int mCreatorPid;
private int mStartcount; // number of SCO connections started by this client
ScoClient(IBinder cb) {
mCb = cb;
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
@@ -685,70 +699,6 @@ public class BtHelper {
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() {
return mCb;
}
@@ -757,23 +707,14 @@ public class BtHelper {
return mCreatorPid;
}
private int totalCount() {
int count = 0;
for (ScoClient mScoClient : mScoClients) {
count += mScoClient.getCount();
}
return count;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private boolean requestScoState(int state, int scoAudioMode) {
checkScoAudioState();
int clientCount = totalCount();
if (clientCount != 0) {
if (mScoClients.size() != 1) {
Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode
+ ", clientCount=" + clientCount);
+ ", num SCO clients=" + mScoClients.size());
return true;
}
if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
@@ -842,12 +783,14 @@ public class BtHelper {
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
break;
case SCO_STATE_ACTIVE_INTERNAL:
Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return");
break;
default:
Log.w(TAG, "requestScoState: failed to connect in state "
+ mScoAudioState + ", scoAudioMode=" + scoAudioMode);
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
return false;
}
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
switch (mScoAudioState) {
@@ -893,6 +836,18 @@ public class BtHelper {
}
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) {
for (ScoClient existingClient : mScoClients) {
if (existingClient.getBinder() == cb) {
@@ -954,6 +910,7 @@ public class BtHelper {
}
if (create) {
ScoClient newClient = new ScoClient(cb);
newClient.registerDeathRecipient();
mScoClients.add(newClient);
return newClient;
}
@@ -964,18 +921,16 @@ public class BtHelper {
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private void clearAllScoClients(int exceptPid, boolean stopSco) {
ScoClient savedClient = null;
final ArrayList<ScoClient> clients = new ArrayList<ScoClient>();
for (ScoClient cl : mScoClients) {
if (cl.getPid() != exceptPid) {
cl.clearCount(stopSco);
} else {
savedClient = cl;
clients.add(cl);
}
}
mScoClients.clear();
if (savedClient != null) {
mScoClients.add(savedClient);
for (ScoClient cl : clients) {
cl.remove(stopSco, true /*unregister*/);
}
}
private boolean getBluetoothHeadset() {