/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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 android.media.cts;

import java.util.ArrayList;

import android.cts.util.CtsAndroidTestCase;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.AudioTrack.OnPlaybackPositionUpdateListener;
import android.media.cts.AudioHelper;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.android.cts.util.ReportLog;
import com.android.cts.util.ResultType;
import com.android.cts.util.ResultUnit;

public class AudioTrack_ListenerTest extends CtsAndroidTestCase {
    private final static String TAG = "AudioTrack_ListenerTest";
    private final static int TEST_SR = 11025;
    private final static int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
    private final static int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
    private final static int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
    private final static int TEST_LOOP_FACTOR = 2; // # loops (>= 1) for static tracks
                                                   // simulated for streaming.
    private final static int TEST_BUFFER_FACTOR = 25;
    private boolean mIsHandleMessageCalled;
    private int mMarkerPeriodInFrames;
    private int mMarkerPosition;
    private int mFrameCount;
    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            mIsHandleMessageCalled = true;
            super.handleMessage(msg);
        }
    };

    public void testAudioTrackCallback() throws Exception {
        doTest("Streaming Local Looper", true /*localTrack*/, false /*customHandler*/,
                30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
    }

    public void testAudioTrackCallbackWithHandler() throws Exception {
        // with 100 periods per second, trigger back-to-back notifications.
        doTest("Streaming Private Handler", false /*localTrack*/, true /*customHandler*/,
                100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
        // verify mHandler is used only for accessing its associated Looper
        assertFalse(mIsHandleMessageCalled);
    }

    public void testStaticAudioTrackCallback() throws Exception {
        doTest("Static", false /*localTrack*/, false /*customHandler*/,
                100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
    }

    public void testStaticAudioTrackCallbackWithHandler() throws Exception {
        doTest("Static Private Handler", false /*localTrack*/, true /*customHandler*/,
                30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
        // verify mHandler is used only for accessing its associated Looper
        assertFalse(mIsHandleMessageCalled);
    }

    private void doTest(String reportName, boolean localTrack, boolean customHandler,
            int periodsPerSecond, int markerPeriodsPerSecond, final int mode) throws Exception {
        mIsHandleMessageCalled = false;
        final int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
        final int bufferSizeInBytes;
        if (mode == AudioTrack.MODE_STATIC && TEST_LOOP_FACTOR > 1) {
            // use setLoopPoints for static mode
            bufferSizeInBytes = minBuffSize * TEST_BUFFER_FACTOR;
            mFrameCount = bufferSizeInBytes * TEST_LOOP_FACTOR;
        } else {
            bufferSizeInBytes = minBuffSize * TEST_BUFFER_FACTOR * TEST_LOOP_FACTOR;
            mFrameCount = bufferSizeInBytes;
        }

        final AudioTrack track;
        final AudioHelper.MakeSomethingAsynchronouslyAndLoop<AudioTrack> makeSomething;
        if (localTrack) {
            makeSomething = null;
            track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
                    TEST_FORMAT, bufferSizeInBytes, mode);
        } else {
            makeSomething =
                    new AudioHelper.MakeSomethingAsynchronouslyAndLoop<AudioTrack>(
                    new AudioHelper.MakesSomething<AudioTrack>() {
                        @Override
                        public AudioTrack makeSomething() {
                            return new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
                                TEST_FORMAT, bufferSizeInBytes, mode);
                        }
                    }
                );
           // create audiotrack on different thread's looper.
           track = makeSomething.make();
        }
        final MockOnPlaybackPositionUpdateListener listener;
        if (customHandler) {
            listener = new MockOnPlaybackPositionUpdateListener(track, mHandler);
        } else {
            listener = new MockOnPlaybackPositionUpdateListener(track);
        }

        byte[] vai = AudioHelper.createSoundDataInByteArray(
                bufferSizeInBytes, TEST_SR, 1024 /* frequency */, 0 /* sweep */);
        int markerPeriods = Math.max(3, mFrameCount * markerPeriodsPerSecond / TEST_SR);
        mMarkerPeriodInFrames = mFrameCount / markerPeriods;
        markerPeriods = mFrameCount / mMarkerPeriodInFrames; // recalculate due to round-down
        mMarkerPosition = mMarkerPeriodInFrames;

        // check that we can get and set notification marker position
        assertEquals(0, track.getNotificationMarkerPosition());
        assertEquals(AudioTrack.SUCCESS,
                track.setNotificationMarkerPosition(mMarkerPosition));
        assertEquals(mMarkerPosition, track.getNotificationMarkerPosition());

        int updatePeriods = Math.max(3, mFrameCount * periodsPerSecond / TEST_SR);
        final int updatePeriodInFrames = mFrameCount / updatePeriods;
        updatePeriods = mFrameCount / updatePeriodInFrames; // recalculate due to round-down

        // we set the notification period before running for better period positional accuracy.
        // check that we can get and set notification periods
        assertEquals(0, track.getPositionNotificationPeriod());
        assertEquals(AudioTrack.SUCCESS,
                track.setPositionNotificationPeriod(updatePeriodInFrames));
        assertEquals(updatePeriodInFrames, track.getPositionNotificationPeriod());

        if (mode == AudioTrack.MODE_STATIC && TEST_LOOP_FACTOR > 1) {
            track.setLoopPoints(0, vai.length, TEST_LOOP_FACTOR - 1);
        }
        // write data with single blocking write, then play.
        assertEquals(vai.length, track.write(vai, 0 /* offsetInBytes */, vai.length));
        track.play();

        // sleep until track completes playback - it must complete within 1 second
        // of the expected length otherwise the periodic test should fail.
        final int numChannels =  AudioFormat.channelCountFromOutChannelMask(TEST_CONF);
        final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT);
        final int bytesPerFrame = numChannels * bytesPerSample;
        final int trackLengthMs = (int)((double)mFrameCount * 1000 / TEST_SR / bytesPerFrame);
        Thread.sleep(trackLengthMs + 1000);

        // stop listening - we should be done.
        listener.stop();

        // Beware: stop() resets the playback head position for both static and streaming
        // audio tracks, so stop() cannot be called while we're still logging playback
        // head positions. We could recycle the track after stop(), which isn't done here.
        track.stop();

        // clean up
        if (makeSomething != null) {
            makeSomething.join();
        }
        listener.release();
        track.release();

        // collect statistics
        final ArrayList<Integer> markerList = listener.getMarkerList();
        final ArrayList<Integer> periodicList = listener.getPeriodicList();
        // verify count of markers and periodic notifications.
        assertEquals(markerPeriods, markerList.size());
        assertEquals(updatePeriods, periodicList.size());
        // verify actual playback head positions returned.
        // the max diff should really be around 24 ms,
        // but system load and stability will affect this test;
        // we use 80ms limit here for failure.
        final int tolerance80MsInFrames = TEST_SR * 80 / 1000;

        AudioHelper.Statistics markerStat = new AudioHelper.Statistics();
        for (int i = 0; i < markerPeriods; ++i) {
            final int expected = mMarkerPeriodInFrames * (i + 1);
            final int actual = markerList.get(i);
            // Log.d(TAG, "Marker: expected(" + expected + ")  actual(" + actual
            //        + ")  diff(" + (actual - expected) + ")");
            assertEquals(expected, actual, tolerance80MsInFrames);
            markerStat.add((double)(actual - expected) * 1000 / TEST_SR);
        }

        AudioHelper.Statistics periodicStat = new AudioHelper.Statistics();
        for (int i = 0; i < updatePeriods; ++i) {
            final int expected = updatePeriodInFrames * (i + 1);
            final int actual = periodicList.get(i);
            // Log.d(TAG, "Update: expected(" + expected + ")  actual(" + actual
            //        + ")  diff(" + (actual - expected) + ")");
            assertEquals(expected, actual, tolerance80MsInFrames);
            periodicStat.add((double)(actual - expected) * 1000 / TEST_SR);
        }

        // report this
        ReportLog log = getReportLog();
        log.printValue(reportName + ": Average Marker diff", markerStat.getAvg(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
                ResultType.LOWER_BETTER, ResultUnit.MS);
        log.printSummary(reportName + ": Unified abs diff",
                (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
                ResultType.LOWER_BETTER, ResultUnit.MS);
    }

    private class MockOnPlaybackPositionUpdateListener
                                        implements OnPlaybackPositionUpdateListener {
        public MockOnPlaybackPositionUpdateListener(AudioTrack track) {
            mAudioTrack = track;
            track.setPlaybackPositionUpdateListener(this);
        }

        public MockOnPlaybackPositionUpdateListener(AudioTrack track, Handler handler) {
            mAudioTrack = track;
            track.setPlaybackPositionUpdateListener(this, handler);
        }

        public synchronized void onMarkerReached(AudioTrack track) {
            if (mIsTestActive) {
                int position = mAudioTrack.getPlaybackHeadPosition();
                mOnMarkerReachedCalled.add(position);
                mMarkerPosition += mMarkerPeriodInFrames;
                if (mMarkerPosition <= mFrameCount) {
                    assertEquals(AudioTrack.SUCCESS,
                            mAudioTrack.setNotificationMarkerPosition(mMarkerPosition));
                }
            } else {
                fail("onMarkerReached called when not active");
            }
        }

        public synchronized void onPeriodicNotification(AudioTrack track) {
            if (mIsTestActive) {
                mOnPeriodicNotificationCalled.add(mAudioTrack.getPlaybackHeadPosition());
            } else {
                fail("onPeriodicNotification called when not active");
            }
        }

        public synchronized void stop() {
            mIsTestActive = false;
        }

        public ArrayList<Integer> getMarkerList() {
            return mOnMarkerReachedCalled;
        }

        public ArrayList<Integer> getPeriodicList() {
            return mOnPeriodicNotificationCalled;
        }

        public synchronized void release() {
            mAudioTrack.setPlaybackPositionUpdateListener(null);
            mAudioTrack = null;
        }

        private boolean mIsTestActive = true;
        private AudioTrack mAudioTrack;
        private ArrayList<Integer> mOnMarkerReachedCalled = new ArrayList<Integer>();
        private ArrayList<Integer> mOnPeriodicNotificationCalled = new ArrayList<Integer>();
    }
}
