diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java index 2e935391522..548d17cc9ce 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java @@ -16,13 +16,9 @@ package com.android.settings.connecteddevice.audiosharing; -import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.content.Context; -import android.media.AudioManager; import android.util.Log; -import android.widget.SeekBar; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -40,7 +36,7 @@ import com.android.settingslib.bluetooth.VolumeControlProfile; public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdater implements Preference.OnPreferenceClickListener { - private static final String TAG = "AudioSharingDeviceVolumeControlUpdater"; + private static final String TAG = "AudioSharingVolUpdater"; @VisibleForTesting static final String PREF_KEY_PREFIX = "audio_sharing_volume_control_"; @@ -91,36 +87,9 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat if (cachedDevice == null) return; final BluetoothDevice device = cachedDevice.getDevice(); if (!mPreferenceMap.containsKey(device)) { - SeekBar.OnSeekBarChangeListener listener = - new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged( - SeekBar seekBar, int progress, boolean fromUser) {} - - @Override - public void onStartTrackingTouch(SeekBar seekBar) {} - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - int progress = seekBar.getProgress(); - int groupId = BluetoothUtils.getGroupId(cachedDevice); - if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID - && groupId - == BluetoothUtils.getPrimaryGroupIdForBroadcast( - mContext.getContentResolver())) { - // Set media stream volume for primary buds, audio manager will - // update all buds volume in the audio sharing. - setAudioManagerStreamVolume(progress); - } else { - // Set buds volume for other buds. - setDeviceVolume(cachedDevice, progress); - } - } - }; AudioSharingDeviceVolumePreference vPreference = new AudioSharingDeviceVolumePreference(mPrefContext, cachedDevice); vPreference.initialize(); - vPreference.setOnSeekBarChangeListener(listener); vPreference.setKey(getPreferenceKeyPrefix() + cachedDevice.hashCode()); vPreference.setIcon(com.android.settingslib.R.drawable.ic_bt_untethered_earbuds); vPreference.setTitle(cachedDevice.getName()); @@ -154,35 +123,4 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat @Override public void refreshPreference() {} - - private void setDeviceVolume(CachedBluetoothDevice cachedDevice, int progress) { - if (mVolumeControl != null) { - mVolumeControl.setDeviceVolume( - cachedDevice.getDevice(), progress, /* isGroupOp= */ true); - mMetricsFeatureProvider.action( - mContext, - SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, - /* isPrimary= */ false); - } - } - - private void setAudioManagerStreamVolume(int progress) { - int seekbarRange = - AudioSharingDeviceVolumePreference.MAX_VOLUME - - AudioSharingDeviceVolumePreference.MIN_VOLUME; - try { - AudioManager audioManager = mContext.getSystemService(AudioManager.class); - int streamVolumeRange = - audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) - - audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC); - int volume = Math.round((float) progress * streamVolumeRange / seekbarRange); - audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); - mMetricsFeatureProvider.action( - mContext, - SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, - /* isPrimary= */ true); - } catch (RuntimeException e) { - Log.e(TAG, "Fail to setAudioManagerStreamVolumeForFallbackDevice, error = " + e); - } - } } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java index 48b04b4b58c..42de10a81b2 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java @@ -61,7 +61,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePreferenceController implements DevicePreferenceCallback { - private static final String TAG = "AudioSharingDeviceVolumeGroupController"; + private static final String TAG = "AudioSharingVolCtlr"; private static final String KEY = "audio_sharing_device_volume_group"; @Nullable private final LocalBluetoothManager mBtManager; diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java index 01afc023098..816ec6e2cd3 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java @@ -16,27 +16,46 @@ package com.android.settings.connecteddevice.audiosharing; +import android.app.settings.SettingsEnums; +import android.bluetooth.BluetoothCsipSetCoordinator; +import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.media.AudioManager; +import android.util.Log; import android.widget.SeekBar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.settings.R; +import com.android.settings.bluetooth.Utils; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.SeekBarPreference; +import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.VolumeControlProfile; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.utils.ThreadUtils; public class AudioSharingDeviceVolumePreference extends SeekBarPreference { + private static final String TAG = "AudioSharingVolPref"; + public static final int MIN_VOLUME = 0; public static final int MAX_VOLUME = 255; + private final Context mContext; private final CachedBluetoothDevice mCachedDevice; @Nullable protected SeekBar mSeekBar; + private Boolean mTrackingTouch = false; + private MetricsFeatureProvider mMetricsFeatureProvider = + FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); public AudioSharingDeviceVolumePreference( Context context, @NonNull CachedBluetoothDevice device) { super(context); setLayoutResource(R.layout.preference_volume_slider); + mContext = context; mCachedDevice = device; } @@ -54,4 +73,95 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference { setMax(MAX_VOLUME); setMin(MIN_VOLUME); } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + super.onProgressChanged(seekBar, progress, fromUser); + // When user use talk back swipe up/down or use Switch Access to change the volume bar + // progress, there is no onStopTrackingTouch triggered. So we need to check this scenario + // and update the device volume here. + if (fromUser && !mTrackingTouch) { + Log.d(TAG, "onProgressChanged from user and not in touch, handleProgressChange."); + handleProgressChange(progress); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mTrackingTouch = true; + super.onStartTrackingTouch(seekBar); + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mTrackingTouch = false; + super.onStopTrackingTouch(seekBar); + // When user touch the volume bar to change volume, we only update the device volume when + // user stop touching the bar. + Log.d(TAG, "onStopTrackingTouch, handleProgressChange."); + handleProgressChange(seekBar.getProgress()); + } + + private void handleProgressChange(int progress) { + var unused = + ThreadUtils.postOnBackgroundThread( + () -> { + int groupId = BluetoothUtils.getGroupId(mCachedDevice); + if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID + && groupId + == BluetoothUtils.getPrimaryGroupIdForBroadcast( + mContext.getContentResolver())) { + // Set media stream volume for primary buds, audio manager will + // update all buds volume in the audio sharing. + setAudioManagerStreamVolume(progress); + } else { + // Set buds volume for other buds. + setDeviceVolume(mCachedDevice.getDevice(), progress); + } + }); + } + + private void setDeviceVolume(@Nullable BluetoothDevice device, int progress) { + if (device == null) { + Log.d(TAG, "Skip set device volume, device is null"); + return; + } + LocalBluetoothManager btManager = Utils.getLocalBtManager(mContext); + VolumeControlProfile vc = + btManager == null ? null : btManager.getProfileManager().getVolumeControlProfile(); + if (vc != null) { + vc.setDeviceVolume(device, progress, /* isGroupOp= */ true); + mMetricsFeatureProvider.action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ false); + Log.d( + TAG, + "set device volume, device = " + + device.getAnonymizedAddress() + + " volume = " + + progress); + } + } + + private void setAudioManagerStreamVolume(int progress) { + int seekbarRange = + AudioSharingDeviceVolumePreference.MAX_VOLUME + - AudioSharingDeviceVolumePreference.MIN_VOLUME; + try { + AudioManager audioManager = mContext.getSystemService(AudioManager.class); + int streamVolumeRange = + audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) + - audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC); + int volume = Math.round((float) progress * streamVolumeRange / seekbarRange); + audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + mMetricsFeatureProvider.action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ true); + Log.d(TAG, "set music stream volume, volume = " + progress); + } catch (RuntimeException e) { + Log.e(TAG, "Fail to setAudioManagerStreamVolumeForFallbackDevice, error = " + e); + } + } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java index 3c12946b7e2..95e51e99d51 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java @@ -31,15 +31,11 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; -import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.media.AudioManager; import android.os.Looper; -import android.provider.Settings; -import android.widget.SeekBar; import androidx.preference.Preference; import androidx.test.core.app.ApplicationProvider; @@ -47,7 +43,6 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.bluetooth.BluetoothDevicePreference; import com.android.settings.bluetooth.Utils; import com.android.settings.connecteddevice.DevicePreferenceCallback; -import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; @@ -55,7 +50,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.bluetooth.VolumeControlProfile; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -80,13 +74,7 @@ import java.util.List; @Config(shadows = {ShadowBluetoothUtils.class}) public class AudioSharingDeviceVolumeControlUpdaterTest { private static final String TEST_DEVICE_NAME = "test"; - private static final String TAG = "AudioSharingDeviceVolumeControlUpdater"; - private static final String TEST_SETTINGS_KEY = - "bluetooth_le_broadcast_fallback_active_group_id"; - private static final int TEST_DEVICE_GROUP_ID = 1; - private static final int TEST_VOLUME_VALUE = 255; - private static final int TEST_MAX_STREAM_VALUE = 10; - private static final int TEST_MIN_STREAM_VALUE = 0; + private static final String TAG = "AudioSharingVolUpdater"; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @@ -98,39 +86,32 @@ public class AudioSharingDeviceVolumeControlUpdaterTest { @Mock private LocalBluetoothProfileManager mLocalBtProfileManager; @Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothLeBroadcastAssistant mAssistant; - @Mock private VolumeControlProfile mVolumeControl; @Mock private BluetoothLeBroadcastReceiveState mState; - @Mock private AudioManager mAudioManager; private Context mContext; private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater; private Collection mCachedDevices; - private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { - mContext = spy(ApplicationProvider.getApplicationContext()); + mContext = ApplicationProvider.getApplicationContext(); ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; mLocalBtManager = Utils.getLocalBtManager(mContext); - mFeatureFactory = FakeFeatureFactory.setupForTest(); when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager); when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); - when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl); List bisSyncState = new ArrayList<>(); bisSyncState.add(1L); when(mState.getBisSyncState()).thenReturn(bisSyncState); doReturn(TEST_DEVICE_NAME).when(mCachedBluetoothDevice).getName(); doReturn(mBluetoothDevice).when(mCachedBluetoothDevice).getDevice(); doReturn(ImmutableSet.of()).when(mCachedBluetoothDevice).getMemberDevice(); - doReturn(TEST_DEVICE_GROUP_ID).when(mCachedBluetoothDevice).getGroupId(); mCachedDevices = new ArrayList<>(); mCachedDevices.add(mCachedBluetoothDevice); when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices); doNothing().when(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class)); doNothing().when(mDevicePreferenceCallback).onDeviceRemoved(any(Preference.class)); - when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); mDeviceUpdater = spy( new AudioSharingDeviceVolumeControlUpdater( @@ -250,76 +231,6 @@ public class AudioSharingDeviceVolumeControlUpdaterTest { .isEqualTo(mCachedBluetoothDevice); } - @Test - public void addPreference_notFallbackDevice_setDeviceVolume() { - ArgumentCaptor captor = ArgumentCaptor.forClass(Preference.class); - setupPreferenceMapWithDevice(); - - verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture()); - assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue(); - AudioSharingDeviceVolumePreference preference = - (AudioSharingDeviceVolumePreference) captor.getValue(); - - SeekBar seekBar = mock(SeekBar.class); - when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE); - preference.onStopTrackingTouch(seekBar); - - verify(mVolumeControl) - .setDeviceVolume(mBluetoothDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true); - verifyNoInteractions(mAudioManager); - verify(mFeatureFactory.metricsFeatureProvider) - .action( - mContext, - SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, - /* isPrimary= */ false); - } - - @Test - public void addPreference_fallbackDevice_setStreamVolume() { - ArgumentCaptor captor = ArgumentCaptor.forClass(Preference.class); - setupPreferenceMapWithDevice(); - - verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture()); - assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue(); - AudioSharingDeviceVolumePreference preference = - (AudioSharingDeviceVolumePreference) captor.getValue(); - - Settings.Secure.putInt( - mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID); - when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) - .thenReturn(TEST_MAX_STREAM_VALUE); - when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)) - .thenReturn(TEST_MIN_STREAM_VALUE); - SeekBar seekBar = mock(SeekBar.class); - when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE); - preference.onStopTrackingTouch(seekBar); - - verifyNoInteractions(mVolumeControl); - verify(mAudioManager) - .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0); - verify(mFeatureFactory.metricsFeatureProvider) - .action( - mContext, - SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, - /* isPrimary= */ true); - } - - @Test - public void testOnSeekBarChangeListener_doNothing() { - ArgumentCaptor captor = ArgumentCaptor.forClass(Preference.class); - setupPreferenceMapWithDevice(); - - verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture()); - assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue(); - AudioSharingDeviceVolumePreference preference = - (AudioSharingDeviceVolumePreference) captor.getValue(); - SeekBar seekBar = mock(SeekBar.class); - preference.onProgressChanged(seekBar, TEST_VOLUME_VALUE, /* fromUser= */ false); - - verifyNoInteractions(mAudioManager); - verifyNoInteractions(mVolumeControl); - } - @Test public void getLogTag_returnsCorrectTag() { assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java index 8ceb0eba7ed..5ff143fa1dc 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java @@ -18,11 +18,32 @@ package com.android.settings.connecteddevice.audiosharing; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import android.app.settings.SettingsEnums; +import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.media.AudioManager; +import android.provider.Settings; +import android.widget.SeekBar; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.bluetooth.Utils; +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowBluetoothUtils; +import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.bluetooth.VolumeControlProfile; import org.junit.Before; import org.junit.Rule; @@ -32,18 +53,45 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowBluetoothUtils.class}) public class AudioSharingDeviceVolumePreferenceTest { + private static final int TEST_DEVICE_GROUP_ID = 1; + private static final int TEST_VOLUME_VALUE = 255; + private static final int TEST_MAX_STREAM_VALUE = 10; + private static final int TEST_MIN_STREAM_VALUE = 0; + @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock private LocalBluetoothManager mLocalBtManager; + @Mock private LocalBluetoothProfileManager mLocalBtProfileManager; + @Mock private VolumeControlProfile mVolumeControl; @Mock private CachedBluetoothDevice mCachedDevice; + @Mock private BluetoothDevice mDevice; + @Mock private AudioManager mAudioManager; + @Mock private SeekBar mSeekBar; private Context mContext; private AudioSharingDeviceVolumePreference mPreference; + private FakeFeatureFactory mFeatureFactory; @Before public void setup() { - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; + mLocalBtManager = Utils.getLocalBtManager(mContext); + mFeatureFactory = FakeFeatureFactory.setupForTest(); + when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager); + when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl); + when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); + when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) + .thenReturn(TEST_MAX_STREAM_VALUE); + when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)) + .thenReturn(TEST_MIN_STREAM_VALUE); + when(mCachedDevice.getDevice()).thenReturn(mDevice); + when(mCachedDevice.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID); + when(mSeekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE); mPreference = new AudioSharingDeviceVolumePreference(mContext, mCachedDevice); } @@ -58,4 +106,128 @@ public class AudioSharingDeviceVolumePreferenceTest { assertThat(mPreference.getMax()).isEqualTo(AudioSharingDeviceVolumePreference.MAX_VOLUME); assertThat(mPreference.getMin()).isEqualTo(AudioSharingDeviceVolumePreference.MIN_VOLUME); } + + @Test + public void onStopTrackingTouch_notFallbackDevice_setDeviceVolume() { + mPreference.onStopTrackingTouch(mSeekBar); + + verify(mVolumeControl).setDeviceVolume(mDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ false); + } + + @Test + public void onProgressChanged_notFallbackDevice_fromUserNotInTouch_setDeviceVolume() { + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verify(mVolumeControl).setDeviceVolume(mDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ false); + } + + @Test + public void onProgressChanged_notFallbackDevice_fromUserInTouch_doNothing() { + mPreference.onStartTrackingTouch(mSeekBar); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } + + @Test + public void onProgressChanged_notFallbackDevice_notFromUserNotInTouch_doNothing() { + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ false); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } + + @Test + public void onStopTrackingTouch_fallbackDevice_setDeviceVolume() { + Settings.Secure.putInt( + mContext.getContentResolver(), + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID); + mPreference.onStopTrackingTouch(mSeekBar); + + verifyNoInteractions(mVolumeControl); + verify(mAudioManager) + .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ true); + } + + @Test + public void onProgressChanged_fallbackDevice_fromUserNotInTouch_setDeviceVolume() { + Settings.Secure.putInt( + mContext.getContentResolver(), + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verifyNoInteractions(mVolumeControl); + verify(mAudioManager) + .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ true); + } + + @Test + public void onProgressChanged_fallbackDevice_fromUserInTouch_doNothing() { + Settings.Secure.putInt( + mContext.getContentResolver(), + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID); + mPreference.onStartTrackingTouch(mSeekBar); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } + + @Test + public void onProgressChanged_fallbackDevice_notFromUserNotInTouch_doNothing() { + Settings.Secure.putInt( + mContext.getContentResolver(), + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ false); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } }