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