Use broadcast receiver to update BT A2DP status
Audio routes observer in AudioService could have several seconds delay. To mitigate the issue because of the delay, this CL uses a BroadcastReceiver to get the Bluetooth device connection events. Bug: 70175199 Test: manually and passed Media CTS Change-Id: Ic1e9db1b8d5759070962011d7f2fc4f940ce8497
This commit is contained in:
@@ -21,6 +21,9 @@ import com.android.server.Watchdog;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -96,21 +99,23 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
private final ArrayMap<IBinder, ClientRecord> mAllClientRecords =
|
||||
new ArrayMap<IBinder, ClientRecord>();
|
||||
private int mCurrentUserId = -1;
|
||||
private boolean mGlobalBluetoothA2dpOn = false;
|
||||
private final IAudioService mAudioService;
|
||||
private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
|
||||
private final Handler mHandler = new Handler();
|
||||
private final AudioRoutesInfo mAudioRoutesInfo = new AudioRoutesInfo();
|
||||
private final IntArray mActivePlayerMinPriorityQueue = new IntArray();
|
||||
private final IntArray mActivePlayerUidMinPriorityQueue = new IntArray();
|
||||
|
||||
private final BroadcastReceiver mReceiver = new MediaRouterServiceBroadcastReceiver();
|
||||
BluetoothDevice mBluetoothDevice;
|
||||
int mAudioRouteMainType = AudioRoutesInfo.MAIN_SPEAKER;
|
||||
boolean mGlobalBluetoothA2dpOn = false;
|
||||
|
||||
public MediaRouterService(Context context) {
|
||||
mContext = context;
|
||||
Watchdog.getInstance().addMonitor(this);
|
||||
|
||||
mAudioService = IAudioService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.AUDIO_SERVICE));
|
||||
|
||||
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance();
|
||||
mAudioPlayerStateMonitor.registerListener(
|
||||
new AudioPlayerStateMonitor.OnAudioPlayerActiveStateChangedListener() {
|
||||
@@ -170,44 +175,30 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
@Override
|
||||
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
|
||||
synchronized (mLock) {
|
||||
if (newRoutes.mainType != mAudioRoutesInfo.mainType) {
|
||||
if (newRoutes.mainType != mAudioRouteMainType) {
|
||||
if ((newRoutes.mainType & (AudioRoutesInfo.MAIN_HEADSET
|
||||
| AudioRoutesInfo.MAIN_HEADPHONES
|
||||
| AudioRoutesInfo.MAIN_USB)) == 0) {
|
||||
// headset was plugged out.
|
||||
mGlobalBluetoothA2dpOn = newRoutes.bluetoothName != null;
|
||||
mGlobalBluetoothA2dpOn = mBluetoothDevice != null;
|
||||
} else {
|
||||
// headset was plugged in.
|
||||
mGlobalBluetoothA2dpOn = false;
|
||||
}
|
||||
mAudioRoutesInfo.mainType = newRoutes.mainType;
|
||||
mAudioRouteMainType = newRoutes.mainType;
|
||||
}
|
||||
if (!TextUtils.equals(
|
||||
newRoutes.bluetoothName, mAudioRoutesInfo.bluetoothName)) {
|
||||
if (newRoutes.bluetoothName == null) {
|
||||
// BT was disconnected.
|
||||
mGlobalBluetoothA2dpOn = false;
|
||||
} else {
|
||||
// BT was connected or changed.
|
||||
mGlobalBluetoothA2dpOn = true;
|
||||
}
|
||||
mAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
|
||||
}
|
||||
// Although a Bluetooth device is connected before a new audio playback is
|
||||
// started, dispatchAudioRoutChanged() can be called after
|
||||
// onAudioPlayerActiveStateChanged(). That causes restoreBluetoothA2dp()
|
||||
// is called before mGlobalBluetoothA2dpOn is updated.
|
||||
// Calling restoreBluetoothA2dp() here could prevent that.
|
||||
restoreBluetoothA2dp();
|
||||
// The new audio routes info could be delivered with several seconds delay.
|
||||
// In order to avoid such delay, Bluetooth device info will be updated
|
||||
// via MediaRouterServiceBroadcastReceiver.
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "RemoteException in the audio service.");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mGlobalBluetoothA2dpOn = (audioRoutes != null && audioRoutes.bluetoothName != null);
|
||||
}
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
|
||||
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
|
||||
}
|
||||
|
||||
public void systemRunning() {
|
||||
@@ -415,14 +406,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
|
||||
void restoreBluetoothA2dp() {
|
||||
try {
|
||||
boolean btConnected = false;
|
||||
boolean a2dpOn = false;
|
||||
synchronized (mLock) {
|
||||
btConnected = mAudioRoutesInfo.bluetoothName != null;
|
||||
a2dpOn = mGlobalBluetoothA2dpOn;
|
||||
}
|
||||
// We don't need to change a2dp status when bluetooth is not connected.
|
||||
if (btConnected) {
|
||||
if (mBluetoothDevice != null) {
|
||||
Slog.v(TAG, "restoreBluetoothA2dp(" + a2dpOn + ")");
|
||||
mAudioService.setBluetoothA2dpOn(a2dpOn);
|
||||
}
|
||||
@@ -661,6 +650,25 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
return false;
|
||||
}
|
||||
|
||||
final class MediaRouterServiceBroadcastReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
|
||||
int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
|
||||
BluetoothProfile.STATE_DISCONNECTED);
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
mGlobalBluetoothA2dpOn = false;
|
||||
mBluetoothDevice = null;
|
||||
} else if (state == BluetoothProfile.STATE_CONNECTED) {
|
||||
mGlobalBluetoothA2dpOn = true;
|
||||
mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
// To ensure that BT A2DP is on, call restoreBluetoothA2dp().
|
||||
restoreBluetoothA2dp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a particular client of the media router.
|
||||
* The contents of this object is guarded by mLock.
|
||||
|
||||
Reference in New Issue
Block a user