/*
 * Copyright (C) 2011 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.
 */

//#define USE_LOG SLAndroidLogLevel_Verbose

#include "sles_allinclusive.h"

#include <media/stagefright/foundation/ADebug.h>
#include <sys/stat.h>

namespace android {

//--------------------------------------------------------------------------------------------------
GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) :
        mDataLocatorType(kDataLocatorNone),
        mNotifyClient(NULL),
        mNotifyUser(NULL),
        mStateFlags(0),
        mPlaybackParams(*params),
        mDurationMsec(ANDROID_UNKNOWN_TIME),
        mCacheStatus(kStatusEmpty),
        mCacheFill(0),
        mLastNotifiedCacheFill(0),
        mCacheFillNotifThreshold(100),
        mEventFlags(0),
        mMarkerPositionMs(ANDROID_UNKNOWN_TIME),
        mPositionUpdatePeriodMs(1000), // per spec
        mOneShotGeneration(0),
        mDeliveredNewPosMs(ANDROID_UNKNOWN_TIME),
        mObservedPositionMs(ANDROID_UNKNOWN_TIME)
{
    SL_LOGD("GenericPlayer::GenericPlayer()");

    mLooper = new android::ALooper();

    // Post-construction accesses need to be protected by mSettingsLock
    mAndroidAudioLevels.mFinalVolume[0] = 1.0f;
    mAndroidAudioLevels.mFinalVolume[1] = 1.0f;
}


GenericPlayer::~GenericPlayer() {
    SL_LOGV("GenericPlayer::~GenericPlayer()");

    resetDataLocator();
}


void GenericPlayer::init(const notif_cbf_t cbf, void* notifUser) {
    SL_LOGD("GenericPlayer::init()");

    {
        android::Mutex::Autolock autoLock(mNotifyClientLock);
        mNotifyClient = cbf;
        mNotifyUser = notifUser;
    }

    mLooper->registerHandler(this);
    mLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/, PRIORITY_DEFAULT);
}


void GenericPlayer::preDestroy() {
    SL_LOGD("GenericPlayer::preDestroy()");
    {
        android::Mutex::Autolock autoLock(mNotifyClientLock);
        mNotifyClient = NULL;
        mNotifyUser = NULL;
    }

    mLooper->stop();
    mLooper->unregisterHandler(id());
}


void GenericPlayer::setDataSource(const char *uri) {
    SL_LOGV("GenericPlayer::setDataSource(uri=%s)", uri);
    resetDataLocator();

    mDataLocator.uriRef = uri;

    mDataLocatorType = kDataLocatorUri;
}


void GenericPlayer::setDataSource(int fd, int64_t offset, int64_t length, bool closeAfterUse) {
    SL_LOGV("GenericPlayer::setDataSource(fd=%d, offset=%lld, length=%lld, closeAfterUse=%s)", fd,
            offset, length, closeAfterUse ? "true" : "false");
    resetDataLocator();

    mDataLocator.fdi.fd = fd;

    struct stat sb;
    int ret = fstat(fd, &sb);
    if (ret != 0) {
        SL_LOGE("GenericPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
        return;
    }

    if (offset >= sb.st_size) {
        SL_LOGE("SfPlayer::setDataSource: invalid offset");
        return;
    }
    mDataLocator.fdi.offset = offset;

    if (PLAYER_FD_FIND_FILE_SIZE == length) {
        mDataLocator.fdi.length = sb.st_size;
    } else if (offset + length > sb.st_size) {
        mDataLocator.fdi.length = sb.st_size - offset;
    } else {
        mDataLocator.fdi.length = length;
    }

    mDataLocator.fdi.mCloseAfterUse = closeAfterUse;

    mDataLocatorType = kDataLocatorFd;
}


void GenericPlayer::prepare() {
    SL_LOGD("GenericPlayer::prepare()");
    // do not attempt prepare more than once
    if (!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully))) {
        sp<AMessage> msg = new AMessage(kWhatPrepare, id());
        msg->post();
    }
}


void GenericPlayer::play() {
    SL_LOGD("GenericPlayer::play()");
    sp<AMessage> msg = new AMessage(kWhatPlay, id());
    msg->post();
}


