title: android AcousticEchoCanceler doesn't seem to work on most devices
body: <p>I am building an application which requires the mic to cancel any sound coming from the speaker. It seems that this issue is almost a conspiracy on-line as others with the exact same problem were never responded to for an extended duration. </p>
  
  <p>Android's native hardware accelerated AcousticEchoCanceler does not seem to work on most devices. Tests where made on many devices and the ones that seemed to work Include Nexus 5, and Moto X while almost all Samsung devices tested could not remove background sound.Note: All phones tested return true for <code>AcousticEchoCanceler.isAvailable()</code></p>
  
  <p>However, there must be a solution since applications such as Skype or WhatsApp seem to cancel sounds outside their app context, i.e. a call is on speaker and the Microphone cancels any feedback received.</p>
  
  <p>This simplified recording app records sound to a file and plays it later when play is clicked. </p>
  
  <p>MainActivity.java</p>
  
  <pre><code>public class MainActivity extends Activity {
  
  Button startRec, stopRec, playBack;
  int minBufferSizeIn;
  AudioRecord audioRecord;
  short[] audioData;
  Boolean recording;
  int sampleRateInHz = 48000;
  private String TAG = "TAG";
  
  /**
   * Called when the activity is first created.
   */
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      startRec = (Button) findViewById(R.id.startrec);
      stopRec = (Button) findViewById(R.id.stoprec);
      playBack = (Button) findViewById(R.id.playback);
  
      startRec.setOnClickListener(startRecOnClickListener);
      stopRec.setOnClickListener(stopRecOnClickListener);
      playBack.setOnClickListener(playBackOnClickListener);
      playBack.setEnabled(false);
      startRec.setEnabled(true);
      stopRec.setEnabled(false);
  
      minBufferSizeIn = AudioRecord.getMinBufferSize(sampleRateInHz,
              AudioFormat.CHANNEL_IN_MONO,
              AudioFormat.ENCODING_PCM_16BIT);
  
      audioData = new short[minBufferSizeIn];
  
      audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
              sampleRateInHz,
              AudioFormat.CHANNEL_IN_MONO,
              AudioFormat.ENCODING_PCM_16BIT,
              minBufferSizeIn);
  
  }
  
  OnClickListener startRecOnClickListener
          = new OnClickListener() {
  
      @Override
      public void onClick(View arg0) {
          playBack.setEnabled(false);
          startRec.setEnabled(false);
          stopRec.setEnabled(true);
          Thread recordThread = new Thread(new Runnable() {
  
              @Override
              public void run() {
                  recording = true;
                  startRecord();
              }
  
          });
  
          recordThread.start();
  
      }
  };
  
  
  OnClickListener stopRecOnClickListener
          = new OnClickListener() {
  
      @Override
      public void onClick(View arg0) {
          playBack.setEnabled(true);
          startRec.setEnabled(false);
          stopRec.setEnabled(false);
          recording = false;
      }
  };
  
  
  
  OnClickListener playBackOnClickListener
          = new OnClickListener() {
  
      @Override
      public void onClick(View v) {
          playBack.setEnabled(false);
          startRec.setEnabled(true);
          stopRec.setEnabled(false);
          playRecord();
      }
  
  };
  
  
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void startRecord() {
      File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
  
      try {
          FileOutputStream outputStream = new FileOutputStream(file);
          BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
          DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
  
          NoiseSuppressor ns;
          AcousticEchoCanceler aec;
  
          if (NoiseSuppressor.isAvailable()) {
              ns = NoiseSuppressor.create(audioRecord.getAudioSessionId());
              if (ns != null) {
                  ns.setEnabled(true);
              } else {
                  Log.e(TAG, "AudioInput: NoiseSuppressor is null and not enabled");
              }
          }
  
          if (AcousticEchoCanceler.isAvailable()) {
              aec = AcousticEchoCanceler.create(audioRecord.getAudioSessionId());
              if (aec != null) {
                  aec.setEnabled(true);
              } else {
                  Log.e(TAG, "AudioInput: AcousticEchoCanceler is null and not enabled");
              }
          }
          audioRecord.startRecording();
  
          while (recording) {
              int numberOfShort = audioRecord.read(audioData, 0, minBufferSizeIn);
              for (int i = 0; i &lt; numberOfShort; i++) {
                  dataOutputStream.writeShort(audioData[i]);
              }
          }
  
          audioRecord.stop();
          dataOutputStream.close();
  
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
  
  void playRecord() {
      File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
  
      int shortSizeInBytes = Short.SIZE / Byte.SIZE;
  
      int bufferSizeInBytes = (int) (file.length() / shortSizeInBytes);
      short[] audioData = new short[bufferSizeInBytes];
  
      try {
          FileInputStream inputStream = new FileInputStream(file);
          BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
          DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
  
          int i = 0;
          while (dataInputStream.available() &gt; 0) {
              audioData[i] = dataInputStream.readShort();
              i++;
          }
  
          dataInputStream.close();
  
          AudioTrack audioTrack = new AudioTrack(
                  AudioManager.STREAM_MUSIC, sampleRateInHz,
                  AudioFormat.CHANNEL_OUT_MONO,
                  AudioFormat.ENCODING_PCM_16BIT,
                  bufferSizeInBytes,
                  AudioTrack.MODE_STREAM);
          while(audioTrack.getState() != AudioTrack.STATE_INITIALIZED){
  
          }
          audioTrack.play();
          audioTrack.write(audioData, 0, bufferSizeInBytes);
  
  
      } catch (FileNotFoundException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }
  
  }
  
  }
  </code></pre>
  
  <p>activity_main.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" &gt;
  
  &lt;TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/hello_world" /&gt;
  &lt;Button
      android:id="@+id/startrec"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Start Recording Test" /&gt;
  &lt;Button
      android:id="@+id/stoprec"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stop Recording" /&gt;
  &lt;Button
      android:id="@+id/playback"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Play Back" /&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>AndroidManfist.xml permissions</p>
  
  <pre><code>    &lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/&gt;
      &lt;uses-permission android:name="android.permission.RECORD_AUDIO"/&gt;
      &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&gt;
  </code></pre>
  
  <p>To Verify if the device works simply play something in the background and  then click <code>Start Recording</code> record a small sector and then click <code>Stop Recording</code> at this point click <code>Play Back</code> and check if you hear the background sound. If you can hear the background sound then AEC is not working. 
  But why is this inconsistency occurring, or how do I achieve echo cancellation (I am already using WebRTC within my app for noise cancellation within my apps context) </p>
  
  <p>Any help would be appreciated !</p>