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 || (mCurrentState & MEDIA_PLAYER_STOPPED)) {
399        return INVALID_OPERATION;
400    }
401
402    if (rate.mSpeed != 0.f && !(mCurrentState & MEDIA_PLAYER_STARTED)
403            && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
404                    | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
405        mPlayer->setLooping(mLoop);
406        mPlayer->setVolume(mLeftVolume, mRightVolume);
407        mPlayer->setAuxEffectSendLevel(mSendLevel);
408    }
409
410    status_t err = mPlayer->setPlaybackSettings(rate);
411    if (err == OK) {
412        if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER_STARTED) {
413            mCurrentState = MEDIA_PLAYER_PAUSED;
414        } else if (rate.mSpeed != 0.f
415                && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
416                    | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
417            mCurrentState = MEDIA_PLAYER_STARTED;
418        }
419    }
420    return err;
421}
422
423status_t MediaPlayer::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
424{
425    Mutex::Autolock _l(mLock);
426    if (mPlayer == 0) return INVALID_OPERATION;
427    return mPlayer->getPlaybackSettings(rate);
428}
429
430status_t MediaPlayer::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
431{
432    ALOGV("setSyncSettings: %u %u %f %f",
433            sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
434    Mutex::Autolock _l(mLock);
435    if (mPlayer == 0) return INVALID_OPERATION;
436    return mPlayer->setSyncSettings(sync, videoFpsHint);
437}
438
439status_t MediaPlayer::getSyncSettings(
440        AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
441{
442    Mutex::Autolock _l(mLock);
443    if (mPlayer == 0) return INVALID_OPERATION;
444    return mPlayer->getSyncSettings(sync, videoFps);
445}
446
447status_t MediaPlayer::getVideoWidth(int *w)
448{
449    ALOGV("getVideoWidth");
450    Mutex::Autolock _l(mLock);
451    if (mPlayer == 0) return INVALID_OPERATION;
452    *w = mVideoWidth;
453    return NO_ERROR;
454}
455
456status_t MediaPlayer::getVideoHeight(int *h)
457{
458    ALOGV("getVideoHeight");
459    Mutex::Autolock _l(mLock);
460    if (mPlayer == 0) return INVALID_OPERATION;
461    *h = mVideoHeight;
462    return NO_ERROR;
463}
464
465status_t MediaPlayer::getCurrentPosition(int *msec)
466{
467    ALOGV("getCurrentPosition");
468    Mutex::Autolock _l(mLock);
469    if (mPlayer != 0) {
470        if (mCurrentPosition >= 0) {
471            ALOGV("Using cached seek position: %d", mCurrentPosition);
472            *msec = mCurrentPosition;
473            return NO_ERROR;
474        }
475        return mPlayer->getCurrentPosition(msec);
476    }
477    return INVALID_OPERATION;
478}
479
480status_t MediaPlayer::getDuration_l(int *msec)
481{
482    ALOGV("getDuration_l");
483    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
484            MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
485    if (mPlayer != 0 && isValidState) {
486        int durationMs;
487        status_t ret = mPlayer->getDuration(&durationMs);
488
489        if (ret != OK) {
490            // Do not enter error state just because no duration was available.
491            durationMs = -1;
492            ret = OK;
493        }
494
495        if (msec) {
496            *msec = durationMs;
497        }
498        return ret;
499    }
500    ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
501            mPlayer.get(), mCurrentState);
502    return INVALID_OPERATION;
503}
504
505status_t MediaPlayer::getDuration(int *msec)
506{
507    Mutex::Autolock _l(mLock);
508    return getDuration_l(msec);
509}
510
511status_t MediaPlayer::seekTo_l(int msec)
512{
513    ALOGV("seekTo %d", msec);
514    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
515            MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
516        if ( msec < 0 ) {
517            ALOGW("Attempt to seek to invalid position: %d", msec);
518            msec = 0;
519        }
520
521        int durationMs;
522        status_t err = mPlayer->getDuration(&durationMs);
523
524        if (err != OK) {
525            ALOGW("Stream has no duration and is therefore not seekable.");
526            return err;
527        }
528
529        if (msec > durationMs) {
530            ALOGW("Attempt to seek to past end of file: request = %d, "
531                  "durationMs = %d",
532                  msec,
533                  durationMs);
534
535            msec = durationMs;
536        }
537
538        // cache duration
539        mCurrentPosition = msec;
540        if (mSeekPosition < 0) {
541            mSeekPosition = msec;
542            return mPlayer->seekTo(msec);
543        }
544        else {
545            ALOGV("Seek in progress - queue up seekTo[%d]", msec);
546            return NO_ERROR;
547        }
548    }
549    ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
550            mCurrentState);
551    return INVALID_OPERATION;
552}
553
554status_t MediaPlayer::seekTo(int msec)
555{
556    mLockThreadId = getThreadId();
557    Mutex::Autolock _l(mLock);
558    status_t result = seekTo_l(msec);
559    mLockThreadId = 0;
560
561    return result;
562}
563
564status_t MediaPlayer::reset_l()
565{
566    mLoop = false;
567    if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
568    mPrepareSync = false;
569    if (mPlayer != 0) {
570        status_t ret = mPlayer->reset();
571        if (ret != NO_ERROR) {
572            ALOGE("reset() failed with return code (%d)", ret);
573            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
574        } else {
575            mPlayer->disconnect();
576            mCurrentState = MEDIA_PLAYER_IDLE;
577        }
578        // setDataSource has to be called again to create a
579        // new mediaplayer.
580        mPlayer = 0;
581        return ret;
582    }
583    clear_l();
584    return NO_ERROR;
585}
586
587status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
588    Mutex::Autolock _l(mLock);
589
590    if (player == NULL) {
591        return UNKNOWN_ERROR;
592    }
593
594    if (mRetransmitEndpointValid) {
595        return player->setRetransmitEndpoint(&mRetransmitEndpoint);
596    }
597
598    return OK;
599}
600
601status_t MediaPlayer::reset()
602{
603    ALOGV("reset");
604    Mutex::Autolock _l(mLock);
605    return reset_l();
606}
607
608status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
609{
610    ALOGV("MediaPlayer::setAudioStreamType");
611    Mutex::Autolock _l(mLock);
612    if (mStreamType == type) return NO_ERROR;
613    if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
614                MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
615        // Can't change the stream type after prepare
616        ALOGE("setAudioStream called in state %d", mCurrentState);
617        return INVALID_OPERATION;
618    }
619    // cache
620    mStreamType = type;
621    return OK;
622}
623
624status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type)
625{
626    ALOGV("getAudioStreamType");
627    Mutex::Autolock _l(mLock);
628    *type = mStreamType;
629    return OK;
630}
631
632status_t MediaPlayer::setLooping(int loop)
633{
634    ALOGV("MediaPlayer::setLooping");
635    Mutex::Autolock _l(mLock);
636    mLoop = (loop != 0);
637    if (mPlayer != 0) {
638        return mPlayer->setLooping(loop);
639    }
640    return OK;
641}
642
643bool MediaPlayer::isLooping() {
644    ALOGV("isLooping");
645    Mutex::Autolock _l(mLock);
646    if (mPlayer != 0) {
647        return mLoop;
648    }
649    ALOGV("isLooping: no active player");
650    return false;
651}
652
653status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
654{
655    ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
656    Mutex::Autolock _l(mLock);
657    mLeftVolume = leftVolume;
658    mRightVolume = rightVolume;
659    if (mPlayer != 0) {
660        return mPlayer->setVolume(leftVolume, rightVolume);
661    }
662    return OK;
663}
664
665status_t MediaPlayer::setAudioSessionId(audio_session_t sessionId)
666{
667    ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
668    Mutex::Autolock _l(mLock);
669    if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
670        ALOGE("setAudioSessionId called in state %d", mCurrentState);
671        return INVALID_OPERATION;
672    }
673    if (sessionId < 0) {
674        return BAD_VALUE;
675    }
676    if (sessionId != mAudioSessionId) {
677        AudioSystem::acquireAudioSessionId(sessionId, -1);
678        AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
679        mAudioSessionId = sessionId;
680    }
681    return NO_ERROR;
682}
683
684audio_session_t MediaPlayer::getAudioSessionId()
685{
686    Mutex::Autolock _l(mLock);
687    return mAudioSessionId;
688}
689
690status_t MediaPlayer::setAuxEffectSendLevel(float level)
691{
692    ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
693    Mutex::Autolock _l(mLock);
694    mSendLevel = level;
695    if (mPlayer != 0) {
696        return mPlayer->setAuxEffectSendLevel(level);
697    }
698    return OK;
699}
700
701status_t MediaPlayer::attachAuxEffect(int effectId)
702{
703    ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
704    Mutex::Autolock _l(mLock);
705    if (mPlayer == 0 ||
706        (mCurrentState & MEDIA_PLAYER_IDLE) ||
707        (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
708        ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
709        return INVALID_OPERATION;
710    }
711
712    return mPlayer->attachAuxEffect(effectId);
713}
714
715// always call with lock held
716status_t MediaPlayer::checkStateForKeySet_l(int key)
717{
718    switch(key) {
719    case KEY_PARAMETER_AUDIO_ATTRIBUTES:
720        if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
721                MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) {
722            // Can't change the audio attributes after prepare
723            ALOGE("trying to set audio attributes called in state %d", mCurrentState);
724            return INVALID_OPERATION;
725        }
726        break;
727    default:
728        // parameter doesn't require player state check
729        break;
730    }
731    return OK;
732}
733
734status_t MediaPlayer::setParameter(int key, const Parcel& request)
735{
736    ALOGV("MediaPlayer::setParameter(%d)", key);
737    status_t status = INVALID_OPERATION;
738    Mutex::Autolock _l(mLock);
739    if (checkStateForKeySet_l(key) != OK) {
740        return status;
741    }
742    switch (key) {
743    case KEY_PARAMETER_AUDIO_ATTRIBUTES:
744        // save the marshalled audio attributes
745        if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
746        mAudioAttributesParcel = new Parcel();
747        mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
748        status = OK;
749        break;
750    default:
751        ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
752        break;
753    }
754
755    if (mPlayer != NULL) {
756        status = mPlayer->setParameter(key, request);
757    }
758    return status;
759}
760
761status_t MediaPlayer::getParameter(int key, Parcel *reply)
762{
763    ALOGV("MediaPlayer::getParameter(%d)", key);
764    Mutex::Autolock _l(mLock);
765    if (mPlayer != NULL) {
766        return  mPlayer->getParameter(key, reply);
767    }
768    ALOGV("getParameter: no active player");
769    return INVALID_OPERATION;
770}
771
772status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
773                                            uint16_t port) {
774    ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
775            addrString ? addrString : "(null)", port);
776
777    Mutex::Autolock _l(mLock);
778    if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
779        return INVALID_OPERATION;
780
781    if (NULL == addrString) {
782        mRetransmitEndpointValid = false;
783        return OK;
784    }
785
786    struct in_addr saddr;
787    if(!inet_aton(addrString, &saddr)) {
788        return BAD_VALUE;
789    }
790
791    memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
792    mRetransmitEndpoint.sin_family = AF_INET;
793    mRetransmitEndpoint.sin_addr   = saddr;
794    mRetransmitEndpoint.sin_port   = htons(port);
795    mRetransmitEndpointValid       = true;
796
797    return OK;
798}
799
800void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
801{
802    ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
803    bool send = true;
804    bool locked = false;
805
806    // TODO: In the future, we might be on the same thread if the app is
807    // running in the same process as the media server. In that case,
808    // this will deadlock.
809    //
810    // The threadId hack below works around this for the care of prepare,
811    // seekTo and start within the same process.
812    // FIXME: Remember, this is a hack, it's not even a hack that is applied
813    // consistently for all use-cases, this needs to be revisited.
814    if (mLockThreadId != getThreadId()) {
815        mLock.lock();
816        locked = true;
817    }
818
819    // Allows calls from JNI in idle state to notify errors
820    if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
821        ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
822        if (locked) mLock.unlock();   // release the lock when done.
823        return;
824    }
825
826    switch (msg) {
827    case MEDIA_NOP: // interface test message
828        break;
829    case MEDIA_PREPARED:
830        ALOGV("prepared");
831        mCurrentState = MEDIA_PLAYER_PREPARED;
832        if (mPrepareSync) {
833            ALOGV("signal application thread");
834            mPrepareSync = false;
835            mPrepareStatus = NO_ERROR;
836            mSignal.signal();
837        }
838        break;
839    case MEDIA_PLAYBACK_COMPLETE:
840        ALOGV("playback complete");
841        if (mCurrentState == MEDIA_PLAYER_IDLE) {
842            ALOGE("playback complete in idle state");
843        }
844        if (!mLoop) {
845            mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
846        }
847        break;
848    case MEDIA_ERROR:
849        // Always log errors.
850        // ext1: Media framework error code.
851        // ext2: Implementation dependant error code.
852        ALOGE("error (%d, %d)", ext1, ext2);
853        mCurrentState = MEDIA_PLAYER_STATE_ERROR;
854        if (mPrepareSync)
855        {
856            ALOGV("signal application thread");
857            mPrepareSync = false;
858            mPrepareStatus = ext1;
859            mSignal.signal();
860            send = false;
861        }
862        break;
863    case MEDIA_INFO:
864        // ext1: Media framework error code.
865        // ext2: Implementation dependant error code.
866        if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
867            ALOGW("info/warning (%d, %d)", ext1, ext2);
868        }
869        break;
870    case MEDIA_SEEK_COMPLETE:
871        ALOGV("Received seek complete");
872        if (mSeekPosition != mCurrentPosition) {
873            ALOGV("Executing queued seekTo(%d)", mSeekPosition);
874            mSeekPosition = -1;
875            seekTo_l(mCurrentPosition);
876        }
877        else {
878            ALOGV("All seeks complete - return to regularly scheduled program");
879            mCurrentPosition = mSeekPosition = -1;
880        }
881        break;
882    case MEDIA_BUFFERING_UPDATE:
883        ALOGV("buffering %d", ext1);
884        break;
885    case MEDIA_SET_VIDEO_SIZE:
886        ALOGV("New video size %d x %d", ext1, ext2);
887        mVideoWidth = ext1;
888        mVideoHeight = ext2;
889        break;
890    case MEDIA_TIMED_TEXT:
891        ALOGV("Received timed text message");
892        break;
893    case MEDIA_SUBTITLE_DATA:
894        ALOGV("Received subtitle data message");
895        break;
896    case MEDIA_META_DATA:
897        ALOGV("Received timed metadata message");
898        break;
899    default:
900        ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
901        break;
902    }
903
904    sp<MediaPlayerListener> listener = mListener;
905    if (locked) mLock.unlock();
906
907    // this prevents re-entrant calls into client code
908    if ((listener != 0) && send) {
909        Mutex::Autolock _l(mNotifyLock);
910        ALOGV("callback application");
911        listener->notify(msg, ext1, ext2, obj);
912        ALOGV("back from callback");
913    }
914}
915
916void MediaPlayer::died()
917{
918    ALOGV("died");
919    notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
920}
921
922status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
923    Mutex::Autolock _l(mLock);
924    if (mPlayer == NULL) {
925        return NO_INIT;
926    }
927
928    if (next != NULL && !(next->mCurrentState &
929            (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
930        ALOGE("next player is not prepared");
931        return INVALID_OPERATION;
932    }
933
934    return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
935}
936
937} // namespace android
938