void GenericPlayer::pause() {
    SL_LOGD("GenericPlayer::pause()");
    sp<AMessage> msg = new AMessage(kWhatPause, id());
    msg->post();
}


void GenericPlayer::stop() {
    SL_LOGD("GenericPlayer::stop()");
    (new AMessage(kWhatPause, id()))->post();

    // after a stop, playback should resume from the start.
    seek(0);
}


void GenericPlayer::seek(int64_t timeMsec) {
    SL_LOGV("GenericPlayer::seek %lld", timeMsec);
    if (timeMsec < 0 && timeMsec != ANDROID_UNKNOWN_TIME) {
        SL_LOGE("GenericPlayer::seek error, can't seek to negative time %lldms", timeMsec);
        return;
    }
    sp<AMessage> msg = new AMessage(kWhatSeek, id());
    msg->setInt64(WHATPARAM_SEEK_SEEKTIME_MS, timeMsec);
    msg->post();
}


void GenericPlayer::loop(bool loop) {
    SL_LOGV("GenericPlayer::loop %s", loop ? "true" : "false");
    sp<AMessage> msg = new AMessage(kWhatLoop, id());
    msg->setInt32(WHATPARAM_LOOP_LOOPING, (int32_t)loop);
    msg->post();
}


void GenericPlayer::setBufferingUpdateThreshold(int16_t thresholdPercent) {
    SL_LOGV("GenericPlayer::setBufferingUpdateThreshold %d", thresholdPercent);
    sp<AMessage> msg = new AMessage(kWhatBuffUpdateThres, id());
    msg->setInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, (int32_t)thresholdPercent);
    msg->post();
}


//--------------------------------------------------
void GenericPlayer::getDurationMsec(int* msec) {
    Mutex::Autolock _l(mSettingsLock);
    *msec = mDurationMsec;
}

//--------------------------------------------------
void GenericPlayer::setVolume(float leftVol, float rightVol)
{
    {
        Mutex::Autolock _l(mSettingsLock);
        mAndroidAudioLevels.mFinalVolume[0] = leftVol;
        mAndroidAudioLevels.mFinalVolume[1] = rightVol;
    }
    // send a message for the volume to be updated by the object which implements the volume
    (new AMessage(kWhatVolumeUpdate, id()))->post();
}


//--------------------------------------------------
void GenericPlayer::attachAuxEffect(int32_t effectId)
{
    SL_LOGV("GenericPlayer::attachAuxEffect(id=%d)", effectId);
    sp<AMessage> msg = new AMessage(kWhatAttachAuxEffect, id());
    msg->setInt32(WHATPARAM_ATTACHAUXEFFECT, effectId);
    msg->post();
}


//--------------------------------------------------
void GenericPlayer::setAuxEffectSendLevel(float level)
{
    SL_LOGV("GenericPlayer::setAuxEffectSendLevel(level=%g)", level);
    sp<AMessage> msg = new AMessage(kWhatSetAuxEffectSendLevel, id());
    msg->setFloat(WHATPARAM_SETAUXEFFECTSENDLEVEL, level);
    msg->post();
}


//--------------------------------------------------
// Call after changing any of the IPlay settings related to SL_PLAYEVENT_*
void GenericPlayer::setPlayEvents(int32_t eventFlags, int32_t markerPositionMs,
        int32_t positionUpdatePeriodMs)
{
    // Normalize ms that are within the valid unsigned range, but not in the int32_t range
    if (markerPositionMs < 0) {
        markerPositionMs = ANDROID_UNKNOWN_TIME;
    }
    if (positionUpdatePeriodMs < 0) {
        positionUpdatePeriodMs = ANDROID_UNKNOWN_TIME;
    }
    // markers are delivered accurately, but new position updates are limited to every 100 ms
    if (positionUpdatePeriodMs < 100) {
        positionUpdatePeriodMs = 100;
    }
    sp<AMessage> msg = new AMessage(kWhatSetPlayEvents, id());
    msg->setInt32(WHATPARAM_SETPLAYEVENTS_FLAGS, eventFlags);
    msg->setInt32(WHATPARAM_SETPLAYEVENTS_MARKER, markerPositionMs);
    msg->setInt32(WHATPARAM_SETPLAYEVENTS_UPDATE, positionUpdatePeriodMs);
    msg->post();
}


