Update "Play media to" display rule in SoundSetting

- show under Casting mode
- hide under no connected Bluetooth devices
- update test case

Bug: 131143025
Test: make -j42 RunSettingsRoboTests
Change-Id: I0eac856970043ecd9a1975fbe382241078ece924
This commit is contained in:
Tim Peng
2019-04-24 10:47:31 +08:00
committed by tim peng
parent 7a237a40d7
commit 7b0f887000
3 changed files with 33 additions and 135 deletions

View File

@@ -17,7 +17,6 @@
package com.android.settings.sound; package com.android.settings.sound;
import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION; import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION;
import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -29,7 +28,6 @@ import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo; import android.media.AudioDeviceInfo;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaRouter; import android.media.MediaRouter;
import android.media.MediaRouter.Callback;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.FeatureFlagUtils; import android.util.FeatureFlagUtils;
@@ -76,7 +74,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
protected AudioSwitchCallback mAudioSwitchPreferenceCallback; protected AudioSwitchCallback mAudioSwitchPreferenceCallback;
private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;
private final MediaRouterCallback mMediaRouterCallback;
private final WiredHeadsetBroadcastReceiver mReceiver; private final WiredHeadsetBroadcastReceiver mReceiver;
private final Handler mHandler; private final Handler mHandler;
private LocalBluetoothManager mLocalBluetoothManager; private LocalBluetoothManager mLocalBluetoothManager;
@@ -92,7 +89,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
mHandler = new Handler(Looper.getMainLooper()); mHandler = new Handler(Looper.getMainLooper());
mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback();
mReceiver = new WiredHeadsetBroadcastReceiver(); mReceiver = new WiredHeadsetBroadcastReceiver();
mMediaRouterCallback = new MediaRouterCallback();
mConnectedDevices = new ArrayList<>(); mConnectedDevices = new ArrayList<>();
final FutureTask<LocalBluetoothManager> localBtManagerFutureTask = new FutureTask<>( final FutureTask<LocalBluetoothManager> localBtManagerFutureTask = new FutureTask<>(
// Avoid StrictMode ThreadPolicy violation // Avoid StrictMode ThreadPolicy violation
@@ -210,12 +206,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
* get A2dp devices on all states * get A2dp devices on all states
* (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING)
*/ */
protected List<BluetoothDevice> getConnectableA2dpDevices() { protected List<BluetoothDevice> getConnectedA2dpDevices() {
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
if (a2dpProfile == null) { if (a2dpProfile == null) {
return new ArrayList<>(); return new ArrayList<>();
} }
return a2dpProfile.getConnectableDevices(); return a2dpProfile.getConnectedDevices();
} }
/** /**
@@ -241,31 +237,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
return connectedDevices; return connectedDevices;
} }
/**
* get hearing aid profile devices on all states
* (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING)
* exclude other devices with same hiSyncId.
*/
protected List<BluetoothDevice> getConnectableHearingAidDevices() {
final List<BluetoothDevice> connectedDevices = new ArrayList<>();
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
if (hapProfile == null) {
return connectedDevices;
}
final List<Long> devicesHiSyncIds = new ArrayList<>();
final List<BluetoothDevice> devices = hapProfile.getConnectableDevices();
for (BluetoothDevice device : devices) {
final long hiSyncId = hapProfile.getHiSyncId(device);
// device with same hiSyncId should not be shown in the UI.
// So do not add it into connectedDevices.
if (!devicesHiSyncIds.contains(hiSyncId)) {
devicesHiSyncIds.add(hiSyncId);
connectedDevices.add(device);
}
}
return connectedDevices;
}
/** /**
* Find active hearing aid device * Find active hearing aid device
*/ */
@@ -299,7 +270,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
private void register() { private void register() {
mLocalBluetoothManager.getEventManager().registerCallback(this); mLocalBluetoothManager.getEventManager().registerCallback(this);
mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler);
mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback);
// Register for misc other intent broadcasts. // Register for misc other intent broadcasts.
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
@@ -310,7 +280,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
private void unregister() { private void unregister() {
mLocalBluetoothManager.getEventManager().unregisterCallback(this); mLocalBluetoothManager.getEventManager().unregisterCallback(this);
mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback);
mMediaRouter.removeCallback(mMediaRouterCallback);
mContext.unregisterReceiver(mReceiver); mContext.unregisterReceiver(mReceiver);
} }
@@ -338,49 +307,4 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
} }
} }
} }
/** Callback for cast device events. */
private class MediaRouterCallback extends Callback {
@Override
public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
}
@Override
public void onRouteUnselected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
}
@Override
public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
if (info != null && !info.isDefault()) {
// cast mode
updateState(mPreference);
}
}
@Override
public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
}
@Override
public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
if (info != null && !info.isDefault()) {
// cast mode
updateState(mPreference);
}
}
@Override
public void onRouteGrouped(MediaRouter router, MediaRouter.RouteInfo info,
MediaRouter.RouteGroup group, int index) {
}
@Override
public void onRouteUngrouped(MediaRouter router, MediaRouter.RouteInfo info,
MediaRouter.RouteGroup group) {
}
@Override
public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo info) {
}
}
} }

