Add setting page for the Spatial audio
The Spatial audio settings page control the state for the phone speaker
and the wired headphones
Test: make RunSettingsRoboTests
Bug: 220811398
Change-Id: I49e3fab48186d09357a8481652bdccb4aa5d044a
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cb6bcff..6df5b92 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8531,6 +8531,24 @@
<!-- Setting summary for controlling how caption text display in real time [CHAR LIMIT=NONE]-->
<string name="live_caption_summary">Automatically caption media</string>
+ <!-- Output device type for the phone speaker that is available for spatializer effect. [CHAR LIMIT=NONE]-->
+ <string name="spatial_audio_speaker">Phone speaker</string>
+
+ <!-- Output device type for the wired headphones that is available for spatializer effect. [CHAR LIMIT=NONE]-->
+ <string name="spatial_audio_wired_headphones">Wired headphones</string>
+
+ <!-- Sound: Summary for the spatializer effect. [CHAR LIMIT=NONE]-->
+ <string name="spatial_audio_text">Spatial Audio creates immersive sound that seems like it’s coming from all around you. Only works with some media.</string>
+
+ <!-- Sound: Summary for the Spatial audio setting when it is off. [CHAR LIMIT=NONE]-->
+ <string name="spatial_summary_off">Off</string>
+
+ <!-- Sound: Summary for the Spatial audio setting when it is on with one output device enabled. [CHAR LIMIT=NONE]-->
+ <string name="spatial_summary_on_one">On / <xliff:g id="output device" example="Phone speaker">%1$s</xliff:g></string>
+
+ <!-- Sound: Summary for the Spatial audio setting when it is on with two output devices enabled. [CHAR LIMIT=NONE]-->
+ <string name="spatial_summary_on_two">On / <xliff:g id="output device" example="Phone speaker">%1$s</xliff:g> and <xliff:g id="output device" example="Wired headphones">%2$s</xliff:g></string>
+
<!-- Sound: Summary for the Do not Disturb option that describes how many automatic rules (schedules) are enabled [CHAR LIMIT=NONE]-->
<string name="zen_mode_settings_schedules_summary">
{count, plural,
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d79594c..f25b6ec 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -111,6 +111,15 @@
settings:keywords="@string/sound_settings"/>
<!-- Live Caption -110 and Now Playing -105-->
+
+ <!-- Spatial audio -->
+ <Preference
+ android:key="spatial_audio_summary"
+ android:title="@string/spatial_audio_title"
+ android:fragment="com.android.settings.notification.SpatialAudioSettings"
+ android:order="-107"
+ settings:controller="com.android.settings.notification.SpatialAudioParentPreferenceController"/>
+
<Preference
android:key="media_controls_summary"
android:title="@string/media_controls_title"
@@ -154,13 +163,6 @@
android:ringtoneType="alarm"
android:order="-60"/>
- <!-- Spatial audio -->
- <SwitchPreference
- android:key="spatial_audio"
- android:title="@string/spatial_audio_title"
- android:order="-55"
- settings:controller="com.android.settings.notification.SpatialAudioPreferenceController"/>
-
<!-- Dial pad tones -->
<SwitchPreference
android:key="dial_pad_tones"
diff --git a/res/xml/spatial_audio_settings.xml b/res/xml/spatial_audio_settings.xml
new file mode 100644
index 0000000..da33986
--- /dev/null
+++ b/res/xml/spatial_audio_settings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/spatial_audio_title">
+
+ <com.android.settingslib.widget.TopIntroPreference
+ android:key="spatial_audio_top_intro"
+ android:title="@string/spatial_audio_text"
+ settings:searchable="false"/>
+
+ <SwitchPreference
+ android:key="spatial_audio"
+ android:title="@string/spatial_audio_speaker"
+ settings:controller="com.android.settings.notification.SpatialAudioPreferenceController"/>
+
+ <SwitchPreference
+ android:key="spatial_audio_wired_headphones"
+ android:title="@string/spatial_audio_wired_headphones"
+ settings:controller="com.android.settings.notification.SpatialAudioWiredHeadphonesController"/>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/notification/SpatialAudioParentPreferenceController.java b/src/com/android/settings/notification/SpatialAudioParentPreferenceController.java
new file mode 100644
index 0000000..52eea54
--- /dev/null
+++ b/src/com/android/settings/notification/SpatialAudioParentPreferenceController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.Spatializer;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Parent menu summary of the Spatial audio settings
+ */
+public class SpatialAudioParentPreferenceController extends BasePreferenceController {
+ private static final String TAG = "SpatialAudioSetting";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final Spatializer mSpatializer;
+ private SpatialAudioPreferenceController mSpatialAudioPreferenceController;
+ private SpatialAudioWiredHeadphonesController mSpatialAudioWiredHeadphonesController;
+
+ public SpatialAudioParentPreferenceController(Context context, String key) {
+ super(context, key);
+ AudioManager audioManager = context.getSystemService(AudioManager.class);
+ mSpatializer = audioManager.getSpatializer();
+ mSpatialAudioPreferenceController = new SpatialAudioPreferenceController(context);
+ mSpatialAudioWiredHeadphonesController = new SpatialAudioWiredHeadphonesController(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ int level = mSpatializer.getImmersiveAudioLevel();
+ if (DEBUG) {
+ Log.d(TAG, "spatialization level: " + level);
+ }
+ return level == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE
+ ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ boolean speakerOn = mSpatialAudioPreferenceController.isAvailable()
+ && mSpatialAudioWiredHeadphonesController.isChecked();
+ boolean wiredHeadphonesOn = mSpatialAudioWiredHeadphonesController.isAvailable()
+ && mSpatialAudioWiredHeadphonesController.isChecked();
+ if (speakerOn && wiredHeadphonesOn) {
+ return mContext.getString(R.string.spatial_summary_on_two,
+ mContext.getString(R.string.spatial_audio_speaker),
+ mContext.getString(R.string.spatial_audio_wired_headphones));
+ } else if (speakerOn) {
+ return mContext.getString(R.string.spatial_summary_on_one,
+ mContext.getString(R.string.spatial_audio_speaker));
+ } else if (wiredHeadphonesOn) {
+ return mContext.getString(R.string.spatial_summary_on_one,
+ mContext.getString(R.string.spatial_audio_wired_headphones));
+ } else {
+ return mContext.getString(R.string.spatial_summary_off);
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/SpatialAudioPreferenceController.java b/src/com/android/settings/notification/SpatialAudioPreferenceController.java
index 7bca516..b9a0776 100644
--- a/src/com/android/settings/notification/SpatialAudioPreferenceController.java
+++ b/src/com/android/settings/notification/SpatialAudioPreferenceController.java
@@ -17,46 +17,61 @@
package com.android.settings.notification;
import android.content.Context;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.Spatializer;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
/**
- * The controller of the Spatial audio setting in the SoundSettings.
+ * The controller of the Spatial audio setting for speaker in the SoundSettings.
*/
public class SpatialAudioPreferenceController extends TogglePreferenceController {
private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
private final Spatializer mSpatializer;
+ @VisibleForTesting
+ final AudioDeviceAttributes mSpeaker = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, ""
+ );
public SpatialAudioPreferenceController(Context context) {
- super(context, KEY_SPATIAL_AUDIO);
+ this(context, KEY_SPATIAL_AUDIO);
+ }
+
+ public SpatialAudioPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
AudioManager audioManager = context.getSystemService(AudioManager.class);
mSpatializer = audioManager.getSpatializer();
}
@Override
public int getAvailabilityStatus() {
- return mSpatializer.getImmersiveAudioLevel() == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE
- ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
+ return mSpatializer.isAvailableForDevice(mSpeaker) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
- return mSpatializer.isEnabled();
+ return mSpatializer.getCompatibleAudioDevices().contains(mSpeaker);
}
@Override
public boolean setChecked(boolean isChecked) {
- mSpatializer.setEnabled(isChecked);
+ if (isChecked) {
+ mSpatializer.addCompatibleAudioDevice(mSpeaker);
+ } else {
+ mSpatializer.removeCompatibleAudioDevice(mSpeaker);
+ }
return isChecked == isChecked();
}
@Override
public int getSliceHighlightMenuRes() {
- return R.string.menu_key_notifications;
+ return R.string.menu_key_sound;
}
}
diff --git a/src/com/android/settings/notification/SpatialAudioSettings.java b/src/com/android/settings/notification/SpatialAudioSettings.java
new file mode 100644
index 0000000..eb68e87
--- /dev/null
+++ b/src/com/android/settings/notification/SpatialAudioSettings.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Spatial audio settings located in the sound menu
+ */
+@SearchIndexable
+public class SpatialAudioSettings extends DashboardFragment {
+
+ private static final String TAG = "SpatialAudioSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_SPATIAL_AUDIO;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.spatial_audio_settings;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new SpatialAudioPreferenceController(context));
+ controllers.add(new SpatialAudioWiredHeadphonesController(context));
+ return controllers;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.spatial_audio_settings) {
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/SpatialAudioWiredHeadphonesController.java b/src/com/android/settings/notification/SpatialAudioWiredHeadphonesController.java
new file mode 100644
index 0000000..cd723f9
--- /dev/null
+++ b/src/com/android/settings/notification/SpatialAudioWiredHeadphonesController.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.Spatializer;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * The controller of the Spatial audio setting for wired headphones in the SoundSettings.
+ */
+public class SpatialAudioWiredHeadphonesController extends TogglePreferenceController {
+
+ private static final String KEY_SPATIAL_AUDIO_WIRED_HEADPHONES =
+ "spatial_audio_wired_headphones";
+
+ private final Spatializer mSpatializer;
+ @VisibleForTesting
+ final AudioDeviceAttributes mWiredHeadphones = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_WIRED_HEADPHONES, ""
+ );
+
+ public SpatialAudioWiredHeadphonesController(Context context) {
+ this(context, KEY_SPATIAL_AUDIO_WIRED_HEADPHONES);
+ }
+
+ public SpatialAudioWiredHeadphonesController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ AudioManager audioManager = context.getSystemService(AudioManager.class);
+ mSpatializer = audioManager.getSpatializer();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mSpatializer.isAvailableForDevice(mWiredHeadphones) ? AVAILABLE
+ : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mSpatializer.getCompatibleAudioDevices().contains(mWiredHeadphones);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (isChecked) {
+ mSpatializer.addCompatibleAudioDevice(mWiredHeadphones);
+ } else {
+ mSpatializer.removeCompatibleAudioDevice(mWiredHeadphones);
+ }
+ return isChecked == isChecked();
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return R.string.menu_key_sound;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/SpatialAudioParentPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SpatialAudioParentPreferenceControllerTest.java
new file mode 100644
index 0000000..9242cf0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/SpatialAudioParentPreferenceControllerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.Spatializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class SpatialAudioParentPreferenceControllerTest {
+
+ private static final String KEY = "spatial_audio_summary";
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private Spatializer mSpatializer;
+
+ private SpatialAudioParentPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+ when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
+ mController = new SpatialAudioParentPreferenceController(mContext, KEY);
+ }
+
+ @Test
+ public void getAvailabilityStatus_levelNone_shouldReturnUnsupported() {
+ when(mSpatializer.getImmersiveAudioLevel()).thenReturn(
+ Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_levelMultiChannel_shouldReturnAvailable() {
+ when(mSpatializer.getImmersiveAudioLevel()).thenReturn(
+ Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java
index 66d18ec..e57b897 100644
--- a/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java
@@ -30,7 +30,6 @@
import android.media.Spatializer;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -39,7 +38,6 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@Ignore("b/200896161")
@RunWith(RobolectricTestRunner.class)
public class SpatialAudioPreferenceControllerTest {
@@ -56,36 +54,36 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- when((Object) mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+ when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
mController = new SpatialAudioPreferenceController(mContext);
}
@Test
- public void getAvailabilityStatus_levelNone_shouldReturnUnsupported() {
- when(mSpatializer.getImmersiveAudioLevel()).thenReturn(
- Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE);
+ public void getAvailabilityStatus_unavailable_shouldReturnUnavailable() {
+ when(mSpatializer.isAvailableForDevice(mController.mSpeaker)).thenReturn(false);
+
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
- public void getAvailabilityStatus_levelMultiChannel_shouldReturnAvailable() {
- when(mSpatializer.getImmersiveAudioLevel()).thenReturn(
- Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL);
+ public void getAvailabilityStatus_available_shouldReturnAvailable() {
+ when(mSpatializer.isAvailableForDevice(mController.mSpeaker)).thenReturn(true);
+
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
- public void setChecked_withTrue_shouldEnableSpatializer() {
+ public void setChecked_withTrue_enablesDeviceSpatializer() {
mController.setChecked(true);
- verify(mSpatializer).setEnabled(true);
+ verify(mSpatializer).addCompatibleAudioDevice(mController.mSpeaker);
}
@Test
- public void setChecked_withFalse_shouldDisableSpatializer() {
+ public void setChecked_withFalse_disablesDeviceSpatializer() {
mController.setChecked(false);
- verify(mSpatializer).setEnabled(false);
+ verify(mSpatializer).removeCompatibleAudioDevice(mController.mSpeaker);
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/SpatialAudioWiredHeadphonesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SpatialAudioWiredHeadphonesPreferenceControllerTest.java
new file mode 100644
index 0000000..29525e4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/SpatialAudioWiredHeadphonesPreferenceControllerTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.Spatializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class SpatialAudioWiredHeadphonesPreferenceControllerTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private Spatializer mSpatializer;
+
+ private SpatialAudioWiredHeadphonesController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+ when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
+ mController = new SpatialAudioWiredHeadphonesController(mContext);
+ }
+
+ @Test
+ public void getAvailabilityStatus_unavailable_shouldReturnUnavailable() {
+ when(mSpatializer.isAvailableForDevice(mController.mWiredHeadphones)).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_available_shouldReturnAvailable() {
+ when(mSpatializer.isAvailableForDevice(mController.mWiredHeadphones)).thenReturn(true);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void setChecked_withTrue_enablesDeviceSpatializer() {
+ mController.setChecked(true);
+
+ verify(mSpatializer).addCompatibleAudioDevice(mController.mWiredHeadphones);
+ }
+
+ @Test
+ public void setChecked_withFalse_disablesDeviceSpatializer() {
+ mController.setChecked(false);
+
+ verify(mSpatializer).removeCompatibleAudioDevice(mController.mWiredHeadphones);
+ }
+}