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