1 package org.robolectric.shadows; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static org.junit.Assert.assertThrows; 5 import static org.robolectric.Shadows.shadowOf; 6 7 import android.media.audiofx.AudioEffect; 8 import android.media.audiofx.Visualizer; 9 import android.media.audiofx.Visualizer.MeasurementPeakRms; 10 import android.media.audiofx.Visualizer.OnDataCaptureListener; 11 import androidx.test.ext.junit.runners.AndroidJUnit4; 12 import java.util.Arrays; 13 import java.util.concurrent.atomic.AtomicBoolean; 14 import org.junit.Before; 15 import org.junit.Test; 16 import org.junit.runner.RunWith; 17 import org.robolectric.shadows.ShadowVisualizer.VisualizerSource; 18 19 /** Tests for {@link ShadowVisualizer}. */ 20 @RunWith(AndroidJUnit4.class) 21 public class ShadowVisualizerTest { 22 23 private Visualizer visualizer; 24 25 @Before setUp()26 public void setUp() { 27 visualizer = new Visualizer(/* audioSession= */ 0); 28 visualizer.setEnabled(true); 29 } 30 31 @Test getSamplingRate_returnsRateFromSource()32 public void getSamplingRate_returnsRateFromSource() { 33 assertThat(visualizer.getSamplingRate()).isEqualTo(0); 34 35 shadowOf(visualizer) 36 .setSource( 37 new VisualizerSource() { 38 @Override 39 public int getSamplingRate() { 40 return 100; 41 } 42 }); 43 44 assertThat(visualizer.getSamplingRate()).isEqualTo(100); 45 } 46 47 @Test getWaveform_returnsWaveformFromSource()48 public void getWaveform_returnsWaveformFromSource() { 49 byte[] waveformInput = new byte[10]; 50 Arrays.fill(waveformInput, (byte) 5); 51 52 // Default behaviour 53 assertThat(visualizer.getWaveForm(waveformInput)).isEqualTo(Visualizer.SUCCESS); 54 55 shadowOf(visualizer).setSource(createVisualizerSourceReturningValue(42)); 56 57 assertThat(visualizer.getWaveForm(waveformInput)).isEqualTo(42); 58 } 59 60 @Test getFft_returnsFftFromSource()61 public void getFft_returnsFftFromSource() { 62 byte[] fftInput = new byte[10]; 63 Arrays.fill(fftInput, (byte) 5); 64 65 // Default behaviour 66 assertThat(visualizer.getFft(fftInput)).isEqualTo(Visualizer.SUCCESS); 67 68 shadowOf(visualizer).setSource(createVisualizerSourceReturningValue(42)); 69 70 assertThat(visualizer.getFft(fftInput)).isEqualTo(42); 71 } 72 73 @Test getEnabled_isFalseByDefault()74 public void getEnabled_isFalseByDefault() { 75 assertThat(new Visualizer(/* audioSession= */ 0).getEnabled()).isFalse(); 76 } 77 78 @Test setEnabled_changedEnabledState()79 public void setEnabled_changedEnabledState() { 80 int status = visualizer.setEnabled(true); 81 82 assertThat(status).isEqualTo(Visualizer.SUCCESS); 83 assertThat(visualizer.getEnabled()).isTrue(); 84 } 85 86 @Test setCaptureSize_changedCaptureSize()87 public void setCaptureSize_changedCaptureSize() { 88 // The capture size can only be set while the Visualizer is disabled. 89 visualizer.setEnabled(false); 90 91 int status = visualizer.setCaptureSize(2000); 92 93 assertThat(status).isEqualTo(Visualizer.SUCCESS); 94 assertThat(visualizer.getCaptureSize()).isEqualTo(2000); 95 } 96 97 @Test getMeasurementPeakRms_returnsRmsFromSource()98 public void getMeasurementPeakRms_returnsRmsFromSource() { 99 int peak = -500; 100 int rms = -1000; 101 shadowOf(visualizer) 102 .setSource( 103 new VisualizerSource() { 104 @Override 105 public int getPeakRms(MeasurementPeakRms measurement) { 106 measurement.mPeak = peak; 107 measurement.mRms = rms; 108 return AudioEffect.ERROR; 109 } 110 }); 111 MeasurementPeakRms measurement = new MeasurementPeakRms(); 112 113 int result = visualizer.getMeasurementPeakRms(measurement); 114 115 assertThat(result).isEqualTo(AudioEffect.ERROR); 116 assertThat(measurement.mPeak).isEqualTo(peak); 117 assertThat(measurement.mRms).isEqualTo(rms); 118 } 119 120 @Test release_sourceThrowsException_throwsException()121 public void release_sourceThrowsException_throwsException() { 122 shadowOf(visualizer) 123 .setSource( 124 new VisualizerSource() { 125 @Override 126 public void release() { 127 throw new RuntimeException(); 128 } 129 }); 130 131 assertThrows(RuntimeException.class, () -> visualizer.release()); 132 } 133 134 @Test getEnabled_visualizerUninitialized_throwsException()135 public void getEnabled_visualizerUninitialized_throwsException() { 136 shadowOf(visualizer).setState(Visualizer.STATE_UNINITIALIZED); 137 138 assertThrows(IllegalStateException.class, () -> visualizer.getEnabled()); 139 } 140 141 @Test setEnabled_visualizerUninitialized_throwsException()142 public void setEnabled_visualizerUninitialized_throwsException() { 143 shadowOf(visualizer).setState(Visualizer.STATE_UNINITIALIZED); 144 145 assertThrows(IllegalStateException.class, () -> visualizer.setEnabled(false)); 146 } 147 148 @Test setDataCaptureListener_errorCodeSet_returnsErrorCode()149 public void setDataCaptureListener_errorCodeSet_returnsErrorCode() { 150 shadowOf(visualizer).setErrorCode(Visualizer.ERROR); 151 152 assertThat(visualizer.setDataCaptureListener(null, 1024, false, false)) 153 .isEqualTo(Visualizer.ERROR); 154 } 155 156 @Test setEnabled_errorCodeSet_returnsErrorCode()157 public void setEnabled_errorCodeSet_returnsErrorCode() { 158 visualizer.setEnabled(false); 159 shadowOf(visualizer).setErrorCode(Visualizer.ERROR); 160 161 assertThat(visualizer.setEnabled(true)).isEqualTo(Visualizer.ERROR); 162 } 163 164 @Test setCaptureSize_errorCodeSet_returnsErrorCode()165 public void setCaptureSize_errorCodeSet_returnsErrorCode() { 166 // The capture size can only be set while the Visualizer is disabled. 167 visualizer.setEnabled(false); 168 shadowOf(visualizer).setErrorCode(Visualizer.ERROR); 169 170 assertThat(visualizer.setCaptureSize(1024)).isEqualTo(Visualizer.ERROR); 171 } 172 173 @Test triggerDataCapture_waveformAndFftTriggered()174 public void triggerDataCapture_waveformAndFftTriggered() { 175 AtomicBoolean waveformCalled = new AtomicBoolean(false); 176 AtomicBoolean fftCalled = new AtomicBoolean(false); 177 visualizer.setDataCaptureListener( 178 createSimpleDataListener(waveformCalled, fftCalled), 179 /* rate= */ 1, 180 /* waveform= */ true, 181 /* fft= */ true); 182 183 shadowOf(visualizer).triggerDataCapture(); 184 185 assertThat(waveformCalled.get()).isTrue(); 186 assertThat(fftCalled.get()).isTrue(); 187 } 188 189 @Test triggerDataCapture_waveformDisabled_waveFormNotTriggered()190 public void triggerDataCapture_waveformDisabled_waveFormNotTriggered() { 191 AtomicBoolean waveformCalled = new AtomicBoolean(false); 192 AtomicBoolean fftCalled = new AtomicBoolean(false); 193 visualizer.setDataCaptureListener( 194 createSimpleDataListener(waveformCalled, fftCalled), 195 /* rate= */ 1, 196 /* waveform= */ false, 197 /* fft= */ true); 198 199 shadowOf(visualizer).triggerDataCapture(); 200 201 assertThat(waveformCalled.get()).isFalse(); 202 } 203 204 @Test triggerDataCapture_fftDisabled_fftNotTriggered()205 public void triggerDataCapture_fftDisabled_fftNotTriggered() { 206 AtomicBoolean waveformCalled = new AtomicBoolean(false); 207 AtomicBoolean fftCalled = new AtomicBoolean(false); 208 visualizer.setDataCaptureListener( 209 createSimpleDataListener(waveformCalled, fftCalled), 210 /* rate= */ 1, 211 /* waveform= */ true, 212 /* fft= */ false); 213 214 shadowOf(visualizer).triggerDataCapture(); 215 216 assertThat(fftCalled.get()).isFalse(); 217 } 218 createVisualizerSourceReturningValue(int returnValue)219 private static VisualizerSource createVisualizerSourceReturningValue(int returnValue) { 220 return new VisualizerSource() { 221 @Override 222 public int getWaveForm(byte[] waveform) { 223 return returnValue; 224 } 225 226 @Override 227 public int getFft(byte[] fft) { 228 return returnValue; 229 } 230 }; 231 } 232 233 private static OnDataCaptureListener createSimpleDataListener( 234 AtomicBoolean waveformCalled, AtomicBoolean fftCalled) { 235 return new OnDataCaptureListener() { 236 @Override 237 public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) { 238 waveformCalled.set(true); 239 } 240 241 @Override 242 public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { 243 fftCalled.set(true); 244 } 245 }; 246 } 247 } 248