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