Merge "audioservice: fix not able to disconnect VoIP call" into rvc-dev am: 30fd5e4553
Change-Id: I9ee56fc32c883f33236ce35c32ac2091771c5e3c
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user