• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static org.robolectric.util.reflector.Reflector.reflector;
4 
5 import android.media.audiofx.Visualizer;
6 import android.media.audiofx.Visualizer.MeasurementPeakRms;
7 import android.media.audiofx.Visualizer.OnDataCaptureListener;
8 import java.util.concurrent.atomic.AtomicReference;
9 import org.robolectric.annotation.Implementation;
10 import org.robolectric.annotation.Implements;
11 import org.robolectric.annotation.RealObject;
12 import org.robolectric.util.reflector.Accessor;
13 import org.robolectric.util.reflector.ForType;
14 
15 /** Shadow for the {@link Visualizer} class. */
16 @Implements(value = Visualizer.class)
17 public class ShadowVisualizer {
18 
19   @RealObject private Visualizer realObject;
20 
21   private final AtomicReference<VisualizerSource> source =
22       new AtomicReference<>(new VisualizerSource() {});
23 
24   private boolean enabled = false;
25   private OnDataCaptureListener captureListener = null;
26   private boolean captureWaveform;
27   private boolean captureFft;
28   private int captureSize;
29   private int errorCode;
30 
setSource(VisualizerSource source)31   public void setSource(VisualizerSource source) {
32     this.source.set(source);
33   }
34 
35   @Implementation
setDataCaptureListener( OnDataCaptureListener listener, int rate, boolean waveform, boolean fft)36   protected int setDataCaptureListener(
37       OnDataCaptureListener listener, int rate, boolean waveform, boolean fft) {
38     if (errorCode != Visualizer.SUCCESS) {
39       return errorCode;
40     }
41     captureListener = listener;
42     captureWaveform = waveform;
43     captureFft = fft;
44     return Visualizer.SUCCESS;
45   }
46 
47   @Implementation
native_getSamplingRate()48   protected int native_getSamplingRate() {
49     return source.get().getSamplingRate();
50   }
51 
52   @Implementation
native_getWaveForm(byte[] waveform)53   protected int native_getWaveForm(byte[] waveform) {
54     return source.get().getWaveForm(waveform);
55   }
56 
57   @Implementation
native_getFft(byte[] fft)58   protected int native_getFft(byte[] fft) {
59     return source.get().getFft(fft);
60   }
61 
62   @Implementation
native_getEnabled()63   protected boolean native_getEnabled() {
64     return enabled;
65   }
66 
67   @Implementation
native_setCaptureSize(int size)68   protected int native_setCaptureSize(int size) {
69     if (errorCode != Visualizer.SUCCESS) {
70       return errorCode;
71     }
72     captureSize = size;
73     return Visualizer.SUCCESS;
74   }
75 
76   @Implementation
native_getCaptureSize()77   protected int native_getCaptureSize() {
78     return captureSize;
79   }
80 
81   @Implementation
native_setEnabled(boolean enabled)82   protected int native_setEnabled(boolean enabled) {
83     if (errorCode != Visualizer.SUCCESS) {
84       return errorCode;
85     }
86     this.enabled = enabled;
87     return Visualizer.SUCCESS;
88   }
89 
90   @Implementation
native_getPeakRms(MeasurementPeakRms measurement)91   protected int native_getPeakRms(MeasurementPeakRms measurement) {
92     return source.get().getPeakRms(measurement);
93   }
94 
95   @Implementation
native_release()96   protected void native_release() {
97     source.get().release();
98   }
99 
100   /**
101    * Trigger calls to the existing {@link OnDataCaptureListener}.
102    *
103    * <p>This is a no-op if the listener has not been set.
104    */
triggerDataCapture()105   public void triggerDataCapture() {
106     if (captureListener == null) {
107       return;
108     }
109     if (captureWaveform) {
110       byte[] waveform = new byte[captureSize];
111       realObject.getWaveForm(waveform);
112       captureListener.onWaveFormDataCapture(realObject, waveform, realObject.getSamplingRate());
113     }
114     if (captureFft) {
115       byte[] fft = new byte[captureSize];
116       realObject.getFft(fft);
117       captureListener.onFftDataCapture(realObject, fft, realObject.getSamplingRate());
118     }
119   }
120 
121   /**
122    * Updates the state of the {@link Visualizer} itself.
123    *
124    * <p>This can be used e.g. to put the Visualizer in an unexpected state and cause an exception
125    * the next time the Visualizer is used.
126    */
setState(int newState)127   public void setState(int newState) {
128     reflector(ReflectorVisualizer.class, realObject).setState(newState);
129   }
130 
131   /**
132    * Sets the error code to override setter methods in this class.
133    *
134    * <p>When the error code is set to anything other than {@link Visualizer.SUCCESS} setters in the
135    * Visualizer will early-out and return that error code.
136    */
setErrorCode(int errorCode)137   public void setErrorCode(int errorCode) {
138     this.errorCode = errorCode;
139   }
140 
141   /**
142    * Provides underlying data for the {@link ShadowVisualizer}. The default implementations are
143    * there only to help tests to run when they don't need to verify specific behaviour, otherwise
144    * tests should probably override these and provide some specific implementation that allows them
145    * to verify the functionality needed.
146    */
147   public interface VisualizerSource {
148 
getSamplingRate()149     default int getSamplingRate() {
150       return 0;
151     }
152 
getWaveForm(byte[] waveform)153     default int getWaveForm(byte[] waveform) {
154       return Visualizer.SUCCESS;
155     }
156 
getFft(byte[] fft)157     default int getFft(byte[] fft) {
158       return Visualizer.SUCCESS;
159     }
160 
getPeakRms(MeasurementPeakRms measurement)161     default int getPeakRms(MeasurementPeakRms measurement) {
162       return Visualizer.SUCCESS;
163     }
164 
release()165     default void release() {}
166   }
167 
168   /** Accessor interface for {@link Visualizer}'s internals. */
169   @ForType(Visualizer.class)
170   private interface ReflectorVisualizer {
171     @Accessor("mState")
setState(int state)172     void setState(int state);
173   }
174 }
175