android_AudioSfDecoder.cpp revision 7f5cc1afe49395fefaad9b2bbd728a45d1bfda6a
1/*
2 * Copyright (C) 2011 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//#define USE_LOG SLAndroidLogLevel_Verbose
18
19#include "sles_allinclusive.h"
20#include "android/android_AudioSfDecoder.h"
21
22#include <media/stagefright/foundation/ADebug.h>
23
24
25#define SIZE_CACHED_HIGH_BYTES 1000000
26#define SIZE_CACHED_MED_BYTES   700000
27#define SIZE_CACHED_LOW_BYTES   400000
28
29namespace android {
30
31// keep in sync with the entries of kPcmDecodeMetadataKeys[] defined in android_AudioSfDecoder.h
32#define ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS   0
33#define ANDROID_KEY_INDEX_PCMFORMAT_SAMPLESPERSEC 1
34#define ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE 2
35#define ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE 3
36#define ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK   4
37#define ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS    5
38
39//--------------------------------------------------------------------------------------------------
40AudioSfDecoder::AudioSfDecoder(const AudioPlayback_Parameters* params) : GenericPlayer(params),
41        mDataSource(0),
42        mAudioSource(0),
43        mBitrate(-1),
44        mChannelMask(ANDROID_UNKNOWN_CHANNELMASK),
45        mDurationUsec(-1),
46        mDecodeBuffer(NULL),
47        mTimeDelta(-1),
48        mSeekTimeMsec(0),
49        mLastDecodedPositionUs(-1),
50        mPcmFormatKeyCount(0),
51        mGetPcmFormatKeyCount(false)
52{
53    SL_LOGV("AudioSfDecoder::AudioSfDecoder()");
54
55}
56
57
58AudioSfDecoder::~AudioSfDecoder() {
59    SL_LOGV("AudioSfDecoder::~AudioSfDecoder()");
60    if (mAudioSource != 0) {
61        mAudioSource->stop();
62    }
63}
64
65
66//--------------------------------------------------
67void AudioSfDecoder::play() {
68    SL_LOGV("AudioSfDecoder::play");
69
70    GenericPlayer::play();
71    (new AMessage(kWhatDecode, id()))->post();
72}
73
74
75void AudioSfDecoder::startPrefetch_async() {
76    SL_LOGV("AudioSfDecoder::startPrefetch_async()");
77
78    if (wantPrefetch()) {
79        SL_LOGV("AudioSfDecoder::startPrefetch_async(): sending check cache msg");
80
81        mStateFlags |= kFlagPreparing | kFlagBuffering;
82
83        (new AMessage(kWhatCheckCache, id()))->post();
84    }
85}
86
87
88//--------------------------------------------------
89uint32_t AudioSfDecoder::getPcmFormatKeyCount() {
90    android::Mutex::Autolock autoLock(mGetPcmFormatLockSingleton);
91    mGetPcmFormatKeyCount = false;
92    (new AMessage(kWhatGetPcmFormat, id()))->post();
93    {
94        android::Mutex::Autolock autoLock(mGetPcmFormatLock);
95        while (!mGetPcmFormatKeyCount) {
96            mGetPcmFormatCondition.wait(mGetPcmFormatLock);
97        }
98    }
99    mGetPcmFormatKeyCount = false;
100    return mPcmFormatKeyCount;
101}
102
103
104//--------------------------------------------------
105bool AudioSfDecoder::getPcmFormatKeySize(uint32_t index, uint32_t* pKeySize) {
106    uint32_t keyCount = getPcmFormatKeyCount();
107    if (index >= keyCount) {
108        return false;
109    } else {
110        *pKeySize = strlen(kPcmDecodeMetadataKeys[index]) +1;
111        return true;
112    }
113}
114
115
116//--------------------------------------------------
117bool AudioSfDecoder::getPcmFormatKeyName(uint32_t index, uint32_t keySize, char* keyName) {
118    uint32_t actualKeySize;
119    if (!getPcmFormatKeySize(index, &actualKeySize)) {
120        return false;
121    }
122    if (keySize < actualKeySize) {
123        return false;
124    }
125    strncpy(keyName, kPcmDecodeMetadataKeys[index], actualKeySize);
126    return true;
127}
128
129
130//--------------------------------------------------
131bool AudioSfDecoder::getPcmFormatValueSize(uint32_t index, uint32_t* pValueSize) {
132    uint32_t keyCount = getPcmFormatKeyCount();
133    if (index >= keyCount) {
134        *pValueSize = 0;
135        return false;
136    } else {
137        *pValueSize = sizeof(uint32_t);
138        return true;
139    }
140}
141
142
143//--------------------------------------------------
144bool AudioSfDecoder::getPcmFormatKeyValue(uint32_t index, uint32_t size, uint32_t* pValue) {
145    uint32_t valueSize = 0;
146    if (!getPcmFormatValueSize(index, &valueSize)) {
147        return false;
148    } else if (size == valueSize) {
149        // this ensures we are accessing mPcmFormatValues with a valid size for that index
150        return false;
151    } else {
152        *pValue = mPcmFormatValues[index];
153        return true;
154    }
155}
156
157
158//--------------------------------------------------
159// Event handlers
160void AudioSfDecoder::onPrepare() {
161    SL_LOGD("AudioSfDecoder::onPrepare()");
162
163    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE] = SL_PCMSAMPLEFORMAT_FIXED_16;
164    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE] = 16;
165    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS] = SL_BYTEORDER_LITTLEENDIAN;
166    // initialization with the default values
167    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
168    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLESPERSEC] = mSampleRateHz;
169    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = mChannelMask;
170
171    sp<DataSource> dataSource;
172
173    switch (mDataLocatorType) {
174
175    case kDataLocatorNone:
176        SL_LOGE("AudioSfDecoder::onPrepare: no data locator set");
177        notifyPrepared(MEDIA_ERROR_BASE);
178        return;
179
180    case kDataLocatorUri:
181        dataSource = DataSource::CreateFromURI(mDataLocator.uriRef);
182        if (dataSource == NULL) {
183            SL_LOGE("AudioSfDecoder::onPrepare(): Error opening %s", mDataLocator.uriRef);
184            notifyPrepared(MEDIA_ERROR_BASE);
185            return;
186        }
187        break;
188
189    case kDataLocatorFd:
190    {
191        dataSource = new FileSource(
192                mDataLocator.fdi.fd, mDataLocator.fdi.offset, mDataLocator.fdi.length);
193        status_t err = dataSource->initCheck();
194        if (err != OK) {
195            notifyPrepared(err);
196            return;
197        }
198        break;
199    }
200
201    default:
202        TRESPASS();
203    }
204
205    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
206    if (extractor == NULL) {
207        SL_LOGE("AudioSfDecoder::onPrepare: Could not instantiate extractor.");
208        notifyPrepared(ERROR_UNSUPPORTED);
209        return;
210    }
211
212    ssize_t audioTrackIndex = -1;
213    bool isRawAudio = false;
214    for (size_t i = 0; i < extractor->countTracks(); ++i) {
215        sp<MetaData> meta = extractor->getTrackMetaData(i);
216
217        const char *mime;
218        CHECK(meta->findCString(kKeyMIMEType, &mime));
219
220        if (!strncasecmp("audio/", mime, 6)) {
221            audioTrackIndex = i;
222
223            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
224                isRawAudio = true;
225            }
226            break;
227        }
228    }
229
230    if (audioTrackIndex < 0) {
231        SL_LOGE("AudioSfDecoder::onPrepare: Could not find a supported audio track.");
232        notifyPrepared(ERROR_UNSUPPORTED);
233        return;
234    }
235
236    sp<MediaSource> source = extractor->getTrack(audioTrackIndex);
237    sp<MetaData> meta = source->getFormat();
238
239    bool hasChannelCount = meta->findInt32(kKeyChannelCount, &mChannelCount);
240    if (hasChannelCount) {
241        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
242    }
243
244    off64_t size;
245    int64_t durationUs;
246    if (dataSource->getSize(&size) == OK
247            && meta->findInt64(kKeyDuration, &durationUs)) {
248        mBitrate = size * 8000000ll / durationUs;  // in bits/sec
249        mDurationUsec = durationUs;
250        mDurationMsec = durationUs / 1000;
251    } else {
252        mBitrate = -1;
253        mDurationUsec = -1;
254    }
255
256    if (!isRawAudio) {
257        OMXClient client;
258        CHECK_EQ(client.connect(), (status_t)OK);
259
260        source = OMXCodec::Create(
261                client.interface(), meta, false /* createEncoder */,
262                source);
263
264        if (source == NULL) {
265            SL_LOGE("AudioSfDecoder::onPrepare: Could not instantiate decoder.");
266            notifyPrepared(ERROR_UNSUPPORTED);
267            return;
268        }
269
270        meta = source->getFormat();
271    }
272
273
274    if (source->start() != OK) {
275        SL_LOGE("AudioSfDecoder::onPrepare: Failed to start source/decoder.");
276        notifyPrepared(MEDIA_ERROR_BASE);
277        return;
278    }
279
280    mDataSource = dataSource;
281    mAudioSource = source;
282
283    if (!hasChannelCount) {
284        // even though the channel count was already queried above, there are issues with some
285        // OMXCodecs (e.g. MP3 software decoder) not reporting the right count,
286        // we trust the first reported value.
287        CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
288        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
289    }
290    int32_t sr;
291    CHECK(meta->findInt32(kKeySampleRate, &sr));
292    mSampleRateHz = (uint32_t) sr;
293    mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLESPERSEC] = mSampleRateHz;
294    // FIXME add code below once channel mask support is in, currently initialized to default
295    //    if (meta->findInt32(kKeyChannelMask, &mChannelMask)) {
296    //        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = mChannelMask;
297    //    }
298
299    if (!wantPrefetch()) {
300        SL_LOGV("AudioSfDecoder::onPrepare: no need to prefetch");
301        // doesn't need prefetching, notify good to go
302        mCacheStatus = kStatusHigh;
303        mCacheFill = 1000;
304        notifyStatus();
305        notifyCacheFill();
306    }
307
308    // at this point we have enough information about the source to create the sink that
309    // will consume the data
310    createAudioSink();
311
312    GenericPlayer::onPrepare();
313    SL_LOGD("AudioSfDecoder::onPrepare() done, mStateFlags=0x%x", mStateFlags);
314}
315
316
317void AudioSfDecoder::onPause() {
318    SL_LOGD("AudioSfDecoder::onPause()");
319    GenericPlayer::onPause();
320    pauseAudioSink();
321}
322
323
324void AudioSfDecoder::onPlay() {
325    SL_LOGD("AudioSfDecoder::onPlay()");
326    GenericPlayer::onPlay();
327    startAudioSink();
328}
329
330
331void AudioSfDecoder::onSeek(const sp<AMessage> &msg) {
332    SL_LOGV("AudioSfDecoder::onSeek");
333    int64_t timeMsec;
334    CHECK(msg->findInt64(WHATPARAM_SEEK_SEEKTIME_MS, &timeMsec));
335
336    Mutex::Autolock _l(mSeekLock);
337    mStateFlags |= kFlagSeeking;
338    mSeekTimeMsec = timeMsec;
339    mTimeDelta = -1;
340    mLastDecodedPositionUs = -1;
341}
342
343
344void AudioSfDecoder::onLoop(const sp<AMessage> &msg) {
345    SL_LOGV("AudioSfDecoder::onLoop");
346    int32_t loop;
347    CHECK(msg->findInt32(WHATPARAM_LOOP_LOOPING, &loop));
348
349    if (loop) {
350        //SL_LOGV("AudioSfDecoder::onLoop start looping");
351        mStateFlags |= kFlagLooping;
352    } else {
353        //SL_LOGV("AudioSfDecoder::onLoop stop looping");
354        mStateFlags &= ~kFlagLooping;
355    }
356}
357
358
359void AudioSfDecoder::onGetPcmFormatKeyCount() {
360    SL_LOGV("AudioSfDecoder::onGetPcmFormatKeyCount");
361    {
362        android::Mutex::Autolock autoLock(mGetPcmFormatLock);
363
364        if (!(mStateFlags & kFlagPrepared)) {
365            mPcmFormatKeyCount = 0;
366        } else {
367            mPcmFormatKeyCount = NB_PCMMETADATA_KEYS;
368        }
369
370        mGetPcmFormatKeyCount = true;
371        mGetPcmFormatCondition.signal();
372    }
373
374}
375
376
377void AudioSfDecoder::onCheckCache(const sp<AMessage> &msg) {
378    //SL_LOGV("AudioSfDecoder::onCheckCache");
379    bool eos;
380    CacheStatus_t status = getCacheRemaining(&eos);
381
382    if (eos || status == kStatusHigh
383            || ((mStateFlags & kFlagPreparing) && (status >= kStatusEnough))) {
384        if (mStateFlags & kFlagPlaying) {
385            startAudioSink();
386        }
387        mStateFlags &= ~kFlagBuffering;
388
389        SL_LOGV("AudioSfDecoder::onCheckCache: buffering done.");
390
391        if (mStateFlags & kFlagPreparing) {
392            //SL_LOGV("AudioSfDecoder::onCheckCache: preparation done.");
393            mStateFlags &= ~kFlagPreparing;
394        }
395
396        mTimeDelta = -1;
397        if (mStateFlags & kFlagPlaying) {
398            (new AMessage(kWhatDecode, id()))->post();
399        }
400        return;
401    }
402
403    msg->post(100000);
404}
405
406
407void AudioSfDecoder::onDecode() {
408    SL_LOGV("AudioSfDecoder::onDecode");
409
410    //-------------------------------- Need to buffer some more before decoding?
411    bool eos;
412    if (mDataSource == 0) {
413        // application set play state to paused which failed, then set play state to playing
414        return;
415    }
416    if (wantPrefetch()
417            && (getCacheRemaining(&eos) == kStatusLow)
418            && !eos) {
419        SL_LOGV("buffering more.");
420
421        if (mStateFlags & kFlagPlaying) {
422            pauseAudioSink();
423        }
424        mStateFlags |= kFlagBuffering;
425        (new AMessage(kWhatCheckCache, id()))->post(100000);
426        return;
427    }
428
429    if (!(mStateFlags & (kFlagPlaying | kFlagBuffering | kFlagPreparing))) {
430        // don't decode if we're not buffering, prefetching or playing
431        //SL_LOGV("don't decode: not buffering, prefetching or playing");
432        return;
433    }
434
435    //-------------------------------- Decode
436    status_t err;
437    MediaSource::ReadOptions readOptions;
438    if (mStateFlags & kFlagSeeking) {
439        readOptions.setSeekTo(mSeekTimeMsec * 1000);
440    }
441
442    {
443        Mutex::Autolock _l(mDecodeBufferLock);
444        if (NULL != mDecodeBuffer) {
445            // the current decoded buffer hasn't been rendered, drop it
446            mDecodeBuffer->release();
447            mDecodeBuffer = NULL;
448        }
449        err = mAudioSource->read(&mDecodeBuffer, &readOptions);
450        if (err == OK) {
451            CHECK(mDecodeBuffer->meta_data()->findInt64(kKeyTime, &mLastDecodedPositionUs));
452        }
453    }
454
455    {
456        Mutex::Autolock _l(mSeekLock);
457        if (mStateFlags & kFlagSeeking) {
458            mStateFlags &= ~kFlagSeeking;
459        }
460    }
461
462    //-------------------------------- Handle return of decode
463    if (err != OK) {
464        bool continueDecoding = false;
465        switch(err) {
466            case ERROR_END_OF_STREAM:
467                if (0 < mDurationUsec) {
468                    mLastDecodedPositionUs = mDurationUsec;
469                }
470                // handle notification and looping at end of stream
471                if (mStateFlags & kFlagPlaying) {
472                    notify(PLAYEREVENT_ENDOFSTREAM, 1, true);
473                }
474                if (mStateFlags & kFlagLooping) {
475                    seek(0);
476                    // kick-off decoding again
477                    continueDecoding = true;
478                }
479                break;
480            case INFO_FORMAT_CHANGED:
481                SL_LOGD("MediaSource::read encountered INFO_FORMAT_CHANGED");
482                // reconfigure output
483                updateAudioSink();
484                continueDecoding = true;
485                break;
486            case INFO_DISCONTINUITY:
487                SL_LOGD("MediaSource::read encountered INFO_DISCONTINUITY");
488                continueDecoding = true;
489                break;
490            default:
491                SL_LOGE("MediaSource::read returned error %d", err);
492                break;
493        }
494        if (continueDecoding) {
495            if (NULL == mDecodeBuffer) {
496                (new AMessage(kWhatDecode, id()))->post();
497                return;
498            }
499        } else {
500            return;
501        }
502    }
503
504    //-------------------------------- Render
505    sp<AMessage> msg = new AMessage(kWhatRender, id());
506    msg->post();
507}
508
509
510void AudioSfDecoder::onRender() {
511    //SL_LOGV("AudioSfDecoder::onRender");
512
513    Mutex::Autolock _l(mDecodeBufferLock);
514
515    if (NULL == mDecodeBuffer) {
516        // nothing to render, move along
517        SL_LOGV("AudioSfDecoder::onRender NULL buffer, exiting");
518        return;
519    }
520
521    mDecodeBuffer->release();
522    mDecodeBuffer = NULL;
523
524}
525
526
527void AudioSfDecoder::onMessageReceived(const sp<AMessage> &msg) {
528    switch (msg->what()) {
529        case kWhatPrepare:
530            onPrepare();
531            break;
532
533        case kWhatDecode:
534            onDecode();
535            break;
536
537        case kWhatRender:
538            onRender();
539            break;
540
541        case kWhatCheckCache:
542            onCheckCache(msg);
543            break;
544
545        case kWhatNotif:
546            onNotify(msg);
547            break;
548
549        case kWhatPlay:
550            onPlay();
551            break;
552
553        case kWhatPause:
554            onPause();
555            break;
556
557        case kWhatGetPcmFormat:
558            onGetPcmFormatKeyCount();
559            break;
560/*
561        case kWhatSeek:
562            onSeek(msg);
563            break;
564
565        case kWhatLoop:
566            onLoop(msg);
567            break;
568*/
569        default:
570            GenericPlayer::onMessageReceived(msg);
571            break;
572    }
573}
574
575//--------------------------------------------------
576// Prepared state, prefetch status notifications
577void AudioSfDecoder::notifyPrepared(status_t prepareRes) {
578    notify(PLAYEREVENT_PREPARED, (int32_t)prepareRes, true);
579
580}
581
582
583void AudioSfDecoder::onNotify(const sp<AMessage> &msg) {
584    if (NULL == mNotifyClient) {
585        return;
586    }
587    int32_t val;
588    if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val)) {
589        SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val);
590        mNotifyClient(kEventPrefetchStatusChange, val, 0, mNotifyUser);
591    }
592    else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val)) {
593        SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val);
594        mNotifyClient(kEventPrefetchFillLevelUpdate, val, 0, mNotifyUser);
595    }
596    else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val)) {
597        SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val);
598        mNotifyClient(kEventEndOfStream, val, 0, mNotifyUser);
599    }
600    else {
601        GenericPlayer::onNotify(msg);
602    }
603}
604
605
606//--------------------------------------------------
607// Private utility functions
608
609bool AudioSfDecoder::wantPrefetch() {
610    return (mDataSource->flags() & DataSource::kWantsPrefetching);
611}
612
613
614int64_t AudioSfDecoder::getPositionUsec() {
615    Mutex::Autolock _l(mSeekLock);
616    if (mStateFlags & kFlagSeeking) {
617        return mSeekTimeMsec * 1000;
618    } else {
619        if (mLastDecodedPositionUs < 0) {
620            return 0;
621        } else {
622            return mLastDecodedPositionUs;
623        }
624    }
625}
626
627
628CacheStatus_t AudioSfDecoder::getCacheRemaining(bool *eos) {
629    sp<NuCachedSource2> cachedSource =
630        static_cast<NuCachedSource2 *>(mDataSource.get());
631
632    CacheStatus_t oldStatus = mCacheStatus;
633
634    status_t finalStatus;
635    size_t dataRemaining = cachedSource->approxDataRemaining(&finalStatus);
636    *eos = (finalStatus != OK);
637
638    CHECK_GE(mBitrate, 0);
639
640    int64_t dataRemainingUs = dataRemaining * 8000000ll / mBitrate;
641    //SL_LOGV("AudioSfDecoder::getCacheRemaining: approx %.2f secs remaining (eos=%d)",
642    //       dataRemainingUs / 1E6, *eos);
643
644    if (*eos) {
645        // data is buffered up to the end of the stream, it can't get any better than this
646        mCacheStatus = kStatusHigh;
647        mCacheFill = 1000;
648
649    } else {
650        if (mDurationUsec > 0) {
651            // known duration:
652
653            //   fill level is ratio of how much has been played + how much is
654            //   cached, divided by total duration
655            uint32_t currentPositionUsec = getPositionUsec();
656            mCacheFill = (int16_t) ((1000.0
657                    * (double)(currentPositionUsec + dataRemainingUs) / mDurationUsec));
658            //SL_LOGV("cacheFill = %d", mCacheFill);
659
660            //   cache status is evaluated against duration thresholds
661            if (dataRemainingUs > DURATION_CACHED_HIGH_MS*1000) {
662                mCacheStatus = kStatusHigh;
663                //LOGV("high");
664            } else if (dataRemainingUs > DURATION_CACHED_MED_MS*1000) {
665                //LOGV("enough");
666                mCacheStatus = kStatusEnough;
667            } else if (dataRemainingUs < DURATION_CACHED_LOW_MS*1000) {
668                //LOGV("low");
669                mCacheStatus = kStatusLow;
670            } else {
671                mCacheStatus = kStatusIntermediate;
672            }
673
674        } else {
675            // unknown duration:
676
677            //   cache status is evaluated against cache amount thresholds
678            //   (no duration so we don't have the bitrate either, could be derived from format?)
679            if (dataRemaining > SIZE_CACHED_HIGH_BYTES) {
680                mCacheStatus = kStatusHigh;
681            } else if (dataRemaining > SIZE_CACHED_MED_BYTES) {
682                mCacheStatus = kStatusEnough;
683            } else if (dataRemaining < SIZE_CACHED_LOW_BYTES) {
684                mCacheStatus = kStatusLow;
685            } else {
686                mCacheStatus = kStatusIntermediate;
687            }
688        }
689
690    }
691
692    if (oldStatus != mCacheStatus) {
693        notifyStatus();
694    }
695
696    if (abs(mCacheFill - mLastNotifiedCacheFill) > mCacheFillNotifThreshold) {
697        notifyCacheFill();
698    }
699
700    return mCacheStatus;
701}
702
703} // namespace android
704