View File

@@ -16,9 +16,6 @@
package com.android.settings.sound; package com.android.settings.sound;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -56,13 +53,6 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
return; return;
} }
if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_REMOTE_SUBMIX)) {
// In cast mode, disable switch entry.
mPreference.setVisible(false);
preference.setSummary(mContext.getText(R.string.media_output_summary_unavailable));
return;
}
if (Utils.isAudioModeOngoingCall(mContext)) { if (Utils.isAudioModeOngoingCall(mContext)) {
// Ongoing call status, switch entry for media will be disabled. // Ongoing call status, switch entry for media will be disabled.
mPreference.setVisible(false); mPreference.setVisible(false);
@@ -71,19 +61,19 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
return; return;
} }
boolean deviceConnectable = false; boolean deviceConnected = false;
BluetoothDevice activeDevice = null; BluetoothDevice activeDevice = null;
// Show preference if there is connected or previously connected device // Show preference if there is connected or previously connected device
// Find active device and set its name as the preference's summary // Find active device and set its name as the preference's summary
List<BluetoothDevice> connectableA2dpDevices = getConnectableA2dpDevices(); List<BluetoothDevice> connectedA2dpDevices = getConnectedA2dpDevices();
List<BluetoothDevice> connectableHADevices = getConnectableHearingAidDevices(); List<BluetoothDevice> connectedHADevices = getConnectedHearingAidDevices();
if (mAudioManager.getMode() == AudioManager.MODE_NORMAL if (mAudioManager.getMode() == AudioManager.MODE_NORMAL
&& ((connectableA2dpDevices != null && !connectableA2dpDevices.isEmpty()) && ((connectedA2dpDevices != null && !connectedA2dpDevices.isEmpty())
|| (connectableHADevices != null && !connectableHADevices.isEmpty()))) { || (connectedHADevices != null && !connectedHADevices.isEmpty()))) {
deviceConnectable = true; deviceConnected = true;
activeDevice = findActiveDevice(); activeDevice = findActiveDevice();
} }
mPreference.setVisible(deviceConnectable); mPreference.setVisible(deviceConnected);
mPreference.setSummary((activeDevice == null) ? mPreference.setSummary((activeDevice == null) ?
mContext.getText(R.string.media_output_default_summary) : mContext.getText(R.string.media_output_default_summary) :
activeDevice.getAliasName()); activeDevice.getAliasName());

View File

