Loading services/core/java/com/android/server/media/BluetoothRouteProvider.java +41 −9 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaRoute2Info; import android.text.TextUtils; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import com.android.internal.R; Loading @@ -55,6 +57,9 @@ class BluetoothRouteProvider { @SuppressWarnings("WeakerAccess") /* synthetic access */ BluetoothHearingAid mHearingAidProfile; // Route type -> volume map private final SparseIntArray mVolumeMap = new SparseIntArray(); private final Context mContext; private final BluetoothAdapter mBluetoothAdapter; private final BluetoothRoutesUpdatedListener mListener; Loading Loading @@ -192,11 +197,30 @@ class BluetoothRouteProvider { 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) .setVolume(volume) .build(); notifyBluetoothRoutesUpdated(); return true; } Loading @@ -222,6 +246,7 @@ class BluetoothRouteProvider { R.string.bluetooth_a2dp_audio_route_name).toString()) .setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP) .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .build(); newBtRoute.connectedProfiles = new SparseBooleanArray(); return newBtRoute; Loading @@ -240,13 +265,10 @@ class BluetoothRouteProvider { // Update volume when the connection state is changed. MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route) .setConnectionState(state); builder.setType(btRoute.connectedProfiles.get(BluetoothProfile.HEARING_AID, false) ? MediaRoute2Info.TYPE_HEARING_AID : MediaRoute2Info.TYPE_BLUETOOTH_A2DP); builder.setType(btRoute.getRouteType()); if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) { int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); builder.setVolumeMax(maxVolume).setVolume(currentVolume); builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0)); } btRoute.route = builder.build(); } Loading @@ -259,6 +281,15 @@ class BluetoothRouteProvider { public BluetoothDevice btDevice; public MediaRoute2Info route; 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. Loading @@ -285,13 +316,12 @@ class BluetoothRouteProvider { btRoute = createBluetoothRoute(device); mBluetoothRoutes.put(device.getAddress(), btRoute); } btRoute.connectedProfiles.put(profile, true); if (activeDevices.contains(device)) { mSelectedRoute = btRoute; setRouteConnectionState(mSelectedRoute, MediaRoute2Info.CONNECTION_STATE_CONNECTED); } btRoute.connectedProfiles.put(profile, true); } notifyBluetoothRoutesUpdated(); } Loading Loading @@ -348,6 +378,8 @@ class BluetoothRouteProvider { BluetoothDevice.ERROR); BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); 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); if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) { btRoute.connectedProfiles.put(BluetoothProfile.A2DP, true); Loading services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +33 −23 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { MediaRoute2Info mDeviceRoute; RoutingSessionInfo mDefaultSessionInfo; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); int mDeviceVolume; private final Object mRequestLock = new Object(); @GuardedBy("mRequestLock") Loading Loading @@ -127,8 +128,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { }); updateSessionInfosIfNeeded(); mContext.registerReceiver(new VolumeChangeReceiver(), new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION)); IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter); if (mBtRouteProvider != null) { mHandler.post(() -> { Loading @@ -136,6 +138,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { notifyProviderState(); }); } updateVolume(); } @Override Loading Loading @@ -248,8 +251,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { .setVolumeHandling(mAudioManager.isVolumeFixed() ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolume(mDeviceVolume) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)) .setType(type) .addFeature(FEATURE_LIVE_AUDIO) .addFeature(FEATURE_LIVE_VIDEO) Loading Loading @@ -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. @Override 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; } 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) { return; } final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); 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(); } updateVolume(); } } } Loading
services/core/java/com/android/server/media/BluetoothRouteProvider.java +41 −9 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaRoute2Info; import android.text.TextUtils; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import com.android.internal.R; Loading @@ -55,6 +57,9 @@ class BluetoothRouteProvider { @SuppressWarnings("WeakerAccess") /* synthetic access */ BluetoothHearingAid mHearingAidProfile; // Route type -> volume map private final SparseIntArray mVolumeMap = new SparseIntArray(); private final Context mContext; private final BluetoothAdapter mBluetoothAdapter; private final BluetoothRoutesUpdatedListener mListener; Loading Loading @@ -192,11 +197,30 @@ class BluetoothRouteProvider { 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) .setVolume(volume) .build(); notifyBluetoothRoutesUpdated(); return true; } Loading @@ -222,6 +246,7 @@ class BluetoothRouteProvider { R.string.bluetooth_a2dp_audio_route_name).toString()) .setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP) .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .build(); newBtRoute.connectedProfiles = new SparseBooleanArray(); return newBtRoute; Loading @@ -240,13 +265,10 @@ class BluetoothRouteProvider { // Update volume when the connection state is changed. MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route) .setConnectionState(state); builder.setType(btRoute.connectedProfiles.get(BluetoothProfile.HEARING_AID, false) ? MediaRoute2Info.TYPE_HEARING_AID : MediaRoute2Info.TYPE_BLUETOOTH_A2DP); builder.setType(btRoute.getRouteType()); if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) { int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); builder.setVolumeMax(maxVolume).setVolume(currentVolume); builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0)); } btRoute.route = builder.build(); } Loading @@ -259,6 +281,15 @@ class BluetoothRouteProvider { public BluetoothDevice btDevice; public MediaRoute2Info route; 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. Loading @@ -285,13 +316,12 @@ class BluetoothRouteProvider { btRoute = createBluetoothRoute(device); mBluetoothRoutes.put(device.getAddress(), btRoute); } btRoute.connectedProfiles.put(profile, true); if (activeDevices.contains(device)) { mSelectedRoute = btRoute; setRouteConnectionState(mSelectedRoute, MediaRoute2Info.CONNECTION_STATE_CONNECTED); } btRoute.connectedProfiles.put(profile, true); } notifyBluetoothRoutesUpdated(); } Loading Loading @@ -348,6 +378,8 @@ class BluetoothRouteProvider { BluetoothDevice.ERROR); BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); 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); if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) { btRoute.connectedProfiles.put(BluetoothProfile.A2DP, true); Loading
services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +33 −23 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { MediaRoute2Info mDeviceRoute; RoutingSessionInfo mDefaultSessionInfo; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); int mDeviceVolume; private final Object mRequestLock = new Object(); @GuardedBy("mRequestLock") Loading Loading @@ -127,8 +128,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { }); updateSessionInfosIfNeeded(); mContext.registerReceiver(new VolumeChangeReceiver(), new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION)); IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter); if (mBtRouteProvider != null) { mHandler.post(() -> { Loading @@ -136,6 +138,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { notifyProviderState(); }); } updateVolume(); } @Override Loading Loading @@ -248,8 +251,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { .setVolumeHandling(mAudioManager.isVolumeFixed() ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolume(mDeviceVolume) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)) .setType(type) .addFeature(FEATURE_LIVE_AUDIO) .addFeature(FEATURE_LIVE_VIDEO) Loading Loading @@ -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. @Override 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; } 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) { return; } final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); 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(); } updateVolume(); } } }