//--------------------------------------------------
/*
 * post-condition: mDataLocatorType == kDataLocatorNone
 *
 */
void GenericPlayer::resetDataLocator() {
    SL_LOGV("GenericPlayer::resetDataLocator()");
    if (mDataLocatorType == kDataLocatorFd && mDataLocator.fdi.mCloseAfterUse) {
        (void) ::close(mDataLocator.fdi.fd);
        // would be redundant, as we're about to invalidate the union mDataLocator
        //mDataLocator.fdi.fd = -1;
        //mDataLocator.fdi.mCloseAfterUse = false;
    }
    mDataLocatorType = kDataLocatorNone;
}


void GenericPlayer::notify(const char* event, int data, bool async) {
    SL_LOGV("GenericPlayer::notify(event=%s, data=%d, async=%s)", event, data,
            async ? "true" : "false");
    sp<AMessage> msg = new AMessage(kWhatNotif, id());
    msg->setInt32(event, (int32_t)data);
    if (async) {
        msg->post();
    } else {
        this->onNotify(msg);
    }
}


void GenericPlayer::notify(const char* event, int data1, int data2, bool async) {
    SL_LOGV("GenericPlayer::notify(event=%s, data1=%d, data2=%d, async=%s)", event, data1, data2,
            async ? "true" : "false");
    sp<AMessage> msg = new AMessage(kWhatNotif, id());
    msg->setRect(event, 0, 0, (int32_t)data1, (int32_t)data2);
    if (async) {
        msg->post();
    } else {
        this->onNotify(msg);
    }
}


//--------------------------------------------------
// AHandler implementation
void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onMessageReceived()");
    switch (msg->what()) {
        case kWhatPrepare:
            SL_LOGV("kWhatPrepare");
            onPrepare();
            break;

        case kWhatNotif:
            SL_LOGV("kWhatNotif");
            onNotify(msg);
            break;

        case kWhatPlay:
            SL_LOGV("kWhatPlay");
            onPlay();
            break;

        case kWhatPause:
            SL_LOGV("kWhatPause");
            onPause();
            break;

        case kWhatSeek:
            SL_LOGV("kWhatSeek");
            onSeek(msg);
            break;

        case kWhatLoop:
            SL_LOGV("kWhatLoop");
            onLoop(msg);
            break;

        case kWhatVolumeUpdate:
            SL_LOGV("kWhatVolumeUpdate");
            onVolumeUpdate();
            break;

        case kWhatSeekComplete:
            SL_LOGV("kWhatSeekComplete");
            onSeekComplete();
            break;

        case kWhatBufferingUpdate:
            SL_LOGV("kWhatBufferingUpdate");
            onBufferingUpdate(msg);
            break;

        case kWhatBuffUpdateThres:
            SL_LOGV("kWhatBuffUpdateThres");
            onSetBufferingUpdateThreshold(msg);
            break;

        case kWhatAttachAuxEffect:
            SL_LOGV("kWhatAttachAuxEffect");
            onAttachAuxEffect(msg);
            break;

        case kWhatSetAuxEffectSendLevel:
            SL_LOGV("kWhatSetAuxEffectSendLevel");
            onSetAuxEffectSendLevel(msg);
            break;

        case kWhatSetPlayEvents:
            SL_LOGV("kWhatSetPlayEvents");
            onSetPlayEvents(msg);
            break;

        case kWhatOneShot:
            SL_LOGV("kWhatOneShot");
            onOneShot(msg);
            break;

        default:
            SL_LOGE("GenericPlayer::onMessageReceived unknown message %d", msg->what());
            TRESPASS();
    }
}


//--------------------------------------------------
// Event handlers
//  it is strictly verboten to call those methods outside of the event loop

