Track the global setting of BT A2DP on/off
The default phone speaker, bluetooth audio devices, and wired audio devices are handled as system audio routes. When an app starts to make sound to a system audio route, the system audio route will be selected with the following order. 1. The slected route by the app after the latest connection of an audio device. 2. The lastly connected audio device. 3. The default phone speaker if not connected. Bug: 64811580 Test: Passed MediaRouterTest, manual Change-Id: I77badb14596bc661c44237957504164f5476e595
This commit is contained in:
@@ -28,6 +28,7 @@ interface IMediaRouterService {
|
||||
|
||||
MediaRouterClientState getState(IMediaRouterClient client);
|
||||
boolean isPlaybackActive(IMediaRouterClient client);
|
||||
boolean isGlobalBluetoothA2doOn();
|
||||
|
||||
void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
|
||||
void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
|
||||
|
||||
@@ -88,7 +88,6 @@ public class MediaRouter {
|
||||
RouteInfo mBluetoothA2dpRoute;
|
||||
|
||||
RouteInfo mSelectedRoute;
|
||||
RouteInfo mSystemAudioRoute;
|
||||
|
||||
final boolean mCanConfigureWifiDisplays;
|
||||
boolean mActivelyScanningWifiDisplays;
|
||||
@@ -150,7 +149,6 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
addRouteStatic(mDefaultAudioVideo);
|
||||
mSystemAudioRoute = mDefaultAudioVideo;
|
||||
|
||||
// This will select the active wifi display route if there is one.
|
||||
updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus());
|
||||
@@ -185,7 +183,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
void updateAudioRoutes(AudioRoutesInfo newRoutes) {
|
||||
boolean updated = false;
|
||||
boolean audioRoutesChanged = false;
|
||||
if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) {
|
||||
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
|
||||
int name;
|
||||
@@ -201,11 +199,10 @@ public class MediaRouter {
|
||||
}
|
||||
mDefaultAudioVideo.mNameResId = name;
|
||||
dispatchRouteChanged(mDefaultAudioVideo);
|
||||
updated = true;
|
||||
audioRoutesChanged = true;
|
||||
}
|
||||
|
||||
final int mainType = mCurAudioRoutesInfo.mainType;
|
||||
|
||||
if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
|
||||
mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
|
||||
if (mCurAudioRoutesInfo.bluetoothName != null) {
|
||||
@@ -219,8 +216,6 @@ public class MediaRouter {
|
||||
info.mDeviceType = RouteInfo.DEVICE_TYPE_BLUETOOTH;
|
||||
mBluetoothA2dpRoute = info;
|
||||
addRouteStatic(mBluetoothA2dpRoute);
|
||||
mSystemAudioRoute = mBluetoothA2dpRoute;
|
||||
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
|
||||
} else {
|
||||
mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName;
|
||||
dispatchRouteChanged(mBluetoothA2dpRoute);
|
||||
@@ -229,30 +224,32 @@ public class MediaRouter {
|
||||
// BT disconnected
|
||||
removeRouteStatic(mBluetoothA2dpRoute);
|
||||
mBluetoothA2dpRoute = null;
|
||||
mSystemAudioRoute = mDefaultAudioVideo;
|
||||
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
|
||||
}
|
||||
updated = true;
|
||||
audioRoutesChanged = true;
|
||||
}
|
||||
|
||||
if (mBluetoothA2dpRoute != null) {
|
||||
final boolean a2dpEnabled = isBluetoothA2dpOn();
|
||||
if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
|
||||
// A2DP off
|
||||
mSystemAudioRoute = mDefaultAudioVideo;
|
||||
updated = true;
|
||||
} else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
|
||||
a2dpEnabled) {
|
||||
// A2DP on or BT connected
|
||||
mSystemAudioRoute = mBluetoothA2dpRoute;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (updated) {
|
||||
if (audioRoutesChanged) {
|
||||
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false);
|
||||
Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn());
|
||||
}
|
||||
}
|
||||
|
||||
RouteInfo getDefaultSystemAudioRoute() {
|
||||
boolean globalBluetoothA2doOn = false;
|
||||
try {
|
||||
globalBluetoothA2doOn = mMediaRouterService.isGlobalBluetoothA2doOn();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Unable to call isSystemBluetoothA2doOn.", ex);
|
||||
}
|
||||
return (globalBluetoothA2doOn && mBluetoothA2dpRoute != null)
|
||||
? mBluetoothA2dpRoute : mDefaultAudioVideo;
|
||||
}
|
||||
|
||||
RouteInfo getCurrentSystemAudioRoute() {
|
||||
return (isBluetoothA2dpOn() && mBluetoothA2dpRoute != null)
|
||||
? mBluetoothA2dpRoute : mDefaultAudioVideo;
|
||||
}
|
||||
|
||||
boolean isBluetoothA2dpOn() {
|
||||
try {
|
||||
return mAudioService.isBluetoothA2dpOn();
|
||||
@@ -603,15 +600,13 @@ public class MediaRouter {
|
||||
|
||||
@Override
|
||||
public void onRestoreRoute() {
|
||||
// Skip restoring route if the selected route is not a system audio route, or
|
||||
// MediaRouter is initializing.
|
||||
if ((mSelectedRoute != mDefaultAudioVideo && mSelectedRoute != mBluetoothA2dpRoute)
|
||||
|| mSelectedRoute == mSystemAudioRoute) {
|
||||
|| mSelectedRoute == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sStatic.mAudioService.setBluetoothA2dpOn(mSelectedRoute == mBluetoothA2dpRoute);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error changing Bluetooth A2DP state", e);
|
||||
}
|
||||
mSelectedRoute.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -946,7 +941,7 @@ public class MediaRouter {
|
||||
boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo
|
||||
|| oldRoute == sStatic.mBluetoothA2dpRoute);
|
||||
if (oldRoute == route
|
||||
&& (!wasDefaultOrBluetoothRoute || oldRoute == sStatic.mSystemAudioRoute)) {
|
||||
&& (!wasDefaultOrBluetoothRoute || route == sStatic.getCurrentSystemAudioRoute())) {
|
||||
return;
|
||||
}
|
||||
if (!route.matchesTypes(types)) {
|
||||
|
||||
@@ -18,9 +18,7 @@ package com.android.server.media;
|
||||
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.server.Watchdog;
|
||||
import com.android.server.media.AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -96,9 +94,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
private final ArrayMap<IBinder, ClientRecord> mAllClientRecords =
|
||||
new ArrayMap<IBinder, ClientRecord>();
|
||||
private int mCurrentUserId = -1;
|
||||
private boolean mHasBluetoothRoute = false;
|
||||
private boolean mGlobalBluetoothA2dpOn = false;
|
||||
private final IAudioService mAudioService;
|
||||
private final AudioPlaybackMonitor mAudioPlaybackMonitor;
|
||||
private final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
|
||||
|
||||
public MediaRouterService(Context context) {
|
||||
mContext = context;
|
||||
@@ -137,13 +136,39 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() {
|
||||
@Override
|
||||
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
|
||||
mHasBluetoothRoute = newRoutes.bluetoothName != null;
|
||||
synchronized (mLock) {
|
||||
if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) {
|
||||
if ((newRoutes.mainType & (AudioRoutesInfo.MAIN_HEADSET
|
||||
| AudioRoutesInfo.MAIN_HEADPHONES
|
||||
| AudioRoutesInfo.MAIN_USB)) == 0) {
|
||||
// headset was plugged out.
|
||||
mGlobalBluetoothA2dpOn = newRoutes.bluetoothName != null;
|
||||
} else {
|
||||
// headset was plugged in.
|
||||
mGlobalBluetoothA2dpOn = false;
|
||||
}
|
||||
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
|
||||
}
|
||||
if (!TextUtils.equals(
|
||||
newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
|
||||
if (newRoutes.bluetoothName == null) {
|
||||
// BT was disconnected.
|
||||
mGlobalBluetoothA2dpOn = false;
|
||||
} else {
|
||||
// BT was connected or changed.
|
||||
mGlobalBluetoothA2dpOn = true;
|
||||
}
|
||||
mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "RemoteException in the audio service.");
|
||||
}
|
||||
mHasBluetoothRoute = (audioRoutes != null && audioRoutes.bluetoothName != null);
|
||||
synchronized (mLock) {
|
||||
mGlobalBluetoothA2dpOn = (audioRoutes != null && audioRoutes.bluetoothName != null);
|
||||
}
|
||||
}
|
||||
|
||||
public void systemRunning() {
|
||||
@@ -244,6 +269,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// Binder call
|
||||
@Override
|
||||
public boolean isGlobalBluetoothA2doOn() {
|
||||
synchronized (mLock) {
|
||||
return mGlobalBluetoothA2dpOn;
|
||||
}
|
||||
}
|
||||
|
||||
// Binder call
|
||||
@Override
|
||||
public void setDiscoveryRequest(IMediaRouterClient client,
|
||||
@@ -346,7 +379,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
|
||||
void restoreBluetoothA2dp() {
|
||||
try {
|
||||
mAudioService.setBluetoothA2dpOn(mHasBluetoothRoute);
|
||||
boolean a2dpOn = false;
|
||||
synchronized (mLock) {
|
||||
a2dpOn = mGlobalBluetoothA2dpOn;
|
||||
}
|
||||
Slog.v(TAG, "restoreBluetoothA2dp( " + a2dpOn + ")");
|
||||
mAudioService.setBluetoothA2dpOn(a2dpOn);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn.");
|
||||
}
|
||||
@@ -354,12 +392,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
|
||||
void restoreRoute(int uid) {
|
||||
ClientRecord clientRecord = null;
|
||||
UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid));
|
||||
if (userRecord != null && userRecord.mClientRecords != null) {
|
||||
for (ClientRecord cr : userRecord.mClientRecords) {
|
||||
if (validatePackageName(uid, cr.mPackageName)) {
|
||||
clientRecord = cr;
|
||||
break;
|
||||
synchronized (mLock) {
|
||||
UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid));
|
||||
if (userRecord != null && userRecord.mClientRecords != null) {
|
||||
for (ClientRecord cr : userRecord.mClientRecords) {
|
||||
if (validatePackageName(uid, cr.mPackageName)) {
|
||||
clientRecord = cr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user