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