void GenericPlayer::onPrepare() {
    SL_LOGV("GenericPlayer::onPrepare()");
    // Subclass is responsible for indicating whether prepare was successful or unsuccessful
    // by updating mStateFlags accordingly.  It must set exactly one of these two flags.
    assert(!(mStateFlags & kFlagPrepared) != !(mStateFlags & kFlagPreparedUnsuccessfully));
    notify(PLAYEREVENT_PREPARED, mStateFlags & kFlagPrepared ? PLAYER_SUCCESS : PLAYER_FAILURE,
            true /*async*/);
    SL_LOGD("GenericPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
}


void GenericPlayer::onNotify(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onNotify()");
    notif_cbf_t notifClient;
    void*       notifUser;
    {
        android::Mutex::Autolock autoLock(mNotifyClientLock);
        if (NULL == mNotifyClient) {
            return;
        } else {
            notifClient = mNotifyClient;
            notifUser   = mNotifyUser;
        }
    }

    int32_t val1, val2;
    if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val1);
        notifClient(kEventPrefetchStatusChange, val1, 0, notifUser);
    // There is exactly one notification per message, hence "else if" instead of "if"
    } else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val1);
        notifClient(kEventPrefetchFillLevelUpdate, val1, 0, notifUser);
    } else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val1);
        notifClient(kEventEndOfStream, val1, 0, notifUser);
    } else if (msg->findInt32(PLAYEREVENT_PREPARED, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val1);
        notifClient(kEventPrepared, val1, 0, notifUser);
    } else if (msg->findInt32(PLAYEREVENT_CHANNEL_COUNT, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_CHANNEL_COUNT, val1);
        notifClient(kEventChannelCount, val1, 0, notifUser);
    } else if (msg->findRect(PLAYEREVENT_VIDEO_SIZE_UPDATE, &val1, &val2, &val1, &val2)) {
        SL_LOGV("GenericPlayer notifying %s = %d, %d", PLAYEREVENT_VIDEO_SIZE_UPDATE, val1, val2);
        notifClient(kEventHasVideoSize, val1, val2, notifUser);
    } else if (msg->findInt32(PLAYEREVENT_PLAY, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PLAY, val1);
        notifClient(kEventPlay, val1, 0, notifUser);
    } else if (msg->findInt32(PLAYEREVENT_ERRORAFTERPREPARE, &val1)) {
        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_ERRORAFTERPREPARE, val1);
        notifClient(kEventErrorAfterPrepare, val1, 0, notifUser);
    } else {
        SL_LOGV("GenericPlayer notifying unknown");
    }
}


void GenericPlayer::onPlay() {
    SL_LOGD("GenericPlayer::onPlay()");
    if ((mStateFlags & (kFlagPrepared | kFlagPlaying)) == kFlagPrepared) {
        SL_LOGD("starting player");
        mStateFlags |= kFlagPlaying;
        updateOneShot();
    }
}


void GenericPlayer::onPause() {
    SL_LOGD("GenericPlayer::onPause()");
    if (!(~mStateFlags & (kFlagPrepared | kFlagPlaying))) {
        SL_LOGV("pausing player");
        mStateFlags &= ~kFlagPlaying;
        updateOneShot();
    }
}


void GenericPlayer::onSeek(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onSeek");
}


void GenericPlayer::onLoop(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onLoop");
}


void GenericPlayer::onVolumeUpdate() {
    SL_LOGV("GenericPlayer::onVolumeUpdate");
}


void GenericPlayer::onSeekComplete() {
    SL_LOGD("GenericPlayer::onSeekComplete()");
    mStateFlags &= ~kFlagSeeking;
    // avoid spurious or lost events caused by seeking past a marker
    mDeliveredNewPosMs = ANDROID_UNKNOWN_TIME;
    mObservedPositionMs = ANDROID_UNKNOWN_TIME;
    updateOneShot();
}


void GenericPlayer::onBufferingUpdate(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onBufferingUpdate");
}


void GenericPlayer::onSetBufferingUpdateThreshold(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onSetBufferingUpdateThreshold");
    int32_t thresholdPercent = 0;
    if (msg->findInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, &thresholdPercent)) {
        Mutex::Autolock _l(mSettingsLock);
        mCacheFillNotifThreshold = (int16_t)thresholdPercent;
    }
}


