blob: 7504787a4f86a4b8757fe4b3c0134d53d9ae1d1b [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002**
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
Hassan Shojaniacefac142017-02-06 21:02:02 -080019#define LOG_TAG "MediaPlayerNative"
Marco Nelissendab79b32019-11-18 08:25:47 -080020#include <utils/Log.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080021
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080022#include <fcntl.h>
Mark Salyzyn34fb2962014-06-18 16:30:56 -070023#include <inttypes.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080028
Marco Nelissendab79b32019-11-18 08:25:47 -080029#include <android/IDataSource.h>
Mathias Agopian75624082009-05-19 19:08:10 -070030#include <binder/IPCThreadState.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080031#include <media/mediaplayer.h>
Lajos Molnar3a474aa2015-04-24 17:10:07 -070032#include <media/AudioResamplerPublic.h>
Glenn Kastena3f1fa32012-01-18 14:54:46 -080033#include <media/AudioSystem.h>
Lajos Molnar3a474aa2015-04-24 17:10:07 -070034#include <media/AVSyncSettings.h>
Andreas Huber2db84552010-01-28 11:19:57 -080035#include <utils/KeyedVector.h>
36#include <utils/String8.h>
Dima Zavin64760242011-05-11 14:15:23 -070037#include <system/audio.h>
Jamie Gennis61c7ef52011-07-13 12:59:34 -070038#include <system/window.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070039
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080040namespace android {
41
Ivan Lozano8cf3a072017-08-09 09:01:33 -070042using media::VolumeShaper;
Philip P. Moltmannbda45752020-07-17 16:41:18 -070043using media::permission::Identity;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070044
Philip P. Moltmannbda45752020-07-17 16:41:18 -070045MediaPlayer::MediaPlayer(const Identity& identity) : mIdentity(identity)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080046{
Steve Block3856b092011-10-20 11:56:00 +010047 ALOGV("constructor");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080048 mListener = NULL;
49 mCookie = NULL;
Dima Zavinfce7a472011-04-19 22:30:36 -070050 mStreamType = AUDIO_STREAM_MUSIC;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -070051 mAudioAttributesParcel = NULL;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080052 mCurrentPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -080053 mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080054 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -080055 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080056 mCurrentState = MEDIA_PLAYER_IDLE;
57 mPrepareSync = false;
58 mPrepareStatus = NO_ERROR;
59 mLoop = false;
60 mLeftVolume = mRightVolume = 1.0;
61 mVideoWidth = mVideoHeight = 0;
Jason Sams1af452f2009-03-24 18:45:22 -070062 mLockThreadId = 0;
Glenn Kastend848eb42016-03-08 13:42:11 -080063 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Andy Hung8b0bfd92019-12-23 13:11:11 -080064 AudioSystem::acquireAudioSessionId(mAudioSessionId, (pid_t)-1, (uid_t)-1); // always in client.
Eric Laurent8c563ed2010-10-07 18:23:03 -070065 mSendLevel = 0;
John Grossmanc795b642012-02-22 15:38:35 -080066 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080067}
68
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080069MediaPlayer::~MediaPlayer()
70{
Steve Block3856b092011-10-20 11:56:00 +010071 ALOGV("destructor");
Jean-Michel Trivi640adb32014-09-05 11:20:11 -070072 if (mAudioAttributesParcel != NULL) {
73 delete mAudioAttributesParcel;
74 mAudioAttributesParcel = NULL;
75 }
Andy Hung8b0bfd92019-12-23 13:11:11 -080076 AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080077 disconnect();
78 IPCThreadState::self()->flushCommands();
79}
80
81void MediaPlayer::disconnect()
82{
Steve Block3856b092011-10-20 11:56:00 +010083 ALOGV("disconnect");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080084 sp<IMediaPlayer> p;
85 {
86 Mutex::Autolock _l(mLock);
87 p = mPlayer;
88 mPlayer.clear();
89 }
90
91 if (p != 0) {
92 p->disconnect();
93 }
94}
95
96// always call with lock held
97void MediaPlayer::clear_l()
98{
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080099 mCurrentPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800100 mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800101 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800102 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800103 mVideoWidth = mVideoHeight = 0;
John Grossmanc795b642012-02-22 15:38:35 -0800104 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800105}
106
107status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
108{
Steve Block3856b092011-10-20 11:56:00 +0100109 ALOGV("setListener");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800110 Mutex::Autolock _l(mLock);
111 mListener = listener;
112 return NO_ERROR;
113}
114
115
Dave Burked681bbb2011-08-30 14:39:17 +0100116status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800117{
118 status_t err = UNKNOWN_ERROR;
119 sp<IMediaPlayer> p;
120 { // scope for the lock
121 Mutex::Autolock _l(mLock);
122
Marco Nelissen83ff1432010-03-10 10:53:16 -0800123 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
124 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
Steve Block29357bc2012-01-06 19:20:56 +0000125 ALOGE("attachNewPlayer called in state %d", mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800126 return INVALID_OPERATION;
127 }
128
129 clear_l();
130 p = mPlayer;
131 mPlayer = player;
132 if (player != 0) {
133 mCurrentState = MEDIA_PLAYER_INITIALIZED;
134 err = NO_ERROR;
135 } else {
Masaki Muranakaf65fa172013-06-06 09:36:34 +0000136 ALOGE("Unable to create media player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800137 }
138 }
139
140 if (p != 0) {
141 p->disconnect();
142 }
143
144 return err;
145}
146
Andreas Huber2db84552010-01-28 11:19:57 -0800147status_t MediaPlayer::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800148 const sp<IMediaHTTPService> &httpService,
Andreas Huber2db84552010-01-28 11:19:57 -0800149 const char *url, const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800150{
Steve Block3856b092011-10-20 11:56:00 +0100151 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800152 status_t err = BAD_VALUE;
153 if (url != NULL) {
Marco Nelissenfc908d02016-06-07 12:26:43 -0700154 const sp<IMediaPlayerService> service(getMediaPlayerService());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800155 if (service != 0) {
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700156 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mIdentity));
John Grossmanc795b642012-02-22 15:38:35 -0800157 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
Andreas Huber1b86fe02014-01-29 11:13:26 -0800158 (NO_ERROR != player->setDataSource(httpService, url, headers))) {
Dave Burke06620672011-09-06 20:39:47 +0100159 player.clear();
Dave Burked681bbb2011-08-30 14:39:17 +0100160 }
Dave Burke06620672011-09-06 20:39:47 +0100161 err = attachNewPlayer(player);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800162 }
163 }
164 return err;
165}
166
167status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
168{
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700169 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800170 status_t err = UNKNOWN_ERROR;
Marco Nelissenfc908d02016-06-07 12:26:43 -0700171 const sp<IMediaPlayerService> service(getMediaPlayerService());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800172 if (service != 0) {
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700173 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mIdentity));
John Grossmanc795b642012-02-22 15:38:35 -0800174 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
175 (NO_ERROR != player->setDataSource(fd, offset, length))) {
Dave Burke06620672011-09-06 20:39:47 +0100176 player.clear();
Dave Burked681bbb2011-08-30 14:39:17 +0100177 }
Dave Burke06620672011-09-06 20:39:47 +0100178 err = attachNewPlayer(player);
Dave Burked681bbb2011-08-30 14:39:17 +0100179 }
180 return err;
181}
182
Chris Watkins99f31602015-03-20 13:06:33 -0700183status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
184{
185 ALOGV("setDataSource(IDataSource)");
186 status_t err = UNKNOWN_ERROR;
Marco Nelissenfc908d02016-06-07 12:26:43 -0700187 const sp<IMediaPlayerService> service(getMediaPlayerService());
Chris Watkins99f31602015-03-20 13:06:33 -0700188 if (service != 0) {
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700189 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mIdentity));
Chris Watkins99f31602015-03-20 13:06:33 -0700190 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
191 (NO_ERROR != player->setDataSource(source))) {
192 player.clear();
193 }
194 err = attachNewPlayer(player);
195 }
196 return err;
197}
198
Byeongjo Park28225ab2019-01-24 20:31:19 +0900199status_t MediaPlayer::setDataSource(const String8& rtpParams)
200{
201 ALOGV("setDataSource(rtpParams)");
202 status_t err = UNKNOWN_ERROR;
203 const sp<IMediaPlayerService> service(getMediaPlayerService());
204 if (service != 0) {
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700205 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mIdentity));
Byeongjo Park28225ab2019-01-24 20:31:19 +0900206 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
207 (NO_ERROR != player->setDataSource(rtpParams))) {
208 player.clear();
209 }
210 err = attachNewPlayer(player);
211 }
212 return err;
213}
214
Nicolas Catania1d187f12009-05-12 23:25:55 -0700215status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
216{
217 Mutex::Autolock _l(mLock);
Nicolas Catania40234932010-03-10 10:41:04 -0800218 const bool hasBeenInitialized =
219 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
220 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
221 if ((mPlayer != NULL) && hasBeenInitialized) {
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700222 ALOGV("invoke %zu", request.dataSize());
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700223 return mPlayer->invoke(request, reply);
Nicolas Catania1d187f12009-05-12 23:25:55 -0700224 }
Wei Jia848ebc62016-03-23 14:06:46 -0700225 ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Nicolas Catania1d187f12009-05-12 23:25:55 -0700226 return INVALID_OPERATION;
227}
228
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700229status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
230{
Steve Blockb8a80522011-12-20 16:23:08 +0000231 ALOGD("setMetadataFilter");
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700232 Mutex::Autolock lock(mLock);
233 if (mPlayer == NULL) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700234 return NO_INIT;
235 }
236 return mPlayer->setMetadataFilter(filter);
237}
Nicolas Catania1d187f12009-05-12 23:25:55 -0700238
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700239status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
240{
Steve Blockb8a80522011-12-20 16:23:08 +0000241 ALOGD("getMetadata");
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700242 Mutex::Autolock lock(mLock);
243 if (mPlayer == NULL) {
244 return NO_INIT;
245 }
246 return mPlayer->getMetadata(update_only, apply_filter, metadata);
247}
248
Glenn Kasten11731182011-02-08 17:26:17 -0800249status_t MediaPlayer::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800250 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800251{
Steve Block3856b092011-10-20 11:56:00 +0100252 ALOGV("setVideoSurfaceTexture");
Glenn Kasten11731182011-02-08 17:26:17 -0800253 Mutex::Autolock _l(mLock);
254 if (mPlayer == 0) return NO_INIT;
Andy McFadden484566c2012-12-18 09:46:54 -0800255 return mPlayer->setVideoSurfaceTexture(bufferProducer);
Glenn Kasten11731182011-02-08 17:26:17 -0800256}
257
Wei Jiaed320862017-01-18 14:03:40 -0800258status_t MediaPlayer::getBufferingSettings(BufferingSettings* buffering /* nonnull */)
259{
260 ALOGV("getBufferingSettings");
261
262 Mutex::Autolock _l(mLock);
263 if (mPlayer == 0) {
264 return NO_INIT;
265 }
Wei Jia9bb38032017-03-23 18:00:38 -0700266 return mPlayer->getBufferingSettings(buffering);
Wei Jiaed320862017-01-18 14:03:40 -0800267}
268
Wei Jiadc6f3402017-01-09 15:04:18 -0800269status_t MediaPlayer::setBufferingSettings(const BufferingSettings& buffering)
270{
271 ALOGV("setBufferingSettings");
272
273 Mutex::Autolock _l(mLock);
274 if (mPlayer == 0) {
275 return NO_INIT;
276 }
Wei Jia9bb38032017-03-23 18:00:38 -0700277 return mPlayer->setBufferingSettings(buffering);
Wei Jiadc6f3402017-01-09 15:04:18 -0800278}
279
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800280// must call with lock held
281status_t MediaPlayer::prepareAsync_l()
282{
Glenn Kastenb187de12014-12-30 08:18:15 -0800283 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700284 if (mAudioAttributesParcel != NULL) {
285 mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
Eric Laurent43562692015-07-15 16:49:07 -0700286 } else {
287 mPlayer->setAudioStreamType(mStreamType);
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700288 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800289 mCurrentState = MEDIA_PLAYER_PREPARING;
290 return mPlayer->prepareAsync();
291 }
Wei Jia848ebc62016-03-23 14:06:46 -0700292 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800293 return INVALID_OPERATION;
294}
295
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700296// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
297// one defined in the Android framework and one provided by the implementation
298// that generated the error. The sync version of prepare returns only 1 error
299// code.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800300status_t MediaPlayer::prepare()
301{
Steve Block3856b092011-10-20 11:56:00 +0100302 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800303 Mutex::Autolock _l(mLock);
Jason Sams1af452f2009-03-24 18:45:22 -0700304 mLockThreadId = getThreadId();
305 if (mPrepareSync) {
306 mLockThreadId = 0;
307 return -EALREADY;
308 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800309 mPrepareSync = true;
310 status_t ret = prepareAsync_l();
Jason Sams1af452f2009-03-24 18:45:22 -0700311 if (ret != NO_ERROR) {
312 mLockThreadId = 0;
313 return ret;
314 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800315
316 if (mPrepareSync) {
317 mSignal.wait(mLock); // wait for prepare done
318 mPrepareSync = false;
319 }
Steve Block3856b092011-10-20 11:56:00 +0100320 ALOGV("prepare complete - status=%d", mPrepareStatus);
Jason Sams1af452f2009-03-24 18:45:22 -0700321 mLockThreadId = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800322 return mPrepareStatus;
323}
324
325status_t MediaPlayer::prepareAsync()
326{
Steve Block3856b092011-10-20 11:56:00 +0100327 ALOGV("prepareAsync");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800328 Mutex::Autolock _l(mLock);
329 return prepareAsync_l();
330}
331
332status_t MediaPlayer::start()
333{
Steve Block3856b092011-10-20 11:56:00 +0100334 ALOGV("start");
Chong Zhangd88adb92014-07-23 11:43:46 -0700335
336 status_t ret = NO_ERROR;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800337 Mutex::Autolock _l(mLock);
Chong Zhangd88adb92014-07-23 11:43:46 -0700338
339 mLockThreadId = getThreadId();
340
341 if (mCurrentState & MEDIA_PLAYER_STARTED) {
342 ret = NO_ERROR;
343 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800344 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
345 mPlayer->setLooping(mLoop);
346 mPlayer->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -0700347 mPlayer->setAuxEffectSendLevel(mSendLevel);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800348 mCurrentState = MEDIA_PLAYER_STARTED;
Chong Zhangd88adb92014-07-23 11:43:46 -0700349 ret = mPlayer->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800350 if (ret != NO_ERROR) {
351 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
352 } else {
353 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
Steve Block3856b092011-10-20 11:56:00 +0100354 ALOGV("playback completed immediately following start()");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800355 }
356 }
Chong Zhangd88adb92014-07-23 11:43:46 -0700357 } else {
Wei Jia848ebc62016-03-23 14:06:46 -0700358 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
Chong Zhangd88adb92014-07-23 11:43:46 -0700359 ret = INVALID_OPERATION;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800360 }
Chong Zhangd88adb92014-07-23 11:43:46 -0700361
362 mLockThreadId = 0;
363
364 return ret;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800365}
366
367status_t MediaPlayer::stop()
368{
Steve Block3856b092011-10-20 11:56:00 +0100369 ALOGV("stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800370 Mutex::Autolock _l(mLock);
371 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
372 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
373 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
374 status_t ret = mPlayer->stop();
375 if (ret != NO_ERROR) {
376 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
377 } else {
378 mCurrentState = MEDIA_PLAYER_STOPPED;
379 }
380 return ret;
381 }
Wei Jia848ebc62016-03-23 14:06:46 -0700382 ALOGE("stop called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800383 return INVALID_OPERATION;
384}
385
386status_t MediaPlayer::pause()
387{
Steve Block3856b092011-10-20 11:56:00 +0100388 ALOGV("pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800389 Mutex::Autolock _l(mLock);
Marco Nelissen698f4762010-02-26 13:16:23 -0800390 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800391 return NO_ERROR;
392 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
393 status_t ret = mPlayer->pause();
394 if (ret != NO_ERROR) {
395 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
396 } else {
397 mCurrentState = MEDIA_PLAYER_PAUSED;
398 }
399 return ret;
400 }
Wei Jia848ebc62016-03-23 14:06:46 -0700401 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800402 return INVALID_OPERATION;
403}
404
405bool MediaPlayer::isPlaying()
406{
407 Mutex::Autolock _l(mLock);
408 if (mPlayer != 0) {
409 bool temp = false;
410 mPlayer->isPlaying(&temp);
Steve Block3856b092011-10-20 11:56:00 +0100411 ALOGV("isPlaying: %d", temp);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800412 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
Steve Block29357bc2012-01-06 19:20:56 +0000413 ALOGE("internal/external state mismatch corrected");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800414 mCurrentState = MEDIA_PLAYER_PAUSED;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700415 } else if ((mCurrentState & MEDIA_PLAYER_PAUSED) && temp) {
416 ALOGE("internal/external state mismatch corrected");
417 mCurrentState = MEDIA_PLAYER_STARTED;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800418 }
419 return temp;
420 }
Steve Block3856b092011-10-20 11:56:00 +0100421 ALOGV("isPlaying: no active player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800422 return false;
423}
424
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700425status_t MediaPlayer::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -0800426{
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700427 ALOGV("setPlaybackSettings: %f %f %d %d",
428 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
429 // Negative speed and pitch does not make sense. Further validation will
430 // be done by the respective mediaplayers.
431 if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
Wei Jia98160162015-02-04 17:01:11 -0800432 return BAD_VALUE;
433 }
434 Mutex::Autolock _l(mLock);
Wei Jia5af6a9b2016-06-16 12:07:26 -0700435 if (mPlayer == 0 || (mCurrentState & MEDIA_PLAYER_STOPPED)) {
436 return INVALID_OPERATION;
437 }
Wei Jia5be109f2016-06-10 16:15:07 -0700438
439 if (rate.mSpeed != 0.f && !(mCurrentState & MEDIA_PLAYER_STARTED)
440 && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
441 | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
442 mPlayer->setLooping(mLoop);
443 mPlayer->setVolume(mLeftVolume, mRightVolume);
444 mPlayer->setAuxEffectSendLevel(mSendLevel);
445 }
446
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700447 status_t err = mPlayer->setPlaybackSettings(rate);
448 if (err == OK) {
449 if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER_STARTED) {
450 mCurrentState = MEDIA_PLAYER_PAUSED;
Wei Jia5be109f2016-06-10 16:15:07 -0700451 } else if (rate.mSpeed != 0.f
452 && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
453 | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700454 mCurrentState = MEDIA_PLAYER_STARTED;
Wei Jia98160162015-02-04 17:01:11 -0800455 }
Wei Jia98160162015-02-04 17:01:11 -0800456 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700457 return err;
458}
459
460status_t MediaPlayer::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
461{
462 Mutex::Autolock _l(mLock);
463 if (mPlayer == 0) return INVALID_OPERATION;
464 return mPlayer->getPlaybackSettings(rate);
465}
466
467status_t MediaPlayer::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
468{
469 ALOGV("setSyncSettings: %u %u %f %f",
470 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
471 Mutex::Autolock _l(mLock);
472 if (mPlayer == 0) return INVALID_OPERATION;
473 return mPlayer->setSyncSettings(sync, videoFpsHint);
474}
475
476status_t MediaPlayer::getSyncSettings(
477 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
478{
479 Mutex::Autolock _l(mLock);
480 if (mPlayer == 0) return INVALID_OPERATION;
481 return mPlayer->getSyncSettings(sync, videoFps);
Wei Jia98160162015-02-04 17:01:11 -0800482}
483
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800484status_t MediaPlayer::getVideoWidth(int *w)
485{
Steve Block3856b092011-10-20 11:56:00 +0100486 ALOGV("getVideoWidth");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800487 Mutex::Autolock _l(mLock);
488 if (mPlayer == 0) return INVALID_OPERATION;
489 *w = mVideoWidth;
490 return NO_ERROR;
491}
492
493status_t MediaPlayer::getVideoHeight(int *h)
494{
Steve Block3856b092011-10-20 11:56:00 +0100495 ALOGV("getVideoHeight");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800496 Mutex::Autolock _l(mLock);
497 if (mPlayer == 0) return INVALID_OPERATION;
498 *h = mVideoHeight;
499 return NO_ERROR;
500}
501
502status_t MediaPlayer::getCurrentPosition(int *msec)
503{
Steve Block3856b092011-10-20 11:56:00 +0100504 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800505 Mutex::Autolock _l(mLock);
506 if (mPlayer != 0) {
507 if (mCurrentPosition >= 0) {
Steve Block3856b092011-10-20 11:56:00 +0100508 ALOGV("Using cached seek position: %d", mCurrentPosition);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800509 *msec = mCurrentPosition;
510 return NO_ERROR;
511 }
512 return mPlayer->getCurrentPosition(msec);
513 }
514 return INVALID_OPERATION;
515}
516
517status_t MediaPlayer::getDuration_l(int *msec)
518{
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800519 ALOGV("getDuration_l");
Glenn Kastenb187de12014-12-30 08:18:15 -0800520 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
521 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800522 if (mPlayer != 0 && isValidState) {
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800523 int durationMs;
524 status_t ret = mPlayer->getDuration(&durationMs);
Andreas Huber20702542013-04-11 11:07:55 -0700525
526 if (ret != OK) {
527 // Do not enter error state just because no duration was available.
528 durationMs = -1;
529 ret = OK;
530 }
531
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800532 if (msec) {
533 *msec = durationMs;
534 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800535 return ret;
536 }
Wei Jia848ebc62016-03-23 14:06:46 -0700537 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
538 mPlayer.get(), mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800539 return INVALID_OPERATION;
540}
541
542status_t MediaPlayer::getDuration(int *msec)
543{
544 Mutex::Autolock _l(mLock);
545 return getDuration_l(msec);
546}
547
Wei Jiac5de0912016-11-18 10:22:14 -0800548status_t MediaPlayer::seekTo_l(int msec, MediaPlayerSeekMode mode)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800549{
Wei Jiac5de0912016-11-18 10:22:14 -0800550 ALOGV("seekTo (%d, %d)", msec, mode);
Glenn Kastenb187de12014-12-30 08:18:15 -0800551 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
552 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800553 if ( msec < 0 ) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000554 ALOGW("Attempt to seek to invalid position: %d", msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800555 msec = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800556 }
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800557
558 int durationMs;
559 status_t err = mPlayer->getDuration(&durationMs);
560
561 if (err != OK) {
562 ALOGW("Stream has no duration and is therefore not seekable.");
563 return err;
564 }
565
566 if (msec > durationMs) {
567 ALOGW("Attempt to seek to past end of file: request = %d, "
568 "durationMs = %d",
569 msec,
570 durationMs);
571
572 msec = durationMs;
573 }
574
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800575 // cache duration
576 mCurrentPosition = msec;
Wei Jiac5de0912016-11-18 10:22:14 -0800577 mCurrentSeekMode = mode;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800578 if (mSeekPosition < 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800579 mSeekPosition = msec;
Wei Jiac5de0912016-11-18 10:22:14 -0800580 mSeekMode = mode;
581 return mPlayer->seekTo(msec, mode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800582 }
583 else {
Wei Jiac5de0912016-11-18 10:22:14 -0800584 ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, mode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800585 return NO_ERROR;
586 }
587 }
Glenn Kastenb187de12014-12-30 08:18:15 -0800588 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
589 mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800590 return INVALID_OPERATION;
591}
592
Wei Jiac5de0912016-11-18 10:22:14 -0800593status_t MediaPlayer::seekTo(int msec, MediaPlayerSeekMode mode)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800594{
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700595 mLockThreadId = getThreadId();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800596 Mutex::Autolock _l(mLock);
Wei Jiac5de0912016-11-18 10:22:14 -0800597 status_t result = seekTo_l(msec, mode);
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700598 mLockThreadId = 0;
599
600 return result;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800601}
602
Wei Jia52c28512017-09-13 18:17:51 -0700603status_t MediaPlayer::notifyAt(int64_t mediaTimeUs)
604{
605 Mutex::Autolock _l(mLock);
606 if (mPlayer != 0) {
607 return mPlayer->notifyAt(mediaTimeUs);
608 }
609 return INVALID_OPERATION;
610}
611
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700612status_t MediaPlayer::reset_l()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800613{
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800614 mLoop = false;
615 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
616 mPrepareSync = false;
617 if (mPlayer != 0) {
618 status_t ret = mPlayer->reset();
619 if (ret != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000620 ALOGE("reset() failed with return code (%d)", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800621 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
622 } else {
Robert Shih2b95bda2015-07-22 10:11:51 -0700623 mPlayer->disconnect();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800624 mCurrentState = MEDIA_PLAYER_IDLE;
625 }
James Donga1680bc2010-11-18 12:23:58 -0800626 // setDataSource has to be called again to create a
627 // new mediaplayer.
628 mPlayer = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800629 return ret;
630 }
631 clear_l();
632 return NO_ERROR;
633}
634
John Grossmanc795b642012-02-22 15:38:35 -0800635status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
636 Mutex::Autolock _l(mLock);
637
638 if (player == NULL) {
639 return UNKNOWN_ERROR;
640 }
641
642 if (mRetransmitEndpointValid) {
643 return player->setRetransmitEndpoint(&mRetransmitEndpoint);
644 }
645
646 return OK;
647}
648
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700649status_t MediaPlayer::reset()
650{
Steve Block3856b092011-10-20 11:56:00 +0100651 ALOGV("reset");
Wonsik Kim5f648972017-07-21 15:42:59 -0700652 mLockThreadId = getThreadId();
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700653 Mutex::Autolock _l(mLock);
Wonsik Kim5f648972017-07-21 15:42:59 -0700654 status_t result = reset_l();
655 mLockThreadId = 0;
656
657 return result;
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700658}
659
Glenn Kastenfff6d712012-01-12 16:38:12 -0800660status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800661{
Steve Block3856b092011-10-20 11:56:00 +0100662 ALOGV("MediaPlayer::setAudioStreamType");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800663 Mutex::Autolock _l(mLock);
664 if (mStreamType == type) return NO_ERROR;
665 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
666 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
667 // Can't change the stream type after prepare
Steve Block29357bc2012-01-06 19:20:56 +0000668 ALOGE("setAudioStream called in state %d", mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800669 return INVALID_OPERATION;
670 }
671 // cache
672 mStreamType = type;
673 return OK;
674}
675
John Spurlockde9453f2014-03-19 13:05:45 -0400676status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type)
677{
678 ALOGV("getAudioStreamType");
679 Mutex::Autolock _l(mLock);
680 *type = mStreamType;
681 return OK;
682}
683
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800684status_t MediaPlayer::setLooping(int loop)
685{
Steve Block3856b092011-10-20 11:56:00 +0100686 ALOGV("MediaPlayer::setLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800687 Mutex::Autolock _l(mLock);
688 mLoop = (loop != 0);
689 if (mPlayer != 0) {
690 return mPlayer->setLooping(loop);
691 }
692 return OK;
693}
694
695bool MediaPlayer::isLooping() {
Steve Block3856b092011-10-20 11:56:00 +0100696 ALOGV("isLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800697 Mutex::Autolock _l(mLock);
698 if (mPlayer != 0) {
699 return mLoop;
700 }
Steve Block3856b092011-10-20 11:56:00 +0100701 ALOGV("isLooping: no active player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800702 return false;
703}
704
705status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
706{
Steve Block3856b092011-10-20 11:56:00 +0100707 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800708 Mutex::Autolock _l(mLock);
709 mLeftVolume = leftVolume;
710 mRightVolume = rightVolume;
711 if (mPlayer != 0) {
712 return mPlayer->setVolume(leftVolume, rightVolume);
713 }
714 return OK;
715}
716
Glenn Kastend848eb42016-03-08 13:42:11 -0800717status_t MediaPlayer::setAudioSessionId(audio_session_t sessionId)
Eric Laurenta514bdb2010-06-21 09:27:30 -0700718{
Steve Block3856b092011-10-20 11:56:00 +0100719 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
Eric Laurenta514bdb2010-06-21 09:27:30 -0700720 Mutex::Autolock _l(mLock);
721 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
Steve Block29357bc2012-01-06 19:20:56 +0000722 ALOGE("setAudioSessionId called in state %d", mCurrentState);
Eric Laurenta514bdb2010-06-21 09:27:30 -0700723 return INVALID_OPERATION;
724 }
725 if (sessionId < 0) {
726 return BAD_VALUE;
727 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700728 if (sessionId != mAudioSessionId) {
Andy Hung8b0bfd92019-12-23 13:11:11 -0800729 AudioSystem::acquireAudioSessionId(sessionId, (pid_t)-1, (uid_t)-1);
730 AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700731 mAudioSessionId = sessionId;
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700732 }
Eric Laurenta514bdb2010-06-21 09:27:30 -0700733 return NO_ERROR;
734}
735
Glenn Kastend848eb42016-03-08 13:42:11 -0800736audio_session_t MediaPlayer::getAudioSessionId()
Eric Laurenta514bdb2010-06-21 09:27:30 -0700737{
738 Mutex::Autolock _l(mLock);
739 return mAudioSessionId;
740}
741
Eric Laurent2beeb502010-07-16 07:43:46 -0700742status_t MediaPlayer::setAuxEffectSendLevel(float level)
743{
Steve Block3856b092011-10-20 11:56:00 +0100744 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
Eric Laurent2beeb502010-07-16 07:43:46 -0700745 Mutex::Autolock _l(mLock);
746 mSendLevel = level;
747 if (mPlayer != 0) {
748 return mPlayer->setAuxEffectSendLevel(level);
749 }
750 return OK;
751}
752
753status_t MediaPlayer::attachAuxEffect(int effectId)
754{
Steve Block3856b092011-10-20 11:56:00 +0100755 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -0700756 Mutex::Autolock _l(mLock);
757 if (mPlayer == 0 ||
758 (mCurrentState & MEDIA_PLAYER_IDLE) ||
759 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
Wei Jia848ebc62016-03-23 14:06:46 -0700760 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
Eric Laurent2beeb502010-07-16 07:43:46 -0700761 return INVALID_OPERATION;
762 }
763
764 return mPlayer->attachAuxEffect(effectId);
765}
766
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700767// always call with lock held
768status_t MediaPlayer::checkStateForKeySet_l(int key)
769{
770 switch(key) {
771 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
772 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
773 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) {
774 // Can't change the audio attributes after prepare
775 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
776 return INVALID_OPERATION;
777 }
778 break;
779 default:
780 // parameter doesn't require player state check
781 break;
782 }
783 return OK;
784}
785
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700786status_t MediaPlayer::setParameter(int key, const Parcel& request)
787{
Steve Block3856b092011-10-20 11:56:00 +0100788 ALOGV("MediaPlayer::setParameter(%d)", key);
Eric Laurent43562692015-07-15 16:49:07 -0700789 status_t status = INVALID_OPERATION;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700790 Mutex::Autolock _l(mLock);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700791 if (checkStateForKeySet_l(key) != OK) {
Eric Laurent43562692015-07-15 16:49:07 -0700792 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700793 }
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700794 switch (key) {
795 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
Eric Laurent43562692015-07-15 16:49:07 -0700796 // save the marshalled audio attributes
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700797 if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
798 mAudioAttributesParcel = new Parcel();
799 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
Eric Laurent43562692015-07-15 16:49:07 -0700800 status = OK;
801 break;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700802 default:
Eric Laurent43562692015-07-15 16:49:07 -0700803 ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
804 break;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700805 }
Eric Laurent43562692015-07-15 16:49:07 -0700806
807 if (mPlayer != NULL) {
808 status = mPlayer->setParameter(key, request);
809 }
810 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700811}
812
813status_t MediaPlayer::getParameter(int key, Parcel *reply)
814{
Steve Block3856b092011-10-20 11:56:00 +0100815 ALOGV("MediaPlayer::getParameter(%d)", key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700816 Mutex::Autolock _l(mLock);
817 if (mPlayer != NULL) {
Ray Essickdb122142017-01-25 17:51:55 -0800818 status_t status = mPlayer->getParameter(key, reply);
819 if (status != OK) {
820 ALOGD("getParameter returns %d", status);
821 }
822 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700823 }
Steve Block3856b092011-10-20 11:56:00 +0100824 ALOGV("getParameter: no active player");
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700825 return INVALID_OPERATION;
826}
827
John Grossmanc795b642012-02-22 15:38:35 -0800828status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
829 uint16_t port) {
830 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
831 addrString ? addrString : "(null)", port);
832
833 Mutex::Autolock _l(mLock);
834 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
835 return INVALID_OPERATION;
836
837 if (NULL == addrString) {
838 mRetransmitEndpointValid = false;
839 return OK;
840 }
841
842 struct in_addr saddr;
843 if(!inet_aton(addrString, &saddr)) {
844 return BAD_VALUE;
845 }
846
Glenn Kastenbe08f6a2013-12-19 09:09:33 -0800847 memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
John Grossmanc795b642012-02-22 15:38:35 -0800848 mRetransmitEndpoint.sin_family = AF_INET;
849 mRetransmitEndpoint.sin_addr = saddr;
850 mRetransmitEndpoint.sin_port = htons(port);
851 mRetransmitEndpointValid = true;
852
853 return OK;
854}
855
Gloria Wangb483c472011-04-11 17:23:27 -0700856void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800857{
Steve Block3856b092011-10-20 11:56:00 +0100858 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800859 bool send = true;
Jason Sams1af452f2009-03-24 18:45:22 -0700860 bool locked = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800861
862 // TODO: In the future, we might be on the same thread if the app is
863 // running in the same process as the media server. In that case,
864 // this will deadlock.
Nicolas Catania66095182009-06-11 16:33:49 -0700865 //
Chong Zhangd88adb92014-07-23 11:43:46 -0700866 // The threadId hack below works around this for the care of prepare,
Wonsik Kim5f648972017-07-21 15:42:59 -0700867 // seekTo, start, and reset within the same process.
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700868 // FIXME: Remember, this is a hack, it's not even a hack that is applied
869 // consistently for all use-cases, this needs to be revisited.
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700870 if (mLockThreadId != getThreadId()) {
Jason Sams1af452f2009-03-24 18:45:22 -0700871 mLock.lock();
872 locked = true;
Nicolas Catania66095182009-06-11 16:33:49 -0700873 }
Jason Sams1af452f2009-03-24 18:45:22 -0700874
Eric Laurent3b268442010-08-03 07:49:49 -0700875 // Allows calls from JNI in idle state to notify errors
876 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
Steve Block3856b092011-10-20 11:56:00 +0100877 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
Jason Sams1af452f2009-03-24 18:45:22 -0700878 if (locked) mLock.unlock(); // release the lock when done.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800879 return;
880 }
881
882 switch (msg) {
883 case MEDIA_NOP: // interface test message
884 break;
885 case MEDIA_PREPARED:
Hassan Shojania071437a2017-01-23 09:19:40 -0800886 ALOGV("MediaPlayer::notify() prepared");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800887 mCurrentState = MEDIA_PLAYER_PREPARED;
888 if (mPrepareSync) {
Steve Block3856b092011-10-20 11:56:00 +0100889 ALOGV("signal application thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800890 mPrepareSync = false;
891 mPrepareStatus = NO_ERROR;
892 mSignal.signal();
893 }
894 break;
Hassan Shojania071437a2017-01-23 09:19:40 -0800895 case MEDIA_DRM_INFO:
896 ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
897 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800898 case MEDIA_PLAYBACK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +0100899 ALOGV("playback complete");
Marco Nelissen1c1503c2010-09-17 15:04:01 -0700900 if (mCurrentState == MEDIA_PLAYER_IDLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000901 ALOGE("playback complete in idle state");
Marco Nelissen1c1503c2010-09-17 15:04:01 -0700902 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800903 if (!mLoop) {
904 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
905 }
906 break;
907 case MEDIA_ERROR:
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700908 // Always log errors.
909 // ext1: Media framework error code.
910 // ext2: Implementation dependant error code.
Steve Block29357bc2012-01-06 19:20:56 +0000911 ALOGE("error (%d, %d)", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800912 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
913 if (mPrepareSync)
914 {
Steve Block3856b092011-10-20 11:56:00 +0100915 ALOGV("signal application thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800916 mPrepareSync = false;
917 mPrepareStatus = ext1;
918 mSignal.signal();
919 send = false;
920 }
921 break;
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700922 case MEDIA_INFO:
923 // ext1: Media framework error code.
924 // ext2: Implementation dependant error code.
Andreas Huber145e68f2011-01-11 15:05:28 -0800925 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000926 ALOGW("info/warning (%d, %d)", ext1, ext2);
Andreas Huber145e68f2011-01-11 15:05:28 -0800927 }
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700928 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800929 case MEDIA_SEEK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +0100930 ALOGV("Received seek complete");
Wei Jiac5de0912016-11-18 10:22:14 -0800931 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
932 ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800933 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800934 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
935 seekTo_l(mCurrentPosition, mCurrentSeekMode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800936 }
937 else {
Steve Block3856b092011-10-20 11:56:00 +0100938 ALOGV("All seeks complete - return to regularly scheduled program");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800939 mCurrentPosition = mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800940 mCurrentSeekMode = mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800941 }
942 break;
943 case MEDIA_BUFFERING_UPDATE:
Steve Block3856b092011-10-20 11:56:00 +0100944 ALOGV("buffering %d", ext1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800945 break;
946 case MEDIA_SET_VIDEO_SIZE:
Steve Block3856b092011-10-20 11:56:00 +0100947 ALOGV("New video size %d x %d", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800948 mVideoWidth = ext1;
949 mVideoHeight = ext2;
950 break;
Wei Jia52c28512017-09-13 18:17:51 -0700951 case MEDIA_NOTIFY_TIME:
952 ALOGV("Received notify time message");
953 break;
Gloria Wangb483c472011-04-11 17:23:27 -0700954 case MEDIA_TIMED_TEXT:
Steve Block3856b092011-10-20 11:56:00 +0100955 ALOGV("Received timed text message");
Gloria Wangb483c472011-04-11 17:23:27 -0700956 break;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700957 case MEDIA_SUBTITLE_DATA:
958 ALOGV("Received subtitle data message");
959 break;
Robert Shih08528432015-04-08 09:06:54 -0700960 case MEDIA_META_DATA:
961 ALOGV("Received timed metadata message");
962 break;
Kim Sungyeond3c6b322018-03-02 14:41:19 +0900963 case MEDIA_IMS_RX_NOTICE:
964 ALOGV("Received IMS Rx notice message");
965 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800966 default:
Steve Block3856b092011-10-20 11:56:00 +0100967 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800968 break;
969 }
970
971 sp<MediaPlayerListener> listener = mListener;
Jason Sams1af452f2009-03-24 18:45:22 -0700972 if (locked) mLock.unlock();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800973
974 // this prevents re-entrant calls into client code
975 if ((listener != 0) && send) {
976 Mutex::Autolock _l(mNotifyLock);
Steve Block3856b092011-10-20 11:56:00 +0100977 ALOGV("callback application");
Gloria Wangb483c472011-04-11 17:23:27 -0700978 listener->notify(msg, ext1, ext2, obj);
Steve Block3856b092011-10-20 11:56:00 +0100979 ALOGV("back from callback");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800980 }
981}
982
James Dongdd172fc2010-01-15 18:13:58 -0800983void MediaPlayer::died()
984{
Steve Block3856b092011-10-20 11:56:00 +0100985 ALOGV("died");
James Dongdd172fc2010-01-15 18:13:58 -0800986 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
987}
988
Marco Nelissen6b74d672012-02-28 16:07:44 -0800989status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
Wei Jia12438692016-03-28 14:12:57 -0700990 Mutex::Autolock _l(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -0800991 if (mPlayer == NULL) {
992 return NO_INIT;
993 }
Marco Nelissenb13820f2013-08-05 12:22:43 -0700994
995 if (next != NULL && !(next->mCurrentState &
996 (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
997 ALOGE("next player is not prepared");
998 return INVALID_OPERATION;
999 }
1000
Marco Nelissen6b74d672012-02-28 16:07:44 -08001001 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
1002}
1003
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001004VolumeShaper::Status MediaPlayer::applyVolumeShaper(
1005 const sp<VolumeShaper::Configuration>& configuration,
1006 const sp<VolumeShaper::Operation>& operation)
1007{
1008 Mutex::Autolock _l(mLock);
1009 if (mPlayer == nullptr) {
1010 return VolumeShaper::Status(NO_INIT);
1011 }
1012 VolumeShaper::Status status = mPlayer->applyVolumeShaper(configuration, operation);
1013 return status;
1014}
1015
1016sp<VolumeShaper::State> MediaPlayer::getVolumeShaperState(int id)
1017{
1018 Mutex::Autolock _l(mLock);
1019 if (mPlayer == nullptr) {
1020 return nullptr;
1021 }
1022 return mPlayer->getVolumeShaperState(id);
1023}
1024
Hassan Shojaniacefac142017-02-06 21:02:02 -08001025// Modular DRM
1026status_t MediaPlayer::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
Hassan Shojania071437a2017-01-23 09:19:40 -08001027{
Hassan Shojaniacefac142017-02-06 21:02:02 -08001028 // TODO change to ALOGV
1029 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1030 drmSessionId.array(), drmSessionId.size());
Hassan Shojania071437a2017-01-23 09:19:40 -08001031 Mutex::Autolock _l(mLock);
1032 if (mPlayer == NULL) {
1033 return NO_INIT;
1034 }
1035
Hassan Shojania838be392017-05-23 14:14:24 -07001036 // Only allowed it in player's preparing/prepared state.
1037 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1038 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1039 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1040 if (!(mCurrentState & (MEDIA_PLAYER_PREPARING | MEDIA_PLAYER_PREPARED))) {
1041 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
Hassan Shojania071437a2017-01-23 09:19:40 -08001042 return INVALID_OPERATION;
1043 }
1044
Hassan Shojaniacefac142017-02-06 21:02:02 -08001045 if (drmSessionId.isEmpty()) {
1046 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1047 return INVALID_OPERATION;
1048 }
Hassan Shojania071437a2017-01-23 09:19:40 -08001049
Hassan Shojaniacefac142017-02-06 21:02:02 -08001050 // Passing down to mediaserver mainly for creating the crypto
1051 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1052 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1053
1054 // TODO change to ALOGV
1055 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1056
1057 return status;
Hassan Shojania071437a2017-01-23 09:19:40 -08001058}
1059
1060status_t MediaPlayer::releaseDrm()
1061{
1062 Mutex::Autolock _l(mLock);
1063 if (mPlayer == NULL) {
1064 return NO_INIT;
1065 }
1066
Hassan Shojaniacefac142017-02-06 21:02:02 -08001067 // Not allowing releaseDrm in an active/resumable state
1068 if (mCurrentState & (MEDIA_PLAYER_STARTED |
1069 MEDIA_PLAYER_PAUSED |
1070 MEDIA_PLAYER_PLAYBACK_COMPLETE |
1071 MEDIA_PLAYER_STATE_ERROR)) {
1072 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
Hassan Shojania071437a2017-01-23 09:19:40 -08001073 return INVALID_OPERATION;
1074 }
1075
Hassan Shojaniacefac142017-02-06 21:02:02 -08001076 status_t status = mPlayer->releaseDrm();
1077 // TODO change to ALOGV
1078 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1079 if (status != OK) {
1080 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1081 // Overriding to OK so the client proceed with its own cleanup
1082 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1083 status = OK;
Hassan Shojania071437a2017-01-23 09:19:40 -08001084 }
1085
Hassan Shojaniacefac142017-02-06 21:02:02 -08001086 return status;
Hassan Shojania071437a2017-01-23 09:19:40 -08001087}
1088
jiabin156c6872017-10-06 09:47:15 -07001089status_t MediaPlayer::setOutputDevice(audio_port_handle_t deviceId)
1090{
1091 Mutex::Autolock _l(mLock);
1092 if (mPlayer == NULL) {
1093 ALOGV("setOutputDevice: player not init");
1094 return NO_INIT;
1095 }
1096 return mPlayer->setOutputDevice(deviceId);
1097}
1098
1099audio_port_handle_t MediaPlayer::getRoutedDeviceId()
1100{
1101 Mutex::Autolock _l(mLock);
1102 if (mPlayer == NULL) {
1103 ALOGV("getRoutedDeviceId: player not init");
1104 return AUDIO_PORT_HANDLE_NONE;
1105 }
1106 audio_port_handle_t deviceId;
1107 status_t status = mPlayer->getRoutedDeviceId(&deviceId);
1108 if (status != NO_ERROR) {
1109 return AUDIO_PORT_HANDLE_NONE;
1110 }
1111 return deviceId;
1112}
1113
1114status_t MediaPlayer::enableAudioDeviceCallback(bool enabled)
1115{
1116 Mutex::Autolock _l(mLock);
1117 if (mPlayer == NULL) {
1118 ALOGV("addAudioDeviceCallback: player not init");
1119 return NO_INIT;
1120 }
1121 return mPlayer->enableAudioDeviceCallback(enabled);
1122}
1123
Glenn Kasten40bc9062015-03-20 09:09:33 -07001124} // namespace android