Loading services/core/java/com/android/server/audio/SpatializerHelper.java +72 −38 Original line number Diff line number Diff line Loading @@ -106,12 +106,12 @@ public class SpatializerHelper { }; // Spatializer state machine private static final int STATE_UNINITIALIZED = 0; private static final int STATE_NOT_SUPPORTED = 1; private static final int STATE_DISABLED_UNAVAILABLE = 3; private static final int STATE_ENABLED_UNAVAILABLE = 4; private static final int STATE_ENABLED_AVAILABLE = 5; private static final int STATE_DISABLED_AVAILABLE = 6; /*package*/ static final int STATE_UNINITIALIZED = 0; /*package*/ static final int STATE_NOT_SUPPORTED = 1; /*package*/ static final int STATE_DISABLED_UNAVAILABLE = 3; /*package*/ static final int STATE_ENABLED_UNAVAILABLE = 4; /*package*/ static final int STATE_ENABLED_AVAILABLE = 5; /*package*/ static final int STATE_DISABLED_AVAILABLE = 6; private int mState = STATE_UNINITIALIZED; private boolean mFeatureEnabled = false; Loading Loading @@ -147,9 +147,9 @@ public class SpatializerHelper { .setSampleRate(48000) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build(); // device array to store the routing for the default attributes and format, size 1 because // media is never expected to be duplicated private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1]; // device array to store the routing for the default attributes and format, initialized to // an empty list as routing hasn't been established yet private static ArrayList<AudioDeviceAttributes> sRoutingDevices = new ArrayList<>(0); //--------------------------------------------------------------- // audio device compatibility / enabled Loading Loading @@ -184,11 +184,6 @@ public class SpatializerHelper { SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledDefault; } synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) { mBinauralSupported = hasBinaural; mTransauralSupported = hasTransaural; } synchronized void init(boolean effectExpected, @Nullable String settings) { loglogi("init effectExpected=" + effectExpected); if (!effectExpected) { Loading Loading @@ -322,8 +317,7 @@ public class SpatializerHelper { return; } mState = STATE_DISABLED_UNAVAILABLE; mASA.getDevicesForAttributes( DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES); sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES); // note at this point mSpat is still not instantiated } Loading Loading @@ -365,34 +359,35 @@ public class SpatializerHelper { case STATE_DISABLED_AVAILABLE: break; } mASA.getDevicesForAttributes( DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES); sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES); // check validity of routing information if (ROUTING_DEVICES[0] == null) { logloge("onRoutingUpdated: device is null, no Spatial Audio"); if (sRoutingDevices.isEmpty()) { logloge("onRoutingUpdated: no device, no Spatial Audio"); setDispatchAvailableState(false); // not changing the spatializer level as this is likely a transient state return; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); // is media routed to a new device? if (isWireless(ROUTING_DEVICES[0].getType())) { addWirelessDeviceIfNew(ROUTING_DEVICES[0]); if (isWireless(currentDevice.getType())) { addWirelessDeviceIfNew(currentDevice); } // find if media device enabled / available final Pair<Boolean, Boolean> enabledAvailable = evaluateState(ROUTING_DEVICES[0]); final Pair<Boolean, Boolean> enabledAvailable = evaluateState(currentDevice); boolean able = false; if (enabledAvailable.second) { // available for Spatial audio, check w/ effect able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES); able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, sRoutingDevices); loglogi("onRoutingUpdated: can spatialize media 5.1:" + able + " on device:" + ROUTING_DEVICES[0]); + " on device:" + currentDevice); setDispatchAvailableState(able); } else { loglogi("onRoutingUpdated: device:" + ROUTING_DEVICES[0] loglogi("onRoutingUpdated: device:" + currentDevice + " not available for Spatial Audio"); setDispatchAvailableState(false); } Loading @@ -400,10 +395,10 @@ public class SpatializerHelper { boolean enabled = able && enabledAvailable.first; if (enabled) { loglogi("Enabling Spatial Audio since enabled for media device:" + ROUTING_DEVICES[0]); + currentDevice); } else { loglogi("Disabling Spatial Audio since disabled for media device:" + ROUTING_DEVICES[0]); + currentDevice); } if (mSpat != null) { byte level = enabled ? (byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL Loading Loading @@ -736,9 +731,13 @@ public class SpatializerHelper { } private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes, @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) { if (isDeviceCompatibleWithSpatializationModes(devices[0])) { return AudioSystem.canBeSpatialized(attributes, format, devices); @NonNull AudioFormat format, @NonNull ArrayList<AudioDeviceAttributes> devices) { if (devices.isEmpty()) { return false; } if (isDeviceCompatibleWithSpatializationModes(devices.get(0))) { AudioDeviceAttributes[] devArray = new AudioDeviceAttributes[devices.size()]; return AudioSystem.canBeSpatialized(attributes, format, devices.toArray(devArray)); } return false; } Loading Loading @@ -1014,10 +1013,13 @@ public class SpatializerHelper { logd("canBeSpatialized false due to usage:" + attributes.getUsage()); return false; } AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1]; // going through adapter to take advantage of routing cache mASA.getDevicesForAttributes( attributes, false /* forVolume */).toArray(devices); final ArrayList<AudioDeviceAttributes> devices = getRoutingDevices(attributes); if (devices.isEmpty()) { logloge("canBeSpatialized got no device for " + attributes); return false; } final boolean able = canBeSpatializedOnDevice(attributes, format, devices); logd("canBeSpatialized usage:" + attributes.getUsage() + " format:" + format.toLogFriendlyString() + " returning " + able); Loading Loading @@ -1148,8 +1150,13 @@ public class SpatializerHelper { logDeviceState(deviceState, "setHeadTrackerEnabled"); // check current routing to see if it affects the headtracking mode if (ROUTING_DEVICES[0] != null && ROUTING_DEVICES[0].getType() == ada.getType() && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) { if (sRoutingDevices.isEmpty()) { logloge("setHeadTrackerEnabled: no device, bailing"); return; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); if (currentDevice.getType() == ada.getType() && currentDevice.getAddress().equals(ada.getAddress())) { setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled : Spatializer.HEAD_TRACKING_MODE_DISABLED); if (enabled && !mHeadTrackerAvailable) { Loading Loading @@ -1706,10 +1713,11 @@ public class SpatializerHelper { private int getHeadSensorHandleUpdateTracker() { int headHandle = -1; final AudioDeviceAttributes currentDevice = ROUTING_DEVICES[0]; if (currentDevice == null) { if (sRoutingDevices.isEmpty()) { logloge("getHeadSensorHandleUpdateTracker: no device, no head tracker"); return headHandle; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice); // We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion // with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR Loading Loading @@ -1743,6 +1751,23 @@ public class SpatializerHelper { return screenHandle; } /** * Returns routing for the given attributes * @param aa AudioAttributes whose routing is being queried * @return a non-null never-empty list of devices. If the routing query failed, the list * will contain null. */ private @NonNull ArrayList<AudioDeviceAttributes> getRoutingDevices(AudioAttributes aa) { final ArrayList<AudioDeviceAttributes> devices = mASA.getDevicesForAttributes( aa, false /* forVolume */); for (AudioDeviceAttributes ada : devices) { if (ada == null) { // invalid entry, reject this routing query by returning an empty list return new ArrayList<>(0); } } return devices; } private static void loglogi(String msg) { AudioService.sSpatialLogger.loglogi(msg, TAG); Loading @@ -1759,4 +1784,13 @@ public class SpatializerHelper { /*package*/ void clearSADevices() { mSADevices.clear(); } /*package*/ synchronized void forceStateForTest(int state) { mState = state; } /*package*/ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) { mBinauralSupported = hasBinaural; mTransauralSupported = hasTransaural; } } services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java +60 −2 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.server.audio; import com.android.server.audio.SpatializerHelper.SADeviceState; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; import android.util.Log; Loading @@ -36,6 +41,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Spy; import java.util.ArrayList; import java.util.List; @MediumTest Loading @@ -49,16 +55,35 @@ public class SpatializerHelperTest { @Mock private AudioService mMockAudioService; @Spy private AudioSystemAdapter mSpyAudioSystem; @Mock private AudioSystemAdapter mMockAudioSystem; @Before public void setUp() throws Exception { mMockAudioService = mock(AudioService.class); mSpyAudioSystem = spy(new NoOpAudioSystemAdapter()); } mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem, /** * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy * AudioSystemAdapter * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use * the mock adapter, mMockAudioSystem. */ private void setUpSpatHelper(boolean useSpyAudioSystem) { final AudioSystemAdapter asAdapter; if (useSpyAudioSystem) { mSpyAudioSystem = spy(new NoOpAudioSystemAdapter()); asAdapter = mSpyAudioSystem; mMockAudioSystem = null; } else { mSpyAudioSystem = null; mMockAudioSystem = mock(NoOpAudioSystemAdapter.class); asAdapter = mMockAudioSystem; } mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter, true /*binauralEnabledDefault*/, true /*transauralEnabledDefault*/, false /*headTrackingEnabledDefault*/); } /** Loading @@ -68,6 +93,7 @@ public class SpatializerHelperTest { */ @Test public void testSADeviceStateNullAddressCtor() throws Exception { setUpSpatHelper(true /*useSpyAudioSystem*/); try { SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null); devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null); Loading @@ -78,6 +104,7 @@ public class SpatializerHelperTest { @Test public void testSADeviceStateStringSerialization() throws Exception { Log.i(TAG, "starting testSADeviceStateStringSerialization"); setUpSpatHelper(true /*useSpyAudioSystem*/); final SADeviceState devState = new SADeviceState( AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla"); devState.mHasHeadTracker = false; Loading @@ -93,6 +120,7 @@ public class SpatializerHelperTest { @Test public void testSADeviceSettings() throws Exception { Log.i(TAG, "starting testSADeviceSettings"); setUpSpatHelper(true /*useSpyAudioSystem*/); final AudioDeviceAttributes dev1 = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""); final AudioDeviceAttributes dev2 = Loading Loading @@ -143,4 +171,34 @@ public class SpatializerHelperTest { Log.i(TAG, "device settingsRestored: " + settingsRestored); Assert.assertEquals(settings, settingsRestored); } /** * Test that null devices for routing do not break canBeSpatialized * @throws Exception */ @Test public void testNoRoutingCanBeSpatialized() throws Exception { Log.i(TAG, "Starting testNoRoutingCanBeSpatialized"); setUpSpatHelper(false /*useSpyAudioSystem*/); mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE); final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0); final ArrayList<AudioDeviceAttributes> listWithNull = new ArrayList<>(1); listWithNull.add(null); final AudioAttributes media = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build(); final AudioFormat spatialFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build(); when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean())) .thenReturn(emptyList); Assert.assertFalse("can be spatialized on empty routing", mSpatHelper.canBeSpatialized(media, spatialFormat)); when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean())) .thenReturn(listWithNull); Assert.assertFalse("can be spatialized on null routing", mSpatHelper.canBeSpatialized(media, spatialFormat)); } } Loading
services/core/java/com/android/server/audio/SpatializerHelper.java +72 −38 Original line number Diff line number Diff line Loading @@ -106,12 +106,12 @@ public class SpatializerHelper { }; // Spatializer state machine private static final int STATE_UNINITIALIZED = 0; private static final int STATE_NOT_SUPPORTED = 1; private static final int STATE_DISABLED_UNAVAILABLE = 3; private static final int STATE_ENABLED_UNAVAILABLE = 4; private static final int STATE_ENABLED_AVAILABLE = 5; private static final int STATE_DISABLED_AVAILABLE = 6; /*package*/ static final int STATE_UNINITIALIZED = 0; /*package*/ static final int STATE_NOT_SUPPORTED = 1; /*package*/ static final int STATE_DISABLED_UNAVAILABLE = 3; /*package*/ static final int STATE_ENABLED_UNAVAILABLE = 4; /*package*/ static final int STATE_ENABLED_AVAILABLE = 5; /*package*/ static final int STATE_DISABLED_AVAILABLE = 6; private int mState = STATE_UNINITIALIZED; private boolean mFeatureEnabled = false; Loading Loading @@ -147,9 +147,9 @@ public class SpatializerHelper { .setSampleRate(48000) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build(); // device array to store the routing for the default attributes and format, size 1 because // media is never expected to be duplicated private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1]; // device array to store the routing for the default attributes and format, initialized to // an empty list as routing hasn't been established yet private static ArrayList<AudioDeviceAttributes> sRoutingDevices = new ArrayList<>(0); //--------------------------------------------------------------- // audio device compatibility / enabled Loading Loading @@ -184,11 +184,6 @@ public class SpatializerHelper { SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledDefault; } synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) { mBinauralSupported = hasBinaural; mTransauralSupported = hasTransaural; } synchronized void init(boolean effectExpected, @Nullable String settings) { loglogi("init effectExpected=" + effectExpected); if (!effectExpected) { Loading Loading @@ -322,8 +317,7 @@ public class SpatializerHelper { return; } mState = STATE_DISABLED_UNAVAILABLE; mASA.getDevicesForAttributes( DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES); sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES); // note at this point mSpat is still not instantiated } Loading Loading @@ -365,34 +359,35 @@ public class SpatializerHelper { case STATE_DISABLED_AVAILABLE: break; } mASA.getDevicesForAttributes( DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES); sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES); // check validity of routing information if (ROUTING_DEVICES[0] == null) { logloge("onRoutingUpdated: device is null, no Spatial Audio"); if (sRoutingDevices.isEmpty()) { logloge("onRoutingUpdated: no device, no Spatial Audio"); setDispatchAvailableState(false); // not changing the spatializer level as this is likely a transient state return; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); // is media routed to a new device? if (isWireless(ROUTING_DEVICES[0].getType())) { addWirelessDeviceIfNew(ROUTING_DEVICES[0]); if (isWireless(currentDevice.getType())) { addWirelessDeviceIfNew(currentDevice); } // find if media device enabled / available final Pair<Boolean, Boolean> enabledAvailable = evaluateState(ROUTING_DEVICES[0]); final Pair<Boolean, Boolean> enabledAvailable = evaluateState(currentDevice); boolean able = false; if (enabledAvailable.second) { // available for Spatial audio, check w/ effect able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES); able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, sRoutingDevices); loglogi("onRoutingUpdated: can spatialize media 5.1:" + able + " on device:" + ROUTING_DEVICES[0]); + " on device:" + currentDevice); setDispatchAvailableState(able); } else { loglogi("onRoutingUpdated: device:" + ROUTING_DEVICES[0] loglogi("onRoutingUpdated: device:" + currentDevice + " not available for Spatial Audio"); setDispatchAvailableState(false); } Loading @@ -400,10 +395,10 @@ public class SpatializerHelper { boolean enabled = able && enabledAvailable.first; if (enabled) { loglogi("Enabling Spatial Audio since enabled for media device:" + ROUTING_DEVICES[0]); + currentDevice); } else { loglogi("Disabling Spatial Audio since disabled for media device:" + ROUTING_DEVICES[0]); + currentDevice); } if (mSpat != null) { byte level = enabled ? (byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL Loading Loading @@ -736,9 +731,13 @@ public class SpatializerHelper { } private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes, @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) { if (isDeviceCompatibleWithSpatializationModes(devices[0])) { return AudioSystem.canBeSpatialized(attributes, format, devices); @NonNull AudioFormat format, @NonNull ArrayList<AudioDeviceAttributes> devices) { if (devices.isEmpty()) { return false; } if (isDeviceCompatibleWithSpatializationModes(devices.get(0))) { AudioDeviceAttributes[] devArray = new AudioDeviceAttributes[devices.size()]; return AudioSystem.canBeSpatialized(attributes, format, devices.toArray(devArray)); } return false; } Loading Loading @@ -1014,10 +1013,13 @@ public class SpatializerHelper { logd("canBeSpatialized false due to usage:" + attributes.getUsage()); return false; } AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1]; // going through adapter to take advantage of routing cache mASA.getDevicesForAttributes( attributes, false /* forVolume */).toArray(devices); final ArrayList<AudioDeviceAttributes> devices = getRoutingDevices(attributes); if (devices.isEmpty()) { logloge("canBeSpatialized got no device for " + attributes); return false; } final boolean able = canBeSpatializedOnDevice(attributes, format, devices); logd("canBeSpatialized usage:" + attributes.getUsage() + " format:" + format.toLogFriendlyString() + " returning " + able); Loading Loading @@ -1148,8 +1150,13 @@ public class SpatializerHelper { logDeviceState(deviceState, "setHeadTrackerEnabled"); // check current routing to see if it affects the headtracking mode if (ROUTING_DEVICES[0] != null && ROUTING_DEVICES[0].getType() == ada.getType() && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) { if (sRoutingDevices.isEmpty()) { logloge("setHeadTrackerEnabled: no device, bailing"); return; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); if (currentDevice.getType() == ada.getType() && currentDevice.getAddress().equals(ada.getAddress())) { setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled : Spatializer.HEAD_TRACKING_MODE_DISABLED); if (enabled && !mHeadTrackerAvailable) { Loading Loading @@ -1706,10 +1713,11 @@ public class SpatializerHelper { private int getHeadSensorHandleUpdateTracker() { int headHandle = -1; final AudioDeviceAttributes currentDevice = ROUTING_DEVICES[0]; if (currentDevice == null) { if (sRoutingDevices.isEmpty()) { logloge("getHeadSensorHandleUpdateTracker: no device, no head tracker"); return headHandle; } final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0); UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice); // We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion // with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR Loading Loading @@ -1743,6 +1751,23 @@ public class SpatializerHelper { return screenHandle; } /** * Returns routing for the given attributes * @param aa AudioAttributes whose routing is being queried * @return a non-null never-empty list of devices. If the routing query failed, the list * will contain null. */ private @NonNull ArrayList<AudioDeviceAttributes> getRoutingDevices(AudioAttributes aa) { final ArrayList<AudioDeviceAttributes> devices = mASA.getDevicesForAttributes( aa, false /* forVolume */); for (AudioDeviceAttributes ada : devices) { if (ada == null) { // invalid entry, reject this routing query by returning an empty list return new ArrayList<>(0); } } return devices; } private static void loglogi(String msg) { AudioService.sSpatialLogger.loglogi(msg, TAG); Loading @@ -1759,4 +1784,13 @@ public class SpatializerHelper { /*package*/ void clearSADevices() { mSADevices.clear(); } /*package*/ synchronized void forceStateForTest(int state) { mState = state; } /*package*/ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) { mBinauralSupported = hasBinaural; mTransauralSupported = hasTransaural; } }
services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java +60 −2 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.server.audio; import com.android.server.audio.SpatializerHelper.SADeviceState; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; import android.util.Log; Loading @@ -36,6 +41,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Spy; import java.util.ArrayList; import java.util.List; @MediumTest Loading @@ -49,16 +55,35 @@ public class SpatializerHelperTest { @Mock private AudioService mMockAudioService; @Spy private AudioSystemAdapter mSpyAudioSystem; @Mock private AudioSystemAdapter mMockAudioSystem; @Before public void setUp() throws Exception { mMockAudioService = mock(AudioService.class); mSpyAudioSystem = spy(new NoOpAudioSystemAdapter()); } mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem, /** * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy * AudioSystemAdapter * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use * the mock adapter, mMockAudioSystem. */ private void setUpSpatHelper(boolean useSpyAudioSystem) { final AudioSystemAdapter asAdapter; if (useSpyAudioSystem) { mSpyAudioSystem = spy(new NoOpAudioSystemAdapter()); asAdapter = mSpyAudioSystem; mMockAudioSystem = null; } else { mSpyAudioSystem = null; mMockAudioSystem = mock(NoOpAudioSystemAdapter.class); asAdapter = mMockAudioSystem; } mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter, true /*binauralEnabledDefault*/, true /*transauralEnabledDefault*/, false /*headTrackingEnabledDefault*/); } /** Loading @@ -68,6 +93,7 @@ public class SpatializerHelperTest { */ @Test public void testSADeviceStateNullAddressCtor() throws Exception { setUpSpatHelper(true /*useSpyAudioSystem*/); try { SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null); devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null); Loading @@ -78,6 +104,7 @@ public class SpatializerHelperTest { @Test public void testSADeviceStateStringSerialization() throws Exception { Log.i(TAG, "starting testSADeviceStateStringSerialization"); setUpSpatHelper(true /*useSpyAudioSystem*/); final SADeviceState devState = new SADeviceState( AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla"); devState.mHasHeadTracker = false; Loading @@ -93,6 +120,7 @@ public class SpatializerHelperTest { @Test public void testSADeviceSettings() throws Exception { Log.i(TAG, "starting testSADeviceSettings"); setUpSpatHelper(true /*useSpyAudioSystem*/); final AudioDeviceAttributes dev1 = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""); final AudioDeviceAttributes dev2 = Loading Loading @@ -143,4 +171,34 @@ public class SpatializerHelperTest { Log.i(TAG, "device settingsRestored: " + settingsRestored); Assert.assertEquals(settings, settingsRestored); } /** * Test that null devices for routing do not break canBeSpatialized * @throws Exception */ @Test public void testNoRoutingCanBeSpatialized() throws Exception { Log.i(TAG, "Starting testNoRoutingCanBeSpatialized"); setUpSpatHelper(false /*useSpyAudioSystem*/); mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE); final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0); final ArrayList<AudioDeviceAttributes> listWithNull = new ArrayList<>(1); listWithNull.add(null); final AudioAttributes media = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build(); final AudioFormat spatialFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build(); when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean())) .thenReturn(emptyList); Assert.assertFalse("can be spatialized on empty routing", mSpatHelper.canBeSpatialized(media, spatialFormat)); when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean())) .thenReturn(listWithNull); Assert.assertFalse("can be spatialized on null routing", mSpatHelper.canBeSpatialized(media, spatialFormat)); } }