Home | History | Annotate | Download | only in audioflinger
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // <IMPORTANT_WARNING>
     18 // Design rules for threadLoop() are given in the comments at section "Fast mixer thread" of
     19 // StateQueue.h.  In particular, avoid library and system calls except at well-known points.
     20 // The design rules are only for threadLoop(), and don't apply to FastMixerDumpState methods.
     21 // </IMPORTANT_WARNING>
     22 
     23 #define LOG_TAG "FastMixer"
     24 //#define LOG_NDEBUG 0
     25 
     26 #define ATRACE_TAG ATRACE_TAG_AUDIO
     27 
     28 #include "Configuration.h"
     29 #include <time.h>
     30 #include <utils/Debug.h>
     31 #include <utils/Log.h>
     32 #include <utils/Trace.h>
     33 #include <system/audio.h>
     34 #ifdef FAST_THREAD_STATISTICS
     35 #include <cpustats/CentralTendencyStatistics.h>
     36 #ifdef CPU_FREQUENCY_STATISTICS
     37 #include <cpustats/ThreadCpuUsage.h>
     38 #endif
     39 #endif
     40 #include <audio_utils/mono_blend.h>
     41 #include <audio_utils/format.h>
     42 #include <media/AudioMixer.h>
     43 #include "FastMixer.h"
     44 #include "TypedLogger.h"
     45 
     46 namespace android {
     47 
     48 /*static*/ const FastMixerState FastMixer::sInitial;
     49 
     50 FastMixer::FastMixer() : FastThread("cycle_ms", "load_us"),
     51     // mFastTrackNames
     52     // mGenerations
     53     mOutputSink(NULL),
     54     mOutputSinkGen(0),
     55     mMixer(NULL),
     56     mSinkBuffer(NULL),
     57     mSinkBufferSize(0),
     58     mSinkChannelCount(FCC_2),
     59     mMixerBuffer(NULL),
     60     mMixerBufferSize(0),
     61     mMixerBufferFormat(AUDIO_FORMAT_PCM_16_BIT),
     62     mMixerBufferState(UNDEFINED),
     63     mFormat(Format_Invalid),
     64     mSampleRate(0),
     65     mFastTracksGen(0),
     66     mTotalNativeFramesWritten(0),
     67     // timestamp
     68     mNativeFramesWrittenButNotPresented(0),   // the = 0 is to silence the compiler
     69     mMasterMono(false)
     70 {
     71     // FIXME pass sInitial as parameter to base class constructor, and make it static local
     72     mPrevious = &sInitial;
     73     mCurrent = &sInitial;
     74 
     75     mDummyDumpState = &mDummyFastMixerDumpState;
     76     // TODO: Add channel mask to NBAIO_Format.
     77     // We assume that the channel mask must be a valid positional channel mask.
     78     mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
     79 
     80     unsigned i;
     81     for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
     82         mGenerations[i] = 0;
     83     }
     84 #ifdef FAST_THREAD_STATISTICS
     85     mOldLoad.tv_sec = 0;
     86     mOldLoad.tv_nsec = 0;
     87 #endif
     88 }
     89 
     90 FastMixer::~FastMixer()
     91 {
     92 }
     93 
     94 FastMixerStateQueue* FastMixer::sq()
     95 {
     96     return &mSQ;
     97 }
     98 
     99 const FastThreadState *FastMixer::poll()
    100 {
    101     return mSQ.poll();
    102 }
    103 
    104 void FastMixer::setNBLogWriter(NBLog::Writer *logWriter)
    105 {
    106     // FIXME If mMixer is set or changed prior to this, we don't inform correctly.
    107     //       Should cache logWriter and re-apply it at the assignment to mMixer.
    108     if (mMixer != NULL) {
    109         mMixer->setNBLogWriter(logWriter);
    110     }
    111 }
    112 
    113 void FastMixer::onIdle()
    114 {
    115     mPreIdle = *(const FastMixerState *)mCurrent;
    116     mCurrent = &mPreIdle;
    117 }
    118 
    119 void FastMixer::onExit()
    120 {
    121     delete mMixer;
    122     free(mMixerBuffer);
    123     free(mSinkBuffer);
    124 }
    125 
    126 bool FastMixer::isSubClassCommand(FastThreadState::Command command)
    127 {
    128     switch ((FastMixerState::Command) command) {
    129     case FastMixerState::MIX:
    130     case FastMixerState::WRITE:
    131     case FastMixerState::MIX_WRITE:
    132         return true;
    133     default:
    134         return false;
    135     }
    136 }
    137 
    138 void FastMixer::onStateChange()
    139 {
    140     const FastMixerState * const current = (const FastMixerState *) mCurrent;
    141     const FastMixerState * const previous = (const FastMixerState *) mPrevious;
    142     FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
    143     const size_t frameCount = current->mFrameCount;
    144 
    145     // update boottime offset, in case it has changed
    146     mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
    147             mBoottimeOffset.load();
    148 
    149     // handle state change here, but since we want to diff the state,
    150     // we're prepared for previous == &sInitial the first time through
    151     unsigned previousTrackMask;
    152 
    153     // check for change in output HAL configuration
    154     NBAIO_Format previousFormat = mFormat;
    155     if (current->mOutputSinkGen != mOutputSinkGen) {
    156         mOutputSink = current->mOutputSink;
    157         mOutputSinkGen = current->mOutputSinkGen;
    158         if (mOutputSink == NULL) {
    159             mFormat = Format_Invalid;
    160             mSampleRate = 0;
    161             mSinkChannelCount = 0;
    162             mSinkChannelMask = AUDIO_CHANNEL_NONE;
    163         } else {
    164             mFormat = mOutputSink->format();
    165             mSampleRate = Format_sampleRate(mFormat);
    166             mSinkChannelCount = Format_channelCount(mFormat);
    167             LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
    168 
    169             // TODO: Add channel mask to NBAIO_Format
    170             // We assume that the channel mask must be a valid positional channel mask.
    171             mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
    172         }
    173         dumpState->mSampleRate = mSampleRate;
    174     }
    175 
    176     if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
    177         // FIXME to avoid priority inversion, don't delete here
    178         delete mMixer;
    179         mMixer = NULL;
    180         free(mMixerBuffer);
    181         mMixerBuffer = NULL;
    182         free(mSinkBuffer);
    183         mSinkBuffer = NULL;
    184         if (frameCount > 0 && mSampleRate > 0) {
    185             // The mixer produces either 16 bit PCM or float output, select
    186             // float output if the HAL supports higher than 16 bit precision.
    187             mMixerBufferFormat = mFormat.mFormat == AUDIO_FORMAT_PCM_16_BIT ?
    188                     AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_FLOAT;
    189             // FIXME new may block for unbounded time at internal mutex of the heap
    190             //       implementation; it would be better to have normal mixer allocate for us
    191             //       to avoid blocking here and to prevent possible priority inversion
    192             mMixer = new AudioMixer(frameCount, mSampleRate);
    193             // FIXME See the other FIXME at FastMixer::setNBLogWriter()
    194             const size_t mixerFrameSize = mSinkChannelCount
    195                     * audio_bytes_per_sample(mMixerBufferFormat);
    196             mMixerBufferSize = mixerFrameSize * frameCount;
    197             (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize);
    198             const size_t sinkFrameSize = mSinkChannelCount
    199                     * audio_bytes_per_sample(mFormat.mFormat);
    200             if (sinkFrameSize > mixerFrameSize) { // need a sink buffer
    201                 mSinkBufferSize = sinkFrameSize * frameCount;
    202                 (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize);
    203             }
    204             mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;    // 1.00
    205             mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate;  // 1.75
    206             mOverrunNs = (frameCount * 500000000LL) / mSampleRate;    // 0.50
    207             mForceNs = (frameCount * 950000000LL) / mSampleRate;      // 0.95
    208             mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate;  // 0.75
    209             mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25
    210         } else {
    211             mPeriodNs = 0;
    212             mUnderrunNs = 0;
    213             mOverrunNs = 0;
    214             mForceNs = 0;
    215             mWarmupNsMin = 0;
    216             mWarmupNsMax = LONG_MAX;
    217         }
    218         mMixerBufferState = UNDEFINED;
    219         // we need to reconfigure all active tracks
    220         previousTrackMask = 0;
    221         mFastTracksGen = current->mFastTracksGen - 1;
    222         dumpState->mFrameCount = frameCount;
    223     } else {
    224         previousTrackMask = previous->mTrackMask;
    225     }
    226 
    227     // check for change in active track set
    228     const unsigned currentTrackMask = current->mTrackMask;
    229     dumpState->mTrackMask = currentTrackMask;
    230     if (current->mFastTracksGen != mFastTracksGen) {
    231         ALOG_ASSERT(mMixerBuffer != NULL);
    232 
    233         // process removed tracks first to avoid running out of track names
    234         unsigned removedTracks = previousTrackMask & ~currentTrackMask;
    235         while (removedTracks != 0) {
    236             int i = __builtin_ctz(removedTracks);
    237             removedTracks &= ~(1 << i);
    238             const FastTrack* fastTrack = &current->mFastTracks[i];
    239             ALOG_ASSERT(fastTrack->mBufferProvider == NULL);
    240             if (mMixer != NULL) {
    241                 mMixer->destroy(i);
    242             }
    243             // don't reset track dump state, since other side is ignoring it
    244             mGenerations[i] = fastTrack->mGeneration;
    245         }
    246 
    247         // now process added tracks
    248         unsigned addedTracks = currentTrackMask & ~previousTrackMask;
    249         while (addedTracks != 0) {
    250             int i = __builtin_ctz(addedTracks);
    251             addedTracks &= ~(1 << i);
    252             const FastTrack* fastTrack = &current->mFastTracks[i];
    253             AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
    254             if (mMixer != NULL) {
    255                 const int name = i; // for clarity, choose name as fast track index.
    256                 status_t status = mMixer->create(
    257                         name,
    258                         fastTrack->mChannelMask,
    259                         fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
    260                 LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
    261                         "%s: cannot create track name"
    262                         " %d, mask %#x, format %#x, sessionId %d in AudioMixer",
    263                         __func__, name,
    264                         fastTrack->mChannelMask, fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
    265                 mMixer->setBufferProvider(name, bufferProvider);
    266                 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
    267                         (void *)mMixerBuffer);
    268                 // newly allocated track names default to full scale volume
    269                 mMixer->setParameter(
    270                         name,
    271                         AudioMixer::TRACK,
    272                         AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
    273                 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
    274                         (void *)(uintptr_t)fastTrack->mFormat);
    275                 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
    276                         (void *)(uintptr_t)fastTrack->mChannelMask);
    277                 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
    278                         (void *)(uintptr_t)mSinkChannelMask);
    279                 mMixer->enable(name);
    280             }
    281             mGenerations[i] = fastTrack->mGeneration;
    282         }
    283 
    284         // finally process (potentially) modified tracks; these use the same slot
    285         // but may have a different buffer provider or volume provider
    286         unsigned modifiedTracks = currentTrackMask & previousTrackMask;
    287         while (modifiedTracks != 0) {
    288             int i = __builtin_ctz(modifiedTracks);
    289             modifiedTracks &= ~(1 << i);
    290             const FastTrack* fastTrack = &current->mFastTracks[i];
    291             if (fastTrack->mGeneration != mGenerations[i]) {
    292                 // this track was actually modified
    293                 AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
    294                 ALOG_ASSERT(bufferProvider != NULL);
    295                 if (mMixer != NULL) {
    296                     const int name = i;
    297                     mMixer->setBufferProvider(name, bufferProvider);
    298                     if (fastTrack->mVolumeProvider == NULL) {
    299                         float f = AudioMixer::UNITY_GAIN_FLOAT;
    300                         mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
    301                         mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
    302                     }
    303                     mMixer->setParameter(name, AudioMixer::RESAMPLE,
    304                             AudioMixer::REMOVE, NULL);
    305                     mMixer->setParameter(
    306                             name,
    307                             AudioMixer::TRACK,
    308                             AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
    309                     mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
    310                             (void *)(uintptr_t)fastTrack->mFormat);
    311                     mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
    312                             (void *)(uintptr_t)fastTrack->mChannelMask);
    313                     mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
    314                             (void *)(uintptr_t)mSinkChannelMask);
    315                     // already enabled
    316                 }
    317                 mGenerations[i] = fastTrack->mGeneration;
    318             }
    319         }
    320 
    321         mFastTracksGen = current->mFastTracksGen;
    322 
    323         dumpState->mNumTracks = popcount(currentTrackMask);
    324     }
    325 }
    326 
    327 void FastMixer::onWork()
    328 {
    329     // TODO: pass an ID parameter to indicate which time series we want to write to in NBLog.cpp
    330     // Or: pass both of these into a single call with a boolean
    331     if (mIsWarm) {
    332         LOG_HIST_TS();
    333     } else {
    334         LOG_AUDIO_STATE();
    335     }
    336     const FastMixerState * const current = (const FastMixerState *) mCurrent;
    337     FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
    338     const FastMixerState::Command command = mCommand;
    339     const size_t frameCount = current->mFrameCount;
    340 
    341     if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
    342         ALOG_ASSERT(mMixerBuffer != NULL);
    343 
    344         // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
    345         // so we keep a side copy of enabledTracks
    346         bool anyEnabledTracks = false;
    347 
    348         // for each track, update volume and check for underrun
    349         unsigned currentTrackMask = current->mTrackMask;
    350         while (currentTrackMask != 0) {
    351             int i = __builtin_ctz(currentTrackMask);
    352             currentTrackMask &= ~(1 << i);
    353             const FastTrack* fastTrack = &current->mFastTracks[i];
    354 
    355             const int64_t trackFramesWrittenButNotPresented =
    356                 mNativeFramesWrittenButNotPresented;
    357             const int64_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
    358             ExtendedTimestamp perTrackTimestamp(mTimestamp);
    359 
    360             // Can't provide an ExtendedTimestamp before first frame presented.
    361             // Also, timestamp may not go to very last frame on stop().
    362             if (trackFramesWritten >= trackFramesWrittenButNotPresented &&
    363                     perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) {
    364                 perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
    365                         trackFramesWritten - trackFramesWrittenButNotPresented;
    366             } else {
    367                 perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
    368                 perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
    369             }
    370             perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = trackFramesWritten;
    371             fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
    372 
    373             const int name = i;
    374             if (fastTrack->mVolumeProvider != NULL) {
    375                 gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
    376                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
    377                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
    378 
    379                 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf);
    380                 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf);
    381             }
    382             // FIXME The current implementation of framesReady() for fast tracks
    383             // takes a tryLock, which can block
    384             // up to 1 ms.  If enough active tracks all blocked in sequence, this would result
    385             // in the overall fast mix cycle being delayed.  Should use a non-blocking FIFO.
    386             size_t framesReady = fastTrack->mBufferProvider->framesReady();
    387             if (ATRACE_ENABLED()) {
    388                 // I wish we had formatted trace names
    389                 char traceName[16];
    390                 strcpy(traceName, "fRdy");
    391                 traceName[4] = i + (i < 10 ? '0' : 'A' - 10);
    392                 traceName[5] = '\0';
    393                 ATRACE_INT(traceName, framesReady);
    394             }
    395             FastTrackDump *ftDump = &dumpState->mTracks[i];
    396             FastTrackUnderruns underruns = ftDump->mUnderruns;
    397             if (framesReady < frameCount) {
    398                 if (framesReady == 0) {
    399                     underruns.mBitFields.mEmpty++;
    400                     underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY;
    401                     mMixer->disable(name);
    402                 } else {
    403                     // allow mixing partial buffer
    404                     underruns.mBitFields.mPartial++;
    405                     underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL;
    406                     mMixer->enable(name);
    407                     anyEnabledTracks = true;
    408                 }
    409             } else {
    410                 underruns.mBitFields.mFull++;
    411                 underruns.mBitFields.mMostRecent = UNDERRUN_FULL;
    412                 mMixer->enable(name);
    413                 anyEnabledTracks = true;
    414             }
    415             ftDump->mUnderruns = underruns;
    416             ftDump->mFramesReady = framesReady;
    417             ftDump->mFramesWritten = trackFramesWritten;
    418         }
    419 
    420         if (anyEnabledTracks) {
    421             // process() is CPU-bound
    422             mMixer->process();
    423             mMixerBufferState = MIXED;
    424         } else if (mMixerBufferState != ZEROED) {
    425             mMixerBufferState = UNDEFINED;
    426         }
    427 
    428     } else if (mMixerBufferState == MIXED) {
    429         mMixerBufferState = UNDEFINED;
    430     }
    431     //bool didFullWrite = false;    // dumpsys could display a count of partial writes
    432     if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
    433         if (mMixerBufferState == UNDEFINED) {
    434             memset(mMixerBuffer, 0, mMixerBufferSize);
    435             mMixerBufferState = ZEROED;
    436         }
    437 
    438         if (mMasterMono.load()) {  // memory_order_seq_cst
    439             mono_blend(mMixerBuffer, mMixerBufferFormat, Format_channelCount(mFormat), frameCount,
    440                     true /*limit*/);
    441         }
    442         // prepare the buffer used to write to sink
    443         void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
    444         if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
    445             memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
    446                     frameCount * Format_channelCount(mFormat));
    447         }
    448         // if non-NULL, then duplicate write() to this non-blocking sink
    449         NBAIO_Sink* teeSink;
    450         if ((teeSink = current->mTeeSink) != NULL) {
    451             (void) teeSink->write(buffer, frameCount);
    452         }
    453         // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink,
    454         //       but this code should be modified to handle both non-blocking and blocking sinks
    455         dumpState->mWriteSequence++;
    456         ATRACE_BEGIN("write");
    457         ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
    458         ATRACE_END();
    459         dumpState->mWriteSequence++;
    460         if (framesWritten >= 0) {
    461             ALOG_ASSERT((size_t) framesWritten <= frameCount);
    462             mTotalNativeFramesWritten += framesWritten;
    463             dumpState->mFramesWritten = mTotalNativeFramesWritten;
    464             //if ((size_t) framesWritten == frameCount) {
    465             //    didFullWrite = true;
    466             //}
    467         } else {
    468             dumpState->mWriteErrors++;
    469         }
    470         mAttemptedWrite = true;
    471         // FIXME count # of writes blocked excessively, CPU usage, etc. for dump
    472 
    473         ExtendedTimestamp timestamp; // local
    474         status_t status = mOutputSink->getTimestamp(timestamp);
    475         if (status == NO_ERROR) {
    476             const int64_t totalNativeFramesPresented =
    477                     timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
    478             if (totalNativeFramesPresented <= mTotalNativeFramesWritten) {
    479                 mNativeFramesWrittenButNotPresented =
    480                     mTotalNativeFramesWritten - totalNativeFramesPresented;
    481                 mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
    482                         timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
    483                 mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
    484                         timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
    485             } else {
    486                 // HAL reported that more frames were presented than were written
    487                 mNativeFramesWrittenButNotPresented = 0;
    488                 status = INVALID_OPERATION;
    489             }
    490         }
    491         if (status == NO_ERROR) {
    492             mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
    493                     mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
    494         } else {
    495             // fetch server time if we can't get timestamp
    496             mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
    497                     systemTime(SYSTEM_TIME_MONOTONIC);
    498             // clear out kernel cached position as this may get rapidly stale
    499             // if we never get a new valid timestamp
    500             mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
    501             mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
    502         }
    503     }
    504 }
    505 
    506 }   // namespace android
    507