public void write(ByteBuffer audioData, long presentationTimeUs) {
        int sizeInBytes = audioData.remaining();

        // TODO find a way to determine the audio decoder max output frame size at configuration time
        if(mFrameChunkSize < sizeInBytes) {
            Log.d(TAG, "incoming frame chunk size increased to " + sizeInBytes);
            mFrameChunkSize = sizeInBytes;
            // re-init the audio track to accommodate buffer to new chunk size
            init(mAudioFormat);
        }

        // Special handling of the first written audio buffer after a flush (pause with flush)
        if(mPresentationTimeOffsetUs == PTS_NOT_SET) {
            // Initialize with the PTS of the first audio buffer (which isn't necessarily zero)
            mPresentationTimeOffsetUs = presentationTimeUs;
            mLastPlaybackHeadPositionUs = 0;

            /** Handle playback head reset bug
             *
             * affected: Galaxy S2 API 16
             * not affected: Nexus 4 API 22
             *
             * Sometimes the playback head does not really reset to zero in a pause. During the
             * pause, it correctly returns zero (0), but when playback continues it sometimes
             * continues from the previous playback head position instead of starting from zero.
             * Since this does not always happen, this looks to be a bug in the Android framework.
             *
             * TODO find out if this is a reported bug
             *
             * To work around this issue, we subtract the playback head position time from the PTS
             * offset to adjust the base time by the playback head time. This leads to the
             * {@link #getCurrentPresentationTimeUs} method returning a correct value.
             */
            long playbackHeadPositionUs = getPlaybackheadPositionUs();
            if(playbackHeadPositionUs > 0) {
                mPresentationTimeOffsetUs -= playbackHeadPositionUs;
                Log.d(TAG, "playback head not reset");
            }
        }

        mBufferQueue.put(audioData, presentationTimeUs);
//        Log.d(TAG, "buffer queue size " + mBufferQueue.bufferQueue.size()
//                + " data " + mBufferQueue.mQueuedDataSize
//                + " time " + getQueueBufferTimeUs());
        mAudioThread.notifyOfNewBufferInQueue();
    }
Can be used to set an audio session ID before calling {@link #init(android.media.MediaFormat)}.
MediaPlayer/src/main/java/net/protyposis/android/mediaplayer/AudioPlayback.java