@@ -109,7 +109,7 @@ public class MediaOutputPreferenceControllerTest {
private BluetoothDevice mRightBluetoothHapDevice; private BluetoothDevice mRightBluetoothHapDevice;
private LocalBluetoothManager mLocalBluetoothManager; private LocalBluetoothManager mLocalBluetoothManager;
private MediaOutputPreferenceController mController; private MediaOutputPreferenceController mController;
private List<BluetoothDevice> mProfileConnectableDevices; private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices; private List<BluetoothDevice> mHearingAidActiveDevices;
@Before @Before
@@ -150,7 +150,7 @@ public class MediaOutputPreferenceControllerTest {
mController = new MediaOutputPreferenceController(mContext, TEST_KEY); mController = new MediaOutputPreferenceController(mContext, TEST_KEY);
mScreen = spy(new PreferenceScreen(mContext, null)); mScreen = spy(new PreferenceScreen(mContext, null));
mPreference = new Preference(mContext); mPreference = new Preference(mContext);
mProfileConnectableDevices = new ArrayList<>(); mProfileConnectedDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2); mHearingAidActiveDevices = new ArrayList<>(2);
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
@@ -172,11 +172,11 @@ public class MediaOutputPreferenceControllerTest {
* Preference should be invisible * Preference should be invisible
*/ */
@Test @Test
public void updateState_withoutConnectableBtDevice_preferenceInvisible() { public void updateState_withoutConnectedBtDevice_preferenceInvisible() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE);
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mProfileConnectableDevices.clear(); mProfileConnectedDevices.clear();
when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
mPreference.setVisible(true); mPreference.setVisible(true);
assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.isVisible()).isTrue();
@@ -185,16 +185,16 @@ public class MediaOutputPreferenceControllerTest {
} }
/** /**
* A2DP Bluetooth device(s) are connectable, no matter active or inactive * A2DP Bluetooth device(s) are connected, no matter active or inactive
* Preference should be visible * Preference should be visible
*/ */
@Test @Test
public void updateState_withConnectableBtDevice_preferenceVisible() { public void updateState_withConnectedBtDevice_preferenceVisible() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mProfileConnectableDevices.clear(); mProfileConnectedDevices.clear();
mProfileConnectableDevices.add(mBluetoothDevice); mProfileConnectedDevices.add(mBluetoothDevice);
when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.isVisible()).isFalse();
// Without Active Bluetooth Device // Without Active Bluetooth Device
@@ -208,17 +208,17 @@ public class MediaOutputPreferenceControllerTest {
} }
/** /**
* A2DP Bluetooth device(s) are connectable, but no device is set as activated * A2DP Bluetooth device(s) are connected, but no device is set as activated
* Preference summary should be "This device" * Preference summary should be "This device"
*/ */
@Test @Test
public void updateState_withConnectableBtDevice_withoutActiveBtDevice_setDefaultSummary() { public void updateState_withConnectedBtDevice_withoutActiveBtDevice_setDefaultSummary() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE);
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mProfileConnectableDevices.clear(); mProfileConnectedDevices.clear();
mProfileConnectableDevices.add(mBluetoothDevice); mProfileConnectedDevices.add(mBluetoothDevice);
mProfileConnectableDevices.add(mSecondBluetoothDevice); mProfileConnectedDevices.add(mSecondBluetoothDevice);
when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
when(mA2dpProfile.getActiveDevice()).thenReturn(null); when(mA2dpProfile.getActiveDevice()).thenReturn(null);
assertThat(mPreference.getSummary()).isNull(); assertThat(mPreference.getSummary()).isNull();
@@ -235,10 +235,10 @@ public class MediaOutputPreferenceControllerTest {
public void updateState_withActiveBtDevice_setActivatedDeviceName() { public void updateState_withActiveBtDevice_setActivatedDeviceName() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mProfileConnectableDevices.clear(); mProfileConnectedDevices.clear();
mProfileConnectableDevices.add(mBluetoothDevice); mProfileConnectedDevices.add(mBluetoothDevice);
mProfileConnectableDevices.add(mSecondBluetoothDevice); mProfileConnectedDevices.add(mSecondBluetoothDevice);
when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
assertThat(mPreference.getSummary()).isNull(); assertThat(mPreference.getSummary()).isNull();
@@ -248,16 +248,16 @@ public class MediaOutputPreferenceControllerTest {
/** /**
* Hearing Aid device(s) are connectable, no matter active or inactive * Hearing Aid device(s) are connected, no matter active or inactive
* Preference should be visible * Preference should be visible
*/ */
@Test @Test
public void updateState_withConnectableHADevice_preferenceVisible() { public void updateState_withConnectedHADevice_preferenceVisible() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mHearingAidActiveDevices.clear(); mHearingAidActiveDevices.clear();
mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); when(mHearingAidProfile.getConnectedDevices()).thenReturn(mHearingAidActiveDevices);
assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.isVisible()).isFalse();
// Without Active Hearing Aid Device // Without Active Hearing Aid Device
@@ -280,7 +280,7 @@ public class MediaOutputPreferenceControllerTest {
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mHearingAidActiveDevices.clear(); mHearingAidActiveDevices.clear();
mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); when(mHearingAidProfile.getConnectedDevices()).thenReturn(mHearingAidActiveDevices);
when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
assertThat(mPreference.getSummary()).isNull(); assertThat(mPreference.getSummary()).isNull();
@@ -332,22 +332,6 @@ public class MediaOutputPreferenceControllerTest {
mContext.getText(R.string.media_out_summary_ongoing_call_state)); mContext.getText(R.string.media_out_summary_ongoing_call_state));
} }
/**
* Media stream is captured by something else (cast device):
* Preference should be invisible
* Preference summary should be "unavailable"
*/
@Test
public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_REMOTE_SUBMIX);
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isFalse();
String defaultString = mContext.getString(R.string.media_output_summary_unavailable);
assertThat(mPreference.getSummary()).isEqualTo(defaultString);
}
@Test @Test
public void findActiveDevice_onlyA2dpDeviceActive_returnA2dpDevice() { public void findActiveDevice_onlyA2dpDeviceActive_returnA2dpDevice() {
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null); when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null);