title: Internal app audio capturing in Android Q is not working on some android devices
body: <p>Basically, my app is for screen recording.</p>
  
  <p>Internal app recoding of other apps is introduced in android 10 as per the Android developer blog and android developer site.
  <a href="https://android-developers.googleblog.com/2019/07/capturing-audio-in-android-q.html" rel="nofollow noreferrer">https://android-developers.googleblog.com/2019/07/capturing-audio-in-android-q.html</a>
  <a href="https://developer.android.com/guide/topics/media/playback-capture" rel="nofollow noreferrer">https://developer.android.com/guide/topics/media/playback-capture</a></p>
  
  <p>I am capturing screen and recording screen using media projection API,</p>
  
  <pre><code> public class WavRecorder {
      private String TAG = WavRecorder.class.getSimpleName();
      private static final int RECORDER_BPP = 16;
      private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
      private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
      private static final int RECORDER_SAMPLERATE = 44100;
      private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
      private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
      short[] audioData;
  
      private AudioRecord recorder = null;
      private int bufferSize = 0;
      private Thread recordingThread = null;
      private boolean isRecording = false;
      int[] bufferData;
      int bytesRecorded;
  
      private InternalAudioCallback internalAudioCallback;
      private String output;
  
      public WavRecorder(String path) {
          bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
                  RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING) * 3;
  
          audioData = new short[bufferSize]; // short array that pcm data is put
          // into.
          output = path;
  
      }
  
      private String getFilename() {
          return (output);
      }
  
      private String getTempFilename() {
          String filepath = Environment.getExternalStorageDirectory().getPath();
          File file = new File(filepath, AUDIO_RECORDER_FOLDER);
  
          if (!file.exists()) {
              file.mkdirs();
          }
  
          File tempFile = new File(filepath, AUDIO_RECORDER_TEMP_FILE);
  
          if (tempFile.exists())
              tempFile.delete();
  
          return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
      }
  
      public void startRecording() {
  
          recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                  RECORDER_SAMPLERATE, RECORDER_CHANNELS,
                  RECORDER_AUDIO_ENCODING, bufferSize);
  
          int i = recorder.getState();
          if (i == 1)
              recorder.startRecording();
  
          isRecording = true;
  
          if (internalAudioCallback != null) {
              internalAudioCallback.recordingStarted();
          }
  
          recordingThread = new Thread(new Runnable() {
              @Override
              public void run() {
                  writeAudioDataToFile();
              }
          }, "AudioRecorder Thread");
  
          recordingThread.start();
      }
  
      public void startRecording(MediaProjection mMediaProjection) {
          if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.Q) {
  
              AudioPlaybackCaptureConfiguration config =
                      new AudioPlaybackCaptureConfiguration.Builder(mMediaProjection)
                              .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
  //                            .addMatchingUsage(AudioAttributes.USAGE_UNKNOWN)
  //                            .addMatchingUsage(AudioAttributes.USAGE_GAME)
                              .build();
  
              AudioFormat audioFormat = new AudioFormat.Builder()
                      .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                      .setSampleRate(RECORDER_SAMPLERATE)
                      .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
                      .build();
  
  
              recorder = new AudioRecord.Builder()
                      .setAudioPlaybackCaptureConfig(config)
                      //.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
                      .setAudioFormat(audioFormat)
                      .setBufferSizeInBytes(bufferSize)
                      .build();
  
              /*recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                      RECORDER_SAMPLERATE, RECORDER_CHANNELS,
                      RECORDER_AUDIO_ENCODING, bufferSize);*/
  
              int i = recorder.getState();
              if (i == 1)
                  recorder.startRecording();
  
              if (internalAudioCallback != null) {
                  internalAudioCallback.recordingStarted();
              }
  
              isRecording = true;
  
              recordingThread = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      writeAudioDataToFile();
                  }
              }, "AudioRecorder Thread");
  
              recordingThread.start();
          }
      }
  
      private void writeAudioDataToFile() {
          Logger.d(TAG, "Buffer Size PortalAndroidAudioDeviceModule " + bufferSize);
          byte data[] = new byte[bufferSize];
          String filename = getTempFilename();
          FileOutputStream os = null;
  
          try {
              os = new FileOutputStream(filename);
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          }
  
          int read = 0;
          if (null != os) {
              while (isRecording) {
                  read = recorder.read(data, 0, bufferSize);
                  if (read &gt; 0) {
                  }
  
                  if (AudioRecord.ERROR_INVALID_OPERATION != read) {
                      try {
                          os.write(data);
  
                          if (internalAudioCallback != null) {
                              internalAudioCallback.recordingData(data);
                          }
  
                          //Logger.d(TAG, "write data here");
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
  
              try {
                  os.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
  
      public void stopRecording() {
          if (null != recorder) {
              isRecording = false;
  
              int i = recorder.getState();
              if (i == 1)
                  recorder.stop();
              recorder.release();
  
              recorder = null;
              recordingThread = null;
  
              if (internalAudioCallback != null) {
                  internalAudioCallback.recordingEnd();
              }
          }
  
          copyWaveFile(getTempFilename(), getFilename());
          deleteTempFile();
      }
  
      private void deleteTempFile() {
          File file = new File(getTempFilename());
          file.delete();
      }
  
      private void copyWaveFile(String inFilename, String outFilename) {
          FileInputStream in = null;
          FileOutputStream out = null;
          long totalAudioLen = 0;
          long totalDataLen = totalAudioLen + 36;
          long longSampleRate = RECORDER_SAMPLERATE;
          int channels = ((RECORDER_CHANNELS == AudioFormat.CHANNEL_IN_MONO) ? 1
                  : 2);
          long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels / 8;
  
          byte[] data = new byte[bufferSize];
  
          try {
              in = new FileInputStream(inFilename);
              out = new FileOutputStream(outFilename);
              totalAudioLen = in.getChannel().size();
              totalDataLen = totalAudioLen + 36;
  
              WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                      longSampleRate, channels, byteRate);
  
              while (in.read(data) != -1) {
                  out.write(data);
              }
  
              in.close();
              out.close();
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  
      private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                       long totalDataLen, long longSampleRate, int channels, long byteRate)
              throws IOException {
          byte[] header = new byte[44];
  
          header[0] = 'R'; // RIFF/WAVE header
          header[1] = 'I';
          header[2] = 'F';
          header[3] = 'F';
          header[4] = (byte) (totalDataLen &amp; 0xff);
          header[5] = (byte) ((totalDataLen &gt;&gt; 8) &amp; 0xff);
          header[6] = (byte) ((totalDataLen &gt;&gt; 16) &amp; 0xff);
          header[7] = (byte) ((totalDataLen &gt;&gt; 24) &amp; 0xff);
          header[8] = 'W';
          header[9] = 'A';
          header[10] = 'V';
          header[11] = 'E';
          header[12] = 'f'; // 'fmt ' chunk
          header[13] = 'm';
          header[14] = 't';
          header[15] = ' ';
          header[16] = 16; // 4 bytes: size of 'fmt ' chunk
          header[17] = 0;
          header[18] = 0;
          header[19] = 0;
          header[20] = 1; // format = 1
          header[21] = 0;
          header[22] = (byte) channels;
          header[23] = 0;
          header[24] = (byte) (longSampleRate &amp; 0xff);
          header[25] = (byte) ((longSampleRate &gt;&gt; 8) &amp; 0xff);
          header[26] = (byte) ((longSampleRate &gt;&gt; 16) &amp; 0xff);
          header[27] = (byte) ((longSampleRate &gt;&gt; 24) &amp; 0xff);
          header[28] = (byte) (byteRate &amp; 0xff);
          header[29] = (byte) ((byteRate &gt;&gt; 8) &amp; 0xff);
          header[30] = (byte) ((byteRate &gt;&gt; 16) &amp; 0xff);
          header[31] = (byte) ((byteRate &gt;&gt; 24) &amp; 0xff);
          header[32] = (byte) (((RECORDER_CHANNELS == AudioFormat.CHANNEL_IN_MONO) ? 1
                  : 2) * 16 / 8); // block align
          header[33] = 0;
          header[34] = RECORDER_BPP; // bits per sample
          header[35] = 0;
          header[36] = 'd';
          header[37] = 'a';
          header[38] = 't';
          header[39] = 'a';
          header[40] = (byte) (totalAudioLen &amp; 0xff);
          header[41] = (byte) ((totalAudioLen &gt;&gt; 8) &amp; 0xff);
          header[42] = (byte) ((totalAudioLen &gt;&gt; 16) &amp; 0xff);
          header[43] = (byte) ((totalAudioLen &gt;&gt; 24) &amp; 0xff);
  
          out.write(header, 0, 44);
      }
  
      public void setRecordingCallback(InternalAudioCallback internalAudioCallback) {
          this.internalAudioCallback = internalAudioCallback;
      }
  
      public interface InternalAudioCallback {
          void recordingStarted();
  
          void recordingEnd();
  
          void recordingData(byte[] data);
      }
  </code></pre>
  
  <p>Above code is for recording internal app audio from other apps. I have limited android 10 devices.
  I have tested on Google Pixel 3a(Android Q), Redmi K20 Pro(Android Q), One Plus 6(Android Q).
  In Google Pixel 3a it is working fine, It is not working on other 2 devices Redmi K20 Pro and One Plus 6</p>
  
  <p>I have checked the recorded file it records blank/silence audio.</p>