void GenericPlayer::onAttachAuxEffect(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onAttachAuxEffect()");
}


void GenericPlayer::onSetAuxEffectSendLevel(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onSetAuxEffectSendLevel()");
}


void GenericPlayer::onSetPlayEvents(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onSetPlayEvents()");
    int32_t eventFlags, markerPositionMs, positionUpdatePeriodMs;
    if (msg->findInt32(WHATPARAM_SETPLAYEVENTS_FLAGS, &eventFlags) &&
            msg->findInt32(WHATPARAM_SETPLAYEVENTS_MARKER, &markerPositionMs) &&
            msg->findInt32(WHATPARAM_SETPLAYEVENTS_UPDATE, &positionUpdatePeriodMs)) {
        mEventFlags = eventFlags;
        mMarkerPositionMs = markerPositionMs;
        mPositionUpdatePeriodMs = positionUpdatePeriodMs;
        updateOneShot();
    }
}


void GenericPlayer::onOneShot(const sp<AMessage> &msg) {
    SL_LOGV("GenericPlayer::onOneShot()");
    int32_t generation;
    if (msg->findInt32(WHATPARAM_ONESHOT_GENERATION, &generation)) {
        if (generation != mOneShotGeneration) {
            SL_LOGV("GenericPlayer::onOneShot() generation %d cancelled; latest is %d",
                    generation, mOneShotGeneration);
            return;
        }
        updateOneShot();
    }
}


//-------------------------------------------------
void GenericPlayer::notifyStatus() {
    SL_LOGV("GenericPlayer::notifyStatus");
    notify(PLAYEREVENT_PREFETCHSTATUSCHANGE, (int32_t)mCacheStatus, true /*async*/);
}


void GenericPlayer::notifyCacheFill() {
    SL_LOGV("GenericPlayer::notifyCacheFill");
    mLastNotifiedCacheFill = mCacheFill;
    notify(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, (int32_t)mLastNotifiedCacheFill, true/*async*/);
}


void GenericPlayer::seekComplete() {
    SL_LOGV("GenericPlayer::seekComplete");
    sp<AMessage> msg = new AMessage(kWhatSeekComplete, id());
    msg->post();
}


void GenericPlayer::bufferingUpdate(int16_t fillLevelPerMille) {
    SL_LOGV("GenericPlayer::bufferingUpdate");
    sp<AMessage> msg = new AMessage(kWhatBufferingUpdate, id());
    msg->setInt32(WHATPARAM_BUFFERING_UPDATE, fillLevelPerMille);
    msg->post();
}


