1/*
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaPlayer"
20#include <utils/Log.h>
21
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <fcntl.h>
26
27#include <binder/IServiceManager.h>
28#include <binder/IPCThreadState.h>
29
30#include <gui/SurfaceTextureClient.h>
31
32#include <media/mediaplayer.h>
33#include <media/AudioSystem.h>
34
35#include <binder/MemoryBase.h>
36
37#include <utils/KeyedVector.h>
38#include <utils/String8.h>
39
40#include <system/audio.h>
41#include <system/window.h>
42
43namespace android {
44
45MediaPlayer::MediaPlayer()
46{
47    ALOGV("constructor");
48    mListener = NULL;
49    mCookie = NULL;
50    mDuration = -1;
51    mStreamType = AUDIO_STREAM_MUSIC;
52    mCurrentPosition = -1;
53    mSeekPosition = -1;
54    mCurrentState = MEDIA_PLAYER_IDLE;
55    mPrepareSync = false;
56    mPrepareStatus = NO_ERROR;
57    mLoop = false;
58    mLeftVolume = mRightVolume = 1.0;
59    mVideoWidth = mVideoHeight = 0;
60    mLockThreadId = 0;
61    mAudioSessionId = AudioSystem::newAudioSessionId();
62    AudioSystem::acquireAudioSessionId(mAudioSessionId);
63    mSendLevel = 0;
64    mRetransmitEndpointValid = false;
65}
66
67MediaPlayer::~MediaPlayer()
68{
69    ALOGV("destructor");
70    AudioSystem::releaseAudioSessionId(mAudioSessionId);
71    disconnect();
72    IPCThreadState::self()->flushCommands();
73}
74
75void MediaPlayer::disconnect()
76{
77    ALOGV("disconnect");
78    sp<IMediaPlayer> p;
79    {
80        Mutex::Autolock _l(mLock);
81        p = mPlayer;
82        mPlayer.clear();
83    }
84
85    if (p != 0) {
86        p->disconnect();
87    }
88}
89
90// always call with lock held
91void MediaPlayer::clear_l()
92{
93    mDuration = -1;
94    mCurrentPosition = -1;
95    mSeekPosition = -1;
96    mVideoWidth = mVideoHeight = 0;
97    mRetransmitEndpointValid = false;
98}
99
100status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
101{
102    ALOGV("setListener");
103    Mutex::Autolock _l(mLock);
104    mListener = listener;
105    return NO_ERROR;
106}
107
108
109status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
110{
111    status_t err = UNKNOWN_ERROR;
112    sp<IMediaPlayer> p;
113    { // scope for the lock
114        Mutex::Autolock _l(mLock);
115
116        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
117                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
118            ALOGE("attachNewPlayer called in state %d", mCurrentState);
119            return INVALID_OPERATION;
120        }
121
122        clear_l();
123        p = mPlayer;
124        mPlayer = player;
125        if (player != 0) {
126            mCurrentState = MEDIA_PLAYER_INITIALIZED;
127            err = NO_ERROR;
128        } else {
129            ALOGE("Unable to to create media player");
130        }
131    }
132
133    if (p != 0) {
134        p->disconnect();
135    }
136
137    return err;
138}
139
140status_t MediaPlayer::setDataSource(
141        const char *url, const KeyedVector<String8, String8> *headers)
142{
143    ALOGV("setDataSource(%s)", url);
144    status_t err = BAD_VALUE;
145    if (url != NULL) {
146        const sp<IMediaPlayerService>& service(getMediaPlayerService());
147        if (service != 0) {
148            sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
149            if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
150                (NO_ERROR != player->setDataSource(url, headers))) {
151                player.clear();
152            }
153            err = attachNewPlayer(player);
154        }
155    }
156    return err;
157}
158
159status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
160{
161    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
162    status_t err = UNKNOWN_ERROR;
163    const sp<IMediaPlayerService>& service(getMediaPlayerService());
164    if (service != 0) {
165        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
166        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
167            (NO_ERROR != player->setDataSource(fd, offset, length))) {
168            player.clear();
169        }
170        err = attachNewPlayer(player);
171    }
172    return err;
173}
174
175status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
176{
177    ALOGV("setDataSource");
178    status_t err = UNKNOWN_ERROR;
179    const sp<IMediaPlayerService>& service(getMediaPlayerService());
180    if (service != 0) {
181        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
182        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
183            (NO_ERROR != player->setDataSource(source))) {
184            player.clear();
185        }
186        err = attachNewPlayer(player);
187    }
188    return err;
189}
190
191status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
192{
193    Mutex::Autolock _l(mLock);
194    const bool hasBeenInitialized =
195            (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
196            ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
197    if ((mPlayer != NULL) && hasBeenInitialized) {
198        ALOGV("invoke %d", request.dataSize());
199        return  mPlayer->invoke(request, reply);
200    }
201    ALOGE("invoke failed: wrong state %X", mCurrentState);
202    return INVALID_OPERATION;
203}
204
205status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
206{
207    ALOGD("setMetadataFilter");
208    Mutex::Autolock lock(mLock);
209    if (mPlayer == NULL) {
210        return NO_INIT;
211    }
212    return mPlayer->setMetadataFilter(filter);
213}
214
215status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
216{
217    ALOGD("getMetadata");
218    Mutex::Autolock lock(mLock);
219    if (mPlayer == NULL) {
220        return NO_INIT;
221    }
222    return mPlayer->getMetadata(update_only, apply_filter, metadata);
223}
224
225status_t MediaPlayer::setVideoSurfaceTexture(
226        const sp<ISurfaceTexture>& surfaceTexture)
227{
228    ALOGV("setVideoSurfaceTexture");
229    Mutex::Autolock _l(mLock);
230    if (mPlayer == 0) return NO_INIT;
231    return mPlayer->setVideoSurfaceTexture(surfaceTexture);
232}
233
234// must call with lock held
235status_t MediaPlayer::prepareAsync_l()
236{
237    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
238        mPlayer->setAudioStreamType(mStreamType);
239        mCurrentState = MEDIA_PLAYER_PREPARING;
240        return mPlayer->prepareAsync();
241    }
242    ALOGE("prepareAsync called in state %d", mCurrentState);
243    return INVALID_OPERATION;
244}
245
246// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
247// one defined in the Android framework and one provided by the implementation
248// that generated the error. The sync version of prepare returns only 1 error
249// code.
250status_t MediaPlayer::prepare()
251{
252    ALOGV("prepare");
253    Mutex::Autolock _l(mLock);
254    mLockThreadId = getThreadId();
255    if (mPrepareSync) {
256        mLockThreadId = 0;
257        return -EALREADY;
258    }
259    mPrepareSync = true;
260    status_t ret = prepareAsync_l();
261    if (ret != NO_ERROR) {
262        mLockThreadId = 0;
263        return ret;
264    }
265
266    if (mPrepareSync) {
267        mSignal.wait(mLock);  // wait for prepare done
268        mPrepareSync = false;
269    }
270    ALOGV("prepare complete - status=%d", mPrepareStatus);
271    mLockThreadId = 0;
272    return mPrepareStatus;
273}
274
275status_t MediaPlayer::prepareAsync()
276{
277    ALOGV("prepareAsync");
278    Mutex::Autolock _l(mLock);
279    return prepareAsync_l();
280}
281
282status_t MediaPlayer::start()
283{
284    ALOGV("start");
285    Mutex::Autolock _l(mLock);
286    if (mCurrentState & MEDIA_PLAYER_STARTED)
287        return NO_ERROR;
288    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
289                    MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
290        mPlayer->setLooping(mLoop);
291        mPlayer->setVolume(mLeftVolume, mRightVolume);
292        mPlayer->setAuxEffectSendLevel(mSendLevel);
293        mCurrentState = MEDIA_PLAYER_STARTED;
294        status_t ret = mPlayer->start();
295        if (ret != NO_ERROR) {
296            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
297        } else {
298            if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
299                ALOGV("playback completed immediately following start()");
300            }
301        }
302        return ret;
303    }
304    ALOGE("start called in state %d", mCurrentState);
305    return INVALID_OPERATION;
306}
307
308status_t MediaPlayer::stop()
309{
310    ALOGV("stop");
311    Mutex::Autolock _l(mLock);
312    if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
313    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
314                    MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
315        status_t ret = mPlayer->stop();
316        if (ret != NO_ERROR) {
317            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
318        } else {
319            mCurrentState = MEDIA_PLAYER_STOPPED;
320        }
321        return ret;
322    }
323    ALOGE("stop called in state %d", mCurrentState);
324    return INVALID_OPERATION;
325}
326
327status_t MediaPlayer::pause()
328{
329    ALOGV("pause");
330    Mutex::Autolock _l(mLock);
331    if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
332        return NO_ERROR;
333    if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
334        status_t ret = mPlayer->pause();
335        if (ret != NO_ERROR) {
336            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
337        } else {
338            mCurrentState = MEDIA_PLAYER_PAUSED;
339        }
340        return ret;
341    }
342    ALOGE("pause called in state %d", mCurrentState);
343    return INVALID_OPERATION;
344}
345
346bool MediaPlayer::isPlaying()
347{
348    Mutex::Autolock _l(mLock);
349    if (mPlayer != 0) {
350        bool temp = false;
351        mPlayer->isPlaying(&temp);
352        ALOGV("isPlaying: %d", temp);
353        if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
354            ALOGE("internal/external state mismatch corrected");
355            mCurrentState = MEDIA_PLAYER_PAUSED;
356        }
357        return temp;
358    }
359    ALOGV("isPlaying: no active player");
360    return false;
361}
362
363status_t MediaPlayer::getVideoWidth(int *w)
364{
365    ALOGV("getVideoWidth");
366    Mutex::Autolock _l(mLock);
367    if (mPlayer == 0) return INVALID_OPERATION;
368    *w = mVideoWidth;
369    return NO_ERROR;
370}
371
372status_t MediaPlayer::getVideoHeight(int *h)
373{
374    ALOGV("getVideoHeight");
375    Mutex::Autolock _l(mLock);
376    if (mPlayer == 0) return INVALID_OPERATION;
377    *h = mVideoHeight;
378    return NO_ERROR;
379}
380
381status_t MediaPlayer::getCurrentPosition(int *msec)
382{
383    ALOGV("getCurrentPosition");
384    Mutex::Autolock _l(mLock);
385    if (mPlayer != 0) {
386        if (mCurrentPosition >= 0) {
387            ALOGV("Using cached seek position: %d", mCurrentPosition);
388            *msec = mCurrentPosition;
389            return NO_ERROR;
390        }
391        return mPlayer->getCurrentPosition(msec);
392    }
393    return INVALID_OPERATION;
394}
395
396status_t MediaPlayer::getDuration_l(int *msec)
397{
398    ALOGV("getDuration");
399    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
400    if (mPlayer != 0 && isValidState) {
401        status_t ret = NO_ERROR;
402        if (mDuration <= 0)
403            ret = mPlayer->getDuration(&mDuration);
404        if (msec)
405            *msec = mDuration;
406        return ret;
407    }
408    ALOGE("Attempt to call getDuration without a valid mediaplayer");
409    return INVALID_OPERATION;
410}
411
412status_t MediaPlayer::getDuration(int *msec)
413{
414    Mutex::Autolock _l(mLock);
415    return getDuration_l(msec);
416}
417
418status_t MediaPlayer::seekTo_l(int msec)
419{
420    ALOGV("seekTo %d", msec);
421    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
422        if ( msec < 0 ) {
423            ALOGW("Attempt to seek to invalid position: %d", msec);
424            msec = 0;
425        } else if ((mDuration > 0) && (msec > mDuration)) {
426            ALOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
427            msec = mDuration;
428        }
429        // cache duration
430        mCurrentPosition = msec;
431        if (mSeekPosition < 0) {
432            getDuration_l(NULL);
433            mSeekPosition = msec;
434            return mPlayer->seekTo(msec);
435        }
436        else {
437            ALOGV("Seek in progress - queue up seekTo[%d]", msec);
438            return NO_ERROR;
439        }
440    }
441    ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
442    return INVALID_OPERATION;
443}
444
445status_t MediaPlayer::seekTo(int msec)
446{
447    mLockThreadId = getThreadId();
448    Mutex::Autolock _l(mLock);
449    status_t result = seekTo_l(msec);
450    mLockThreadId = 0;
451
452    return result;
453}
454
455status_t MediaPlayer::reset_l()
456{
457    mLoop = false;
458    if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
459    mPrepareSync = false;
460    if (mPlayer != 0) {
461        status_t ret = mPlayer->reset();
462        if (ret != NO_ERROR) {
463            ALOGE("reset() failed with return code (%d)", ret);
464            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
465        } else {
466            mCurrentState = MEDIA_PLAYER_IDLE;
467        }
468        // setDataSource has to be called again to create a
469        // new mediaplayer.
470        mPlayer = 0;
471        return ret;
472    }
473    clear_l();
474    return NO_ERROR;
475}
476
477status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
478    Mutex::Autolock _l(mLock);
479
480    if (player == NULL) {
481        return UNKNOWN_ERROR;
482    }
483
484    if (mRetransmitEndpointValid) {
485        return player->setRetransmitEndpoint(&mRetransmitEndpoint);
486    }
487
488    return OK;
489}
490
491status_t MediaPlayer::reset()
492{
493    ALOGV("reset");
494    Mutex::Autolock _l(mLock);
495    return reset_l();
496}
497
498status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
499{
500    ALOGV("MediaPlayer::setAudioStreamType");
501    Mutex::Autolock _l(mLock);
502    if (mStreamType == type) return NO_ERROR;
503    if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
504                MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
505        // Can't change the stream type after prepare
506        ALOGE("setAudioStream called in state %d", mCurrentState);
507        return INVALID_OPERATION;
508    }
509    // cache
510    mStreamType = type;
511    return OK;
512}
513
514status_t MediaPlayer::setLooping(int loop)
515{
516    ALOGV("MediaPlayer::setLooping");
517    Mutex::Autolock _l(mLock);
518    mLoop = (loop != 0);
519    if (mPlayer != 0) {
520        return mPlayer->setLooping(loop);
521    }
522    return OK;
523}
524
525bool MediaPlayer::isLooping() {
526    ALOGV("isLooping");
527    Mutex::Autolock _l(mLock);
528    if (mPlayer != 0) {
529        return mLoop;
530    }
531    ALOGV("isLooping: no active player");
532    return false;
533}
534
535status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
536{
537    ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
538    Mutex::Autolock _l(mLock);
539    mLeftVolume = leftVolume;
540    mRightVolume = rightVolume;
541    if (mPlayer != 0) {
542        return mPlayer->setVolume(leftVolume, rightVolume);
543    }
544    return OK;
545}
546
547status_t MediaPlayer::setAudioSessionId(int sessionId)
548{
549    ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
550    Mutex::Autolock _l(mLock);
551    if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
552        ALOGE("setAudioSessionId called in state %d", mCurrentState);
553        return INVALID_OPERATION;
554    }
555    if (sessionId < 0) {
556        return BAD_VALUE;
557    }
558    if (sessionId != mAudioSessionId) {
559        AudioSystem::releaseAudioSessionId(mAudioSessionId);
560        AudioSystem::acquireAudioSessionId(sessionId);
561        mAudioSessionId = sessionId;
562    }
563    return NO_ERROR;
564}
565
566int MediaPlayer::getAudioSessionId()
567{
568    Mutex::Autolock _l(mLock);
569    return mAudioSessionId;
570}
571
572status_t MediaPlayer::setAuxEffectSendLevel(float level)
573{
574    ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
575    Mutex::Autolock _l(mLock);
576    mSendLevel = level;
577    if (mPlayer != 0) {
578        return mPlayer->setAuxEffectSendLevel(level);
579    }
580    return OK;
581}
582
583status_t MediaPlayer::attachAuxEffect(int effectId)
584{
585    ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
586    Mutex::Autolock _l(mLock);
587    if (mPlayer == 0 ||
588        (mCurrentState & MEDIA_PLAYER_IDLE) ||
589        (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
590        ALOGE("attachAuxEffect called in state %d", mCurrentState);
591        return INVALID_OPERATION;
592    }
593
594    return mPlayer->attachAuxEffect(effectId);
595}
596
597status_t MediaPlayer::setParameter(int key, const Parcel& request)
598{
599    ALOGV("MediaPlayer::setParameter(%d)", key);
600    Mutex::Autolock _l(mLock);
601    if (mPlayer != NULL) {
602        return  mPlayer->setParameter(key, request);
603    }
604    ALOGV("setParameter: no active player");
605    return INVALID_OPERATION;
606}
607
608status_t MediaPlayer::getParameter(int key, Parcel *reply)
609{
610    ALOGV("MediaPlayer::getParameter(%d)", key);
611    Mutex::Autolock _l(mLock);
612    if (mPlayer != NULL) {
613        return  mPlayer->getParameter(key, reply);
614    }
615    ALOGV("getParameter: no active player");
616    return INVALID_OPERATION;
617}
618
619status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
620                                            uint16_t port) {
621    ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
622            addrString ? addrString : "(null)", port);
623
624    Mutex::Autolock _l(mLock);
625    if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
626        return INVALID_OPERATION;
627
628    if (NULL == addrString) {
629        mRetransmitEndpointValid = false;
630        return OK;
631    }
632
633    struct in_addr saddr;
634    if(!inet_aton(addrString, &saddr)) {
635        return BAD_VALUE;
636    }
637
638    memset(&mRetransmitEndpoint, 0, sizeof(&mRetransmitEndpoint));
639    mRetransmitEndpoint.sin_family = AF_INET;
640    mRetransmitEndpoint.sin_addr   = saddr;
641    mRetransmitEndpoint.sin_port   = htons(port);
642    mRetransmitEndpointValid       = true;
643
644    return OK;
645}
646
647void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
648{
649    ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
650    bool send = true;
651    bool locked = false;
652
653    // TODO: In the future, we might be on the same thread if the app is
654    // running in the same process as the media server. In that case,
655    // this will deadlock.
656    //
657    // The threadId hack below works around this for the care of prepare
658    // and seekTo within the same process.
659    // FIXME: Remember, this is a hack, it's not even a hack that is applied
660    // consistently for all use-cases, this needs to be revisited.
661    if (mLockThreadId != getThreadId()) {
662        mLock.lock();
663        locked = true;
664    }
665
666    // Allows calls from JNI in idle state to notify errors
667    if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
668        ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
669        if (locked) mLock.unlock();   // release the lock when done.
670        return;
671    }
672
673    switch (msg) {
674    case MEDIA_NOP: // interface test message
675        break;
676    case MEDIA_PREPARED:
677        ALOGV("prepared");
678        mCurrentState = MEDIA_PLAYER_PREPARED;
679        if (mPrepareSync) {
680            ALOGV("signal application thread");
681            mPrepareSync = false;
682            mPrepareStatus = NO_ERROR;
683            mSignal.signal();
684        }
685        break;
686    case MEDIA_PLAYBACK_COMPLETE:
687        ALOGV("playback complete");
688        if (mCurrentState == MEDIA_PLAYER_IDLE) {
689            ALOGE("playback complete in idle state");
690        }
691        if (!mLoop) {
692            mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
693        }
694        break;
695    case MEDIA_ERROR:
696        // Always log errors.
697        // ext1: Media framework error code.
698        // ext2: Implementation dependant error code.
699        ALOGE("error (%d, %d)", ext1, ext2);
700        mCurrentState = MEDIA_PLAYER_STATE_ERROR;
701        if (mPrepareSync)
702        {
703            ALOGV("signal application thread");
704            mPrepareSync = false;
705            mPrepareStatus = ext1;
706            mSignal.signal();
707            send = false;
708        }
709        break;
710    case MEDIA_INFO:
711        // ext1: Media framework error code.
712        // ext2: Implementation dependant error code.
713        if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
714            ALOGW("info/warning (%d, %d)", ext1, ext2);
715        }
716        break;
717    case MEDIA_SEEK_COMPLETE:
718        ALOGV("Received seek complete");
719        if (mSeekPosition != mCurrentPosition) {
720            ALOGV("Executing queued seekTo(%d)", mSeekPosition);
721            mSeekPosition = -1;
722            seekTo_l(mCurrentPosition);
723        }
724        else {
725            ALOGV("All seeks complete - return to regularly scheduled program");
726            mCurrentPosition = mSeekPosition = -1;
727        }
728        break;
729    case MEDIA_BUFFERING_UPDATE:
730        ALOGV("buffering %d", ext1);
731        break;
732    case MEDIA_SET_VIDEO_SIZE:
733        ALOGV("New video size %d x %d", ext1, ext2);
734        mVideoWidth = ext1;
735        mVideoHeight = ext2;
736        break;
737    case MEDIA_TIMED_TEXT:
738        ALOGV("Received timed text message");
739        break;
740    default:
741        ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
742        break;
743    }
744
745    sp<MediaPlayerListener> listener = mListener;
746    if (locked) mLock.unlock();
747
748    // this prevents re-entrant calls into client code
749    if ((listener != 0) && send) {
750        Mutex::Autolock _l(mNotifyLock);
751        ALOGV("callback application");
752        listener->notify(msg, ext1, ext2, obj);
753        ALOGV("back from callback");
754    }
755}
756
757/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
758{
759    ALOGV("decode(%s)", url);
760    sp<IMemory> p;
761    const sp<IMediaPlayerService>& service = getMediaPlayerService();
762    if (service != 0) {
763        p = service->decode(url, pSampleRate, pNumChannels, pFormat);
764    } else {
765        ALOGE("Unable to locate media service");
766    }
767    return p;
768
769}
770
771void MediaPlayer::died()
772{
773    ALOGV("died");
774    notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
775}
776
777/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
778{
779    ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
780    sp<IMemory> p;
781    const sp<IMediaPlayerService>& service = getMediaPlayerService();
782    if (service != 0) {
783        p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
784    } else {
785        ALOGE("Unable to locate media service");
786    }
787    return p;
788
789}
790
791status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
792    if (mPlayer == NULL) {
793        return NO_INIT;
794    }
795    return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
796}
797
798}; // namespace android
799