Merge "Handles volume for device route and bt routes." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
73de009a8c
@@ -28,10 +28,12 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioSystem;
|
||||||
import android.media.MediaRoute2Info;
|
import android.media.MediaRoute2Info;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
|
||||||
@@ -55,6 +57,9 @@ class BluetoothRouteProvider {
|
|||||||
@SuppressWarnings("WeakerAccess") /* synthetic access */
|
@SuppressWarnings("WeakerAccess") /* synthetic access */
|
||||||
BluetoothHearingAid mHearingAidProfile;
|
BluetoothHearingAid mHearingAidProfile;
|
||||||
|
|
||||||
|
// Route type -> volume map
|
||||||
|
private final SparseIntArray mVolumeMap = new SparseIntArray();
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final BluetoothAdapter mBluetoothAdapter;
|
private final BluetoothAdapter mBluetoothAdapter;
|
||||||
private final BluetoothRoutesUpdatedListener mListener;
|
private final BluetoothRoutesUpdatedListener mListener;
|
||||||
@@ -192,11 +197,30 @@ class BluetoothRouteProvider {
|
|||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean setSelectedRouteVolume(int volume) {
|
/**
|
||||||
if (mSelectedRoute == null) return false;
|
* Updates the volume for {@link AudioManager#getDevicesForStream(int) devices}.
|
||||||
|
*
|
||||||
|
* @return true if devices can be handled by the provider.
|
||||||
|
*/
|
||||||
|
public boolean updateVolumeForDevices(int devices, int volume) {
|
||||||
|
int routeType;
|
||||||
|
if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
|
||||||
|
routeType = MediaRoute2Info.TYPE_HEARING_AID;
|
||||||
|
} else if ((devices & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP
|
||||||
|
| AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
|
||||||
|
| AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
|
||||||
|
routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mVolumeMap.put(routeType, volume);
|
||||||
|
if (mSelectedRoute == null || mSelectedRoute.route.getType() != routeType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
|
mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
|
||||||
.setVolume(volume)
|
.setVolume(volume)
|
||||||
.build();
|
.build();
|
||||||
|
notifyBluetoothRoutesUpdated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +246,7 @@ class BluetoothRouteProvider {
|
|||||||
R.string.bluetooth_a2dp_audio_route_name).toString())
|
R.string.bluetooth_a2dp_audio_route_name).toString())
|
||||||
.setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP)
|
.setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP)
|
||||||
.setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
|
.setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
|
||||||
|
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
|
||||||
.build();
|
.build();
|
||||||
newBtRoute.connectedProfiles = new SparseBooleanArray();
|
newBtRoute.connectedProfiles = new SparseBooleanArray();
|
||||||
return newBtRoute;
|
return newBtRoute;
|
||||||
@@ -240,13 +265,10 @@ class BluetoothRouteProvider {
|
|||||||
// Update volume when the connection state is changed.
|
// Update volume when the connection state is changed.
|
||||||
MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route)
|
MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route)
|
||||||
.setConnectionState(state);
|
.setConnectionState(state);
|
||||||
builder.setType(btRoute.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)
|
builder.setType(btRoute.getRouteType());
|
||||||
? MediaRoute2Info.TYPE_HEARING_AID : MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
|
|
||||||
|
|
||||||
if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
|
if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
|
||||||
int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
|
builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0));
|
||||||
int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
|
||||||
builder.setVolumeMax(maxVolume).setVolume(currentVolume);
|
|
||||||
}
|
}
|
||||||
btRoute.route = builder.build();
|
btRoute.route = builder.build();
|
||||||
}
|
}
|
||||||
@@ -259,6 +281,15 @@ class BluetoothRouteProvider {
|
|||||||
public BluetoothDevice btDevice;
|
public BluetoothDevice btDevice;
|
||||||
public MediaRoute2Info route;
|
public MediaRoute2Info route;
|
||||||
public SparseBooleanArray connectedProfiles;
|
public SparseBooleanArray connectedProfiles;
|
||||||
|
|
||||||
|
@MediaRoute2Info.Type
|
||||||
|
int getRouteType() {
|
||||||
|
// Let hearing aid profile have a priority.
|
||||||
|
if (connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
|
||||||
|
return MediaRoute2Info.TYPE_HEARING_AID;
|
||||||
|
}
|
||||||
|
return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These callbacks run on the main thread.
|
// These callbacks run on the main thread.
|
||||||
@@ -285,13 +316,12 @@ class BluetoothRouteProvider {
|
|||||||
btRoute = createBluetoothRoute(device);
|
btRoute = createBluetoothRoute(device);
|
||||||
mBluetoothRoutes.put(device.getAddress(), btRoute);
|
mBluetoothRoutes.put(device.getAddress(), btRoute);
|
||||||
}
|
}
|
||||||
|
btRoute.connectedProfiles.put(profile, true);
|
||||||
if (activeDevices.contains(device)) {
|
if (activeDevices.contains(device)) {
|
||||||
mSelectedRoute = btRoute;
|
mSelectedRoute = btRoute;
|
||||||
setRouteConnectionState(mSelectedRoute,
|
setRouteConnectionState(mSelectedRoute,
|
||||||
MediaRoute2Info.CONNECTION_STATE_CONNECTED);
|
MediaRoute2Info.CONNECTION_STATE_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
btRoute.connectedProfiles.put(profile, true);
|
|
||||||
}
|
}
|
||||||
notifyBluetoothRoutesUpdated();
|
notifyBluetoothRoutesUpdated();
|
||||||
}
|
}
|
||||||
@@ -348,6 +378,8 @@ class BluetoothRouteProvider {
|
|||||||
BluetoothDevice.ERROR);
|
BluetoothDevice.ERROR);
|
||||||
BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
|
BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
|
||||||
if (bondState == BluetoothDevice.BOND_BONDED && btRoute == null) {
|
if (bondState == BluetoothDevice.BOND_BONDED && btRoute == null) {
|
||||||
|
//TODO: The type of the new route is A2DP even when it's HEARING_AID.
|
||||||
|
// We may determine the type of route when create the route.
|
||||||
btRoute = createBluetoothRoute(device);
|
btRoute = createBluetoothRoute(device);
|
||||||
if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
|
if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
|
||||||
btRoute.connectedProfiles.put(BluetoothProfile.A2DP, true);
|
btRoute.connectedProfiles.put(BluetoothProfile.A2DP, true);
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
|||||||
MediaRoute2Info mDeviceRoute;
|
MediaRoute2Info mDeviceRoute;
|
||||||
RoutingSessionInfo mDefaultSessionInfo;
|
RoutingSessionInfo mDefaultSessionInfo;
|
||||||
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
|
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
|
||||||
|
int mDeviceVolume;
|
||||||
|
|
||||||
private final Object mRequestLock = new Object();
|
private final Object mRequestLock = new Object();
|
||||||
@GuardedBy("mRequestLock")
|
@GuardedBy("mRequestLock")
|
||||||
@@ -127,8 +128,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
|||||||
});
|
});
|
||||||
updateSessionInfosIfNeeded();
|
updateSessionInfosIfNeeded();
|
||||||
|
|
||||||
mContext.registerReceiver(new VolumeChangeReceiver(),
|
IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
|
||||||
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
|
intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
|
||||||
|
mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter);
|
||||||
|
|
||||||
if (mBtRouteProvider != null) {
|
if (mBtRouteProvider != null) {
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
@@ -136,6 +138,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
|||||||
notifyProviderState();
|
notifyProviderState();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
updateVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -248,8 +251,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
|||||||
.setVolumeHandling(mAudioManager.isVolumeFixed()
|
.setVolumeHandling(mAudioManager.isVolumeFixed()
|
||||||
? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
|
? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
|
||||||
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
|
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
|
||||||
|
.setVolume(mDeviceVolume)
|
||||||
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
|
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
|
||||||
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
|
|
||||||
.setType(type)
|
.setType(type)
|
||||||
.addFeature(FEATURE_LIVE_AUDIO)
|
.addFeature(FEATURE_LIVE_AUDIO)
|
||||||
.addFeature(FEATURE_LIVE_VIDEO)
|
.addFeature(FEATURE_LIVE_VIDEO)
|
||||||
@@ -361,36 +364,43 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VolumeChangeReceiver extends BroadcastReceiver {
|
void updateVolume() {
|
||||||
|
int devices = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
|
||||||
|
int volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
|
if (mDefaultRoute.getVolume() != volume) {
|
||||||
|
mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
|
||||||
|
.setVolume(volume)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBtRouteProvider != null && mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mDeviceVolume != volume) {
|
||||||
|
mDeviceVolume = volume;
|
||||||
|
mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
|
||||||
|
.setVolume(volume)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
publishProviderState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AudioManagerBroadcastReceiver extends BroadcastReceiver {
|
||||||
// This will be called in the main thread.
|
// This will be called in the main thread.
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (!intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
|
if (!intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)
|
||||||
|
&& !intent.getAction().equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
|
int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
|
||||||
if (streamType != AudioManager.STREAM_MUSIC) {
|
if (streamType != AudioManager.STREAM_MUSIC) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
|
updateVolume();
|
||||||
final int oldVolume = intent.getIntExtra(
|
|
||||||
AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
|
|
||||||
|
|
||||||
if (newVolume != oldVolume) {
|
|
||||||
if (TextUtils.equals(mDeviceRoute.getId(), mSelectedRouteId)) {
|
|
||||||
mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
|
|
||||||
.setVolume(newVolume)
|
|
||||||
.build();
|
|
||||||
} else if (mBtRouteProvider != null) {
|
|
||||||
mBtRouteProvider.setSelectedRouteVolume(newVolume);
|
|
||||||
}
|
|
||||||
mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
|
|
||||||
.setVolume(newVolume)
|
|
||||||
.build();
|
|
||||||
publishProviderState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user