// For the meaning of positionMs, see comment in declaration at android_GenericPlayer.h
void GenericPlayer::updateOneShot(int positionMs)
{
    SL_LOGV("GenericPlayer::updateOneShot");

    // nop until prepared
    if (!(mStateFlags & kFlagPrepared)) {
        return;
    }

    // cancel any pending one-shot(s)
    ++mOneShotGeneration;

    // don't restart one-shot if player is paused or stopped
    if (!(mStateFlags & kFlagPlaying)) {
        return;
    }

    // get current player position in milliseconds
    if (positionMs < 0) {
        positionMs = ANDROID_UNKNOWN_TIME;
    }
    if (positionMs == ANDROID_UNKNOWN_TIME) {
        getPositionMsec(&positionMs);
        // normalize it
        if (positionMs < 0) {
            positionMs = ANDROID_UNKNOWN_TIME;
        }
        if (ANDROID_UNKNOWN_TIME == positionMs) {
            // getPositionMsec is not working for some reason, give up
            //ALOGV("Does anyone really know what time it is?");
            return;
        }
    }

    // if we observe the player position going backwards, even without without a seek, then recover
    if (mObservedPositionMs != ANDROID_UNKNOWN_TIME && positionMs < mObservedPositionMs) {
        mDeliveredNewPosMs = ANDROID_UNKNOWN_TIME;
        mObservedPositionMs = positionMs;
    }

    // delayUs is the expected delay between current position and marker;
    // the default is infinity in case there are no upcoming marker(s)
    int64_t delayUs = -1;

    // is there a marker?
    if ((mEventFlags & SL_PLAYEVENT_HEADATMARKER) && (mMarkerPositionMs != ANDROID_UNKNOWN_TIME)) {
        // check to see if we have observed the position passing through the marker
        if (mObservedPositionMs <= mMarkerPositionMs && mMarkerPositionMs <= positionMs) {
            notify(PLAYEREVENT_PLAY, (int32_t) SL_PLAYEVENT_HEADATMARKER, true /*async*/);
        } else if (positionMs < mMarkerPositionMs) {
            delayUs = (mMarkerPositionMs - positionMs) * 1000LL;
        }
    }

    // are periodic position updates needed?
    if ((mEventFlags & SL_PLAYEVENT_HEADATNEWPOS) &&
            (mPositionUpdatePeriodMs != ANDROID_UNKNOWN_TIME)) {
        // check to see if we have observed the position passing through a virtual marker, where the
        // virtual marker is at the previously delivered new position plus position update period
        int32_t virtualMarkerMs;
        if (mDeliveredNewPosMs != ANDROID_UNKNOWN_TIME) {
            virtualMarkerMs = mDeliveredNewPosMs + mPositionUpdatePeriodMs;
        } else if (mObservedPositionMs != ANDROID_UNKNOWN_TIME) {
            virtualMarkerMs = mObservedPositionMs + mPositionUpdatePeriodMs;
            // pretend there has been an update in the past
            mDeliveredNewPosMs = mObservedPositionMs;
        } else {
            virtualMarkerMs = positionMs + mPositionUpdatePeriodMs;
            // pretend there has been an update in the past
            mDeliveredNewPosMs = positionMs;
        }
        // nextVirtualMarkerMs will be set to the position of the next upcoming virtual marker
        int32_t nextVirtualMarkerMs;
        if (mObservedPositionMs <= virtualMarkerMs && virtualMarkerMs <= positionMs) {
            // we did pass through the virtual marker, now compute the next virtual marker
            mDeliveredNewPosMs = virtualMarkerMs;
            nextVirtualMarkerMs = virtualMarkerMs + mPositionUpdatePeriodMs;
            // re-synchronize if we missed an update
            if (nextVirtualMarkerMs <= positionMs) {
                SL_LOGW("Missed SL_PLAYEVENT_HEADATNEWPOS for position %d; current position %d",
                        nextVirtualMarkerMs, positionMs);
                // try to catch up by setting next goal to current position plus update period
                mDeliveredNewPosMs = positionMs;
                nextVirtualMarkerMs = positionMs + mPositionUpdatePeriodMs;
            }
            notify(PLAYEREVENT_PLAY, (int32_t) SL_PLAYEVENT_HEADATNEWPOS, true /*async*/);
        } else {
            // we did not pass through the virtual marker yet, so use same marker again
            nextVirtualMarkerMs = virtualMarkerMs;
        }
        // note that if arithmetic overflow occurred, nextVirtualMarkerMs will be negative
        if (positionMs < nextVirtualMarkerMs) {
            int64_t trialDelayUs;
            trialDelayUs = (nextVirtualMarkerMs - positionMs) * 1000LL;
            if (trialDelayUs > 0 && (delayUs == -1 || trialDelayUs < delayUs)) {
                delayUs = trialDelayUs;
            }
        }
    }

    // we have a new observed position
    mObservedPositionMs = positionMs;

    // post the new one-shot message if needed
    if (advancesPositionInRealTime() && delayUs >= 0) {
        // 20 ms min delay to avoid near busy waiting
        if (delayUs < 20000LL) {
            delayUs = 20000LL;
        }
        // 1 minute max delay avoids indefinite memory leaks caused by cancelled one-shots
        if (delayUs > 60000000LL) {
            delayUs = 60000000LL;
        }
        //SL_LOGI("delayUs = %lld", delayUs);
        sp<AMessage> msg = new AMessage(kWhatOneShot, id());
        msg->setInt32(WHATPARAM_ONESHOT_GENERATION, mOneShotGeneration);
        msg->post(delayUs);
    }

}

} // namespace android
