/*
 *
 *  * Copyright 2014 http://Bither.net
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *    http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *
 */

package net.bither.xrandom;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.Handler;
import android.os.HandlerThread;

import net.bither.bitherj.utils.LogUtil;

import java.util.Arrays;

/**
 * Created by songchenwen on 14-9-11.
 */
public class UEntropyMic {

    private static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    private static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    public static final int SAMPPERSEC = 8000;
    private int buffersizebytes;

    private HandlerThread micThread;
    private Handler micHandler;
    private AudioRecord audioRecord;

    private UEntropyCollector collector;

    public UEntropyMic(UEntropyCollector collector) {
        micThread = new HandlerThread("UEntropyMicThread",
                android.os.Process.THREAD_PRIORITY_BACKGROUND);
        micThread.start();
        micHandler = new Handler(micThread.getLooper());

        this.collector = collector;

        micHandler.post(openRunnable);
    }

    public void release() {
        micHandler.removeCallbacksAndMessages(null);
        micHandler.post(closeRunnable);
    }

    private final Runnable openRunnable = new Runnable() {
        @Override
        public void run() {
            buffersizebytes = AudioRecord.getMinBufferSize(SAMPPERSEC, channelConfiguration,
                    audioEncoding);
            audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,
                    SAMPPERSEC, channelConfiguration, audioEncoding, buffersizebytes);
            if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
                audioRecord.startRecording();
                micHandler.post(readRunnable);
            } else {
                release();
                collector.onError(new IllegalStateException("startRecording() called on an " +
                        "uninitialized AudioRecord."), UEntropyCollector.UEntropySource.Mic);
            }
        }
    };

    private final Runnable readRunnable = new Runnable() {
        @Override
        public void run() {
            if (audioRecord != null && audioRecord.getRecordingState() == AudioRecord
                    .RECORDSTATE_RECORDING) {
                byte[] data = new byte[buffersizebytes];
                int outLength = audioRecord.read(data, 0, buffersizebytes);
                collector.onNewData(Arrays.copyOf(data, outLength),
                        UEntropyCollector.UEntropySource.Mic);
            }
            micHandler.post(readRunnable);
        }
    };

    private final Runnable closeRunnable = new Runnable() {
        @Override
        public void run() {
            if (audioRecord != null && audioRecord.getRecordingState() == AudioRecord
                    .RECORDSTATE_RECORDING) {
                audioRecord.stop();
                audioRecord.release();
                audioRecord = null;
                LogUtil.i(UEntropyMic.class.getSimpleName(), "Mic released");
            }
            micHandler.removeCallbacksAndMessages(null);
            micThread.quit();
        }
    };

}

@@ -968,17 +968,17 @@
 nal int 
-c
+C
 hannelCo
@@ -1015,20 +1015,9 @@
 NEL_
-CONFIGURATIO
+I
 N_MO
@@ -1049,17 +1049,17 @@
 nal int 
-a
+A
 udioEnco
@@ -1102,21 +1102,22 @@
 T;%0A    p
-ublic
+rivate
  static 
@@ -1131,25 +1131,79 @@
 nt S
-AMPPERSEC = 8000;
+amplePerSec = 8000;%0A    private static final int MaxBufferSize = 6400;%0A
 %0A   
@@ -1972,31 +1972,33 @@
         
-b
+int minB
 uffer
-s
+S
 ize
-bytes
  = Audio
@@ -2022,28 +2022,30 @@
 erSize(S
-AMPPERSEC, c
+amplePerSec, C
 hannelCo
@@ -2073,25 +2073,25 @@
             
-a
+A
 udioEncoding
@@ -2093,16 +2093,232 @@
 oding);%0A
+            if (minBufferSize %3E MaxBufferSize) %7B%0A                buffersizebytes = minBufferSize;%0A            %7D else %7B%0A                buffersizebytes = (MaxBufferSize / minBufferSize) * minBufferSize;%0A            %7D%0A
         
@@ -2421,20 +2421,22 @@
    S
-AMPPERSEC, c
+amplePerSec, C
 hann
@@ -2452,17 +2452,17 @@
 ration, 
-a
+A
 udioEnco

use a larger mic recorder buffer size to reduce data rate