blob: 1c9b9e49419ac89441ea7194fb6caea081963b00 [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;
Svet Ganov33761132021-05-13 22:51:08 +000043using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070044
Svet Ganov33761132021-05-13 22:51:08 +000045MediaPlayer::MediaPlayer(const AttributionSourceState& attributionSource)
46 : mAttributionSource(attributionSource)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080047{
Steve Block3856b092011-10-20 11:56:00 +010048 ALOGV("constructor");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080049 mListener = NULL;
50 mCookie = NULL;
Dima Zavinfce7a472011-04-19 22:30:36 -070051 mStreamType = AUDIO_STREAM_MUSIC;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -070052 mAudioAttributesParcel = NULL;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080053 mCurrentPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -080054 mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080055 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -080056 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080057 mCurrentState = MEDIA_PLAYER_IDLE;
58 mPrepareSync = false;
59 mPrepareStatus = NO_ERROR;
60 mLoop = false;
61 mLeftVolume = mRightVolume = 1.0;
62 mVideoWidth = mVideoHeight = 0;
Jason Sams1af452f2009-03-24 18:45:22 -070063 mLockThreadId = 0;
Glenn Kastend848eb42016-03-08 13:42:11 -080064 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Andy Hung8b0bfd92019-12-23 13:11:11 -080065 AudioSystem::acquireAudioSessionId(mAudioSessionId, (pid_t)-1, (uid_t)-1); // always in client.
Eric Laurent8c563ed2010-10-07 18:23:03 -070066 mSendLevel = 0;
John Grossmanc795b642012-02-22 15:38:35 -080067 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080068}
69
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080070MediaPlayer::~MediaPlayer()
71{
Steve Block3856b092011-10-20 11:56:00 +010072 ALOGV("destructor");
Jean-Michel Trivi640adb32014-09-05 11:20:11 -070073 if (mAudioAttributesParcel != NULL) {
74 delete mAudioAttributesParcel;
75 mAudioAttributesParcel = NULL;
76 }
Andy Hung8b0bfd92019-12-23 13:11:11 -080077 AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080078 disconnect();
79 IPCThreadState::self()->flushCommands();
80}
81
82void MediaPlayer::disconnect()
83{
Steve Block3856b092011-10-20 11:56:00 +010084 ALOGV("disconnect");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080085 sp<IMediaPlayer> p;
86 {
87 Mutex::Autolock _l(mLock);
88 p = mPlayer;
89 mPlayer.clear();
90 }
91
92 if (p != 0) {
93 p->disconnect();
94 }
95}
96
97// always call with lock held
98void MediaPlayer::clear_l()
99{
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800100 mCurrentPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800101 mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800102 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800103 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800104 mVideoWidth = mVideoHeight = 0;
John Grossmanc795b642012-02-22 15:38:35 -0800105 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800106}
107
108status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
109{
Steve Block3856b092011-10-20 11:56:00 +0100110 ALOGV("setListener");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800111 Mutex::Autolock _l(mLock);
112 mListener = listener;
113 return NO_ERROR;
114}
115
116
Dave Burked681bbb2011-08-30 14:39:17 +0100117status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800118{
119 status_t err = UNKNOWN_ERROR;
120 sp<IMediaPlayer> p;
121 { // scope for the lock
122 Mutex::Autolock _l(mLock);
123
Marco Nelissen83ff1432010-03-10 10:53:16 -0800124 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
125 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
Steve Block29357bc2012-01-06 19:20:56 +0000126 ALOGE("attachNewPlayer called in state %d", mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800127 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 {
Masaki Muranakaf65fa172013-06-06 09:36:34 +0000137 ALOGE("Unable to create media player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800138 }
139 }
140
141 if (p != 0) {
142 p->disconnect();
143 }
144
145 return err;
146}
147
Andreas Huber2db84552010-01-28 11:19:57 -0800148status_t MediaPlayer::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800149 const sp<IMediaHTTPService> &httpService,
Andreas Huber2db84552010-01-28 11:19:57 -0800150 const char *url, const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800151{
Steve Block3856b092011-10-20 11:56:00 +0100152 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800153 status_t err = BAD_VALUE;
154 if (url != NULL) {
Marco Nelissenfc908d02016-06-07 12:26:43 -0700155 const sp<IMediaPlayerService> service(getMediaPlayerService());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800156 if (service != 0) {
Svet Ganov33761132021-05-13 22:51:08 +0000157 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
John Grossmanc795b642012-02-22 15:38:35 -0800158 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
Andreas Huber1b86fe02014-01-29 11:13:26 -0800159 (NO_ERROR != player->setDataSource(httpService, url, headers))) {
Dave Burke06620672011-09-06 20:39:47 +0100160 player.clear();
Dave Burked681bbb2011-08-30 14:39:17 +0100161 }
Dave Burke06620672011-09-06 20:39:47 +0100162 err = attachNewPlayer(player);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800163 }
164 }
165 return err;
166}
167
168status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
169{
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700170 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800171 status_t err = UNKNOWN_ERROR;
Marco Nelissenfc908d02016-06-07 12:26:43 -0700172 const sp<IMediaPlayerService> service(getMediaPlayerService());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800173 if (service != 0) {
Svet Ganov33761132021-05-13 22:51:08 +0000174 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
John Grossmanc795b642012-02-22 15:38:35 -0800175 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
176 (NO_ERROR != player->setDataSource(fd, offset, length))) {
Dave Burke06620672011-09-06 20:39:47 +0100177 player.clear();
Dave Burked681bbb2011-08-30 14:39:17 +0100178 }
Dave Burke06620672011-09-06 20:39:47 +0100179 err = attachNewPlayer(player);
Dave Burked681bbb2011-08-30 14:39:17 +0100180 }
181 return err;
182}
183
Chris Watkins99f31602015-03-20 13:06:33 -0700184status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
185{
186 ALOGV("setDataSource(IDataSource)");
187 status_t err = UNKNOWN_ERROR;
Marco Nelissenfc908d02016-06-07 12:26:43 -0700188 const sp<IMediaPlayerService> service(getMediaPlayerService());
Chris Watkins99f31602015-03-20 13:06:33 -0700189 if (service != 0) {
Svet Ganov33761132021-05-13 22:51:08 +0000190 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
Chris Watkins99f31602015-03-20 13:06:33 -0700191 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
Byeongjo Park28225ab2019-01-24 20:31:19 +0900200status_t MediaPlayer::setDataSource(const String8& rtpParams)
201{
202 ALOGV("setDataSource(rtpParams)");
203 status_t err = UNKNOWN_ERROR;
204 const sp<IMediaPlayerService> service(getMediaPlayerService());
205 if (service != 0) {
Svet Ganov33761132021-05-13 22:51:08 +0000206 sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
Byeongjo Park28225ab2019-01-24 20:31:19 +0900207 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
208 (NO_ERROR != player->setDataSource(rtpParams))) {
209 player.clear();
210 }
211 err = attachNewPlayer(player);
212 }
213 return err;
214}
215
Nicolas Catania1d187f12009-05-12 23:25:55 -0700216status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
217{
218 Mutex::Autolock _l(mLock);
Nicolas Catania40234932010-03-10 10:41:04 -0800219 const bool hasBeenInitialized =
220 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
221 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
222 if ((mPlayer != NULL) && hasBeenInitialized) {
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700223 ALOGV("invoke %zu", request.dataSize());
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700224 return mPlayer->invoke(request, reply);
Nicolas Catania1d187f12009-05-12 23:25:55 -0700225 }
Wei Jia848ebc62016-03-23 14:06:46 -0700226 ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Nicolas Catania1d187f12009-05-12 23:25:55 -0700227 return INVALID_OPERATION;
228}
229
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700230status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
231{
Steve Blockb8a80522011-12-20 16:23:08 +0000232 ALOGD("setMetadataFilter");
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700233 Mutex::Autolock lock(mLock);
234 if (mPlayer == NULL) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700235 return NO_INIT;
236 }
237 return mPlayer->setMetadataFilter(filter);
238}
Nicolas Catania1d187f12009-05-12 23:25:55 -0700239
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700240status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
241{
Steve Blockb8a80522011-12-20 16:23:08 +0000242 ALOGD("getMetadata");
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700243 Mutex::Autolock lock(mLock);
244 if (mPlayer == NULL) {
245 return NO_INIT;
246 }
247 return mPlayer->getMetadata(update_only, apply_filter, metadata);
248}
249
Glenn Kasten11731182011-02-08 17:26:17 -0800250status_t MediaPlayer::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800251 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800252{
Steve Block3856b092011-10-20 11:56:00 +0100253 ALOGV("setVideoSurfaceTexture");
Glenn Kasten11731182011-02-08 17:26:17 -0800254 Mutex::Autolock _l(mLock);
255 if (mPlayer == 0) return NO_INIT;
Andy McFadden484566c2012-12-18 09:46:54 -0800256 return mPlayer->setVideoSurfaceTexture(bufferProducer);
Glenn Kasten11731182011-02-08 17:26:17 -0800257}
258
Wei Jiaed320862017-01-18 14:03:40 -0800259status_t MediaPlayer::getBufferingSettings(BufferingSettings* buffering /* nonnull */)
260{
261 ALOGV("getBufferingSettings");
262
263 Mutex::Autolock _l(mLock);
264 if (mPlayer == 0) {
265 return NO_INIT;
266 }
Wei Jia9bb38032017-03-23 18:00:38 -0700267 return mPlayer->getBufferingSettings(buffering);
Wei Jiaed320862017-01-18 14:03:40 -0800268}
269
Wei Jiadc6f3402017-01-09 15:04:18 -0800270status_t MediaPlayer::setBufferingSettings(const BufferingSettings& buffering)
271{
272 ALOGV("setBufferingSettings");
273
274 Mutex::Autolock _l(mLock);
275 if (mPlayer == 0) {
276 return NO_INIT;
277 }
Wei Jia9bb38032017-03-23 18:00:38 -0700278 return mPlayer->setBufferingSettings(buffering);
Wei Jiadc6f3402017-01-09 15:04:18 -0800279}
280
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800281// must call with lock held
282status_t MediaPlayer::prepareAsync_l()
283{
Glenn Kastenb187de12014-12-30 08:18:15 -0800284 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700285 if (mAudioAttributesParcel != NULL) {
286 mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
Eric Laurent43562692015-07-15 16:49:07 -0700287 } else {
288 mPlayer->setAudioStreamType(mStreamType);
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700289 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800290 mCurrentState = MEDIA_PLAYER_PREPARING;
291 return mPlayer->prepareAsync();
292 }
Wei Jia848ebc62016-03-23 14:06:46 -0700293 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800294 return INVALID_OPERATION;
295}
296
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700297// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
298// one defined in the Android framework and one provided by the implementation
299// that generated the error. The sync version of prepare returns only 1 error
300// code.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800301status_t MediaPlayer::prepare()
302{
Steve Block3856b092011-10-20 11:56:00 +0100303 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800304 Mutex::Autolock _l(mLock);
Jason Sams1af452f2009-03-24 18:45:22 -0700305 mLockThreadId = getThreadId();
306 if (mPrepareSync) {
307 mLockThreadId = 0;
308 return -EALREADY;
309 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800310 mPrepareSync = true;
311 status_t ret = prepareAsync_l();
Jason Sams1af452f2009-03-24 18:45:22 -0700312 if (ret != NO_ERROR) {
313 mLockThreadId = 0;
314 return ret;
315 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800316
317 if (mPrepareSync) {
318 mSignal.wait(mLock); // wait for prepare done
319 mPrepareSync = false;
320 }
Steve Block3856b092011-10-20 11:56:00 +0100321 ALOGV("prepare complete - status=%d", mPrepareStatus);
Jason Sams1af452f2009-03-24 18:45:22 -0700322 mLockThreadId = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800323 return mPrepareStatus;
324}
325
326status_t MediaPlayer::prepareAsync()
327{
Steve Block3856b092011-10-20 11:56:00 +0100328 ALOGV("prepareAsync");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800329 Mutex::Autolock _l(mLock);
330 return prepareAsync_l();
331}
332
333status_t MediaPlayer::start()
334{
Steve Block3856b092011-10-20 11:56:00 +0100335 ALOGV("start");
Chong Zhangd88adb92014-07-23 11:43:46 -0700336
337 status_t ret = NO_ERROR;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800338 Mutex::Autolock _l(mLock);
Chong Zhangd88adb92014-07-23 11:43:46 -0700339
340 mLockThreadId = getThreadId();
341
342 if (mCurrentState & MEDIA_PLAYER_STARTED) {
343 ret = NO_ERROR;
344 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800345 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
346 mPlayer->setLooping(mLoop);
347 mPlayer->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -0700348 mPlayer->setAuxEffectSendLevel(mSendLevel);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800349 mCurrentState = MEDIA_PLAYER_STARTED;
Chong Zhangd88adb92014-07-23 11:43:46 -0700350 ret = mPlayer->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800351 if (ret != NO_ERROR) {
352 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
353 } else {
354 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
Steve Block3856b092011-10-20 11:56:00 +0100355 ALOGV("playback completed immediately following start()");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800356 }
357 }
Chong Zhangd88adb92014-07-23 11:43:46 -0700358 } else {
Wei Jia848ebc62016-03-23 14:06:46 -0700359 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
Chong Zhangd88adb92014-07-23 11:43:46 -0700360 ret = INVALID_OPERATION;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800361 }
Chong Zhangd88adb92014-07-23 11:43:46 -0700362
363 mLockThreadId = 0;
364
365 return ret;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800366}
367
368status_t MediaPlayer::stop()
369{
Steve Block3856b092011-10-20 11:56:00 +0100370 ALOGV("stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800371 Mutex::Autolock _l(mLock);
372 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
373 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
374 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
375 status_t ret = mPlayer->stop();
376 if (ret != NO_ERROR) {
377 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
378 } else {
379 mCurrentState = MEDIA_PLAYER_STOPPED;
380 }
381 return ret;
382 }
Wei Jia848ebc62016-03-23 14:06:46 -0700383 ALOGE("stop called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800384 return INVALID_OPERATION;
385}
386
387status_t MediaPlayer::pause()
388{
Steve Block3856b092011-10-20 11:56:00 +0100389 ALOGV("pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800390 Mutex::Autolock _l(mLock);
Marco Nelissen698f4762010-02-26 13:16:23 -0800391 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800392 return NO_ERROR;
393 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
394 status_t ret = mPlayer->pause();
395 if (ret != NO_ERROR) {
396 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
397 } else {
398 mCurrentState = MEDIA_PLAYER_PAUSED;
399 }
400 return ret;
401 }
Wei Jia848ebc62016-03-23 14:06:46 -0700402 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800403 return INVALID_OPERATION;
404}
405
406bool MediaPlayer::isPlaying()
407{
408 Mutex::Autolock _l(mLock);
409 if (mPlayer != 0) {
410 bool temp = false;
411 mPlayer->isPlaying(&temp);
Steve Block3856b092011-10-20 11:56:00 +0100412 ALOGV("isPlaying: %d", temp);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800413 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
Steve Block29357bc2012-01-06 19:20:56 +0000414 ALOGE("internal/external state mismatch corrected");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800415 mCurrentState = MEDIA_PLAYER_PAUSED;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700416 } else if ((mCurrentState & MEDIA_PLAYER_PAUSED) && temp) {
417 ALOGE("internal/external state mismatch corrected");
418 mCurrentState = MEDIA_PLAYER_STARTED;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800419 }
420 return temp;
421 }
Steve Block3856b092011-10-20 11:56:00 +0100422 ALOGV("isPlaying: no active player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800423 return false;
424}
425
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700426status_t MediaPlayer::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -0800427{
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700428 ALOGV("setPlaybackSettings: %f %f %d %d",
429 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
430 // Negative speed and pitch does not make sense. Further validation will
431 // be done by the respective mediaplayers.
432 if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
Wei Jia98160162015-02-04 17:01:11 -0800433 return BAD_VALUE;
434 }
435 Mutex::Autolock _l(mLock);
Wei Jia5af6a9b2016-06-16 12:07:26 -0700436 if (mPlayer == 0 || (mCurrentState & MEDIA_PLAYER_STOPPED)) {
437 return INVALID_OPERATION;
438 }
Wei Jia5be109f2016-06-10 16:15:07 -0700439
440 if (rate.mSpeed != 0.f && !(mCurrentState & MEDIA_PLAYER_STARTED)
441 && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
442 | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
443 mPlayer->setLooping(mLoop);
444 mPlayer->setVolume(mLeftVolume, mRightVolume);
445 mPlayer->setAuxEffectSendLevel(mSendLevel);
446 }
447
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700448 status_t err = mPlayer->setPlaybackSettings(rate);
449 if (err == OK) {
450 if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER_STARTED) {
451 mCurrentState = MEDIA_PLAYER_PAUSED;
Wei Jia5be109f2016-06-10 16:15:07 -0700452 } else if (rate.mSpeed != 0.f
453 && (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED
454 | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700455 mCurrentState = MEDIA_PLAYER_STARTED;
Wei Jia98160162015-02-04 17:01:11 -0800456 }
Wei Jia98160162015-02-04 17:01:11 -0800457 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700458 return err;
459}
460
461status_t MediaPlayer::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
462{
463 Mutex::Autolock _l(mLock);
464 if (mPlayer == 0) return INVALID_OPERATION;
465 return mPlayer->getPlaybackSettings(rate);
466}
467
468status_t MediaPlayer::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
469{
470 ALOGV("setSyncSettings: %u %u %f %f",
471 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
472 Mutex::Autolock _l(mLock);
473 if (mPlayer == 0) return INVALID_OPERATION;
474 return mPlayer->setSyncSettings(sync, videoFpsHint);
475}
476
477status_t MediaPlayer::getSyncSettings(
478 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
479{
480 Mutex::Autolock _l(mLock);
481 if (mPlayer == 0) return INVALID_OPERATION;
482 return mPlayer->getSyncSettings(sync, videoFps);
Wei Jia98160162015-02-04 17:01:11 -0800483}
484
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800485status_t MediaPlayer::getVideoWidth(int *w)
486{
Steve Block3856b092011-10-20 11:56:00 +0100487 ALOGV("getVideoWidth");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800488 Mutex::Autolock _l(mLock);
489 if (mPlayer == 0) return INVALID_OPERATION;
490 *w = mVideoWidth;
491 return NO_ERROR;
492}
493
494status_t MediaPlayer::getVideoHeight(int *h)
495{
Steve Block3856b092011-10-20 11:56:00 +0100496 ALOGV("getVideoHeight");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800497 Mutex::Autolock _l(mLock);
498 if (mPlayer == 0) return INVALID_OPERATION;
499 *h = mVideoHeight;
500 return NO_ERROR;
501}
502
503status_t MediaPlayer::getCurrentPosition(int *msec)
504{
Steve Block3856b092011-10-20 11:56:00 +0100505 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800506 Mutex::Autolock _l(mLock);
507 if (mPlayer != 0) {
508 if (mCurrentPosition >= 0) {
Steve Block3856b092011-10-20 11:56:00 +0100509 ALOGV("Using cached seek position: %d", mCurrentPosition);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800510 *msec = mCurrentPosition;
511 return NO_ERROR;
512 }
513 return mPlayer->getCurrentPosition(msec);
514 }
515 return INVALID_OPERATION;
516}
517
518status_t MediaPlayer::getDuration_l(int *msec)
519{
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800520 ALOGV("getDuration_l");
Glenn Kastenb187de12014-12-30 08:18:15 -0800521 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
522 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800523 if (mPlayer != 0 && isValidState) {
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800524 int durationMs;
525 status_t ret = mPlayer->getDuration(&durationMs);
Andreas Huber20702542013-04-11 11:07:55 -0700526
527 if (ret != OK) {
528 // Do not enter error state just because no duration was available.
529 durationMs = -1;
530 ret = OK;
531 }
532
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800533 if (msec) {
534 *msec = durationMs;
535 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800536 return ret;
537 }
Wei Jia848ebc62016-03-23 14:06:46 -0700538 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
539 mPlayer.get(), mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800540 return INVALID_OPERATION;
541}
542
543status_t MediaPlayer::getDuration(int *msec)
544{
545 Mutex::Autolock _l(mLock);
546 return getDuration_l(msec);
547}
548
Wei Jiac5de0912016-11-18 10:22:14 -0800549status_t MediaPlayer::seekTo_l(int msec, MediaPlayerSeekMode mode)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800550{
Wei Jiac5de0912016-11-18 10:22:14 -0800551 ALOGV("seekTo (%d, %d)", msec, mode);
Glenn Kastenb187de12014-12-30 08:18:15 -0800552 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
553 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800554 if ( msec < 0 ) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000555 ALOGW("Attempt to seek to invalid position: %d", msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800556 msec = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800557 }
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800558
559 int durationMs;
560 status_t err = mPlayer->getDuration(&durationMs);
561
562 if (err != OK) {
563 ALOGW("Stream has no duration and is therefore not seekable.");
564 return err;
565 }
566
567 if (msec > durationMs) {
568 ALOGW("Attempt to seek to past end of file: request = %d, "
569 "durationMs = %d",
570 msec,
571 durationMs);
572
573 msec = durationMs;
574 }
575
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800576 // cache duration
577 mCurrentPosition = msec;
Wei Jiac5de0912016-11-18 10:22:14 -0800578 mCurrentSeekMode = mode;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800579 if (mSeekPosition < 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800580 mSeekPosition = msec;
Wei Jiac5de0912016-11-18 10:22:14 -0800581 mSeekMode = mode;
582 return mPlayer->seekTo(msec, mode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800583 }
584 else {
Wei Jiac5de0912016-11-18 10:22:14 -0800585 ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, mode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800586 return NO_ERROR;
587 }
588 }
Glenn Kastenb187de12014-12-30 08:18:15 -0800589 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
590 mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800591 return INVALID_OPERATION;
592}
593
Wei Jiac5de0912016-11-18 10:22:14 -0800594status_t MediaPlayer::seekTo(int msec, MediaPlayerSeekMode mode)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800595{
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700596 mLockThreadId = getThreadId();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800597 Mutex::Autolock _l(mLock);
Wei Jiac5de0912016-11-18 10:22:14 -0800598 status_t result = seekTo_l(msec, mode);
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700599 mLockThreadId = 0;
600
601 return result;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800602}
603
Wei Jia52c28512017-09-13 18:17:51 -0700604status_t MediaPlayer::notifyAt(int64_t mediaTimeUs)
605{
606 Mutex::Autolock _l(mLock);
607 if (mPlayer != 0) {
608 return mPlayer->notifyAt(mediaTimeUs);
609 }
610 return INVALID_OPERATION;
611}
612
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700613status_t MediaPlayer::reset_l()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800614{
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800615 mLoop = false;
616 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
617 mPrepareSync = false;
618 if (mPlayer != 0) {
619 status_t ret = mPlayer->reset();
620 if (ret != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000621 ALOGE("reset() failed with return code (%d)", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800622 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
623 } else {
Robert Shih2b95bda2015-07-22 10:11:51 -0700624 mPlayer->disconnect();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800625 mCurrentState = MEDIA_PLAYER_IDLE;
626 }
James Donga1680bc2010-11-18 12:23:58 -0800627 // setDataSource has to be called again to create a
628 // new mediaplayer.
629 mPlayer = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800630 return ret;
631 }
632 clear_l();
633 return NO_ERROR;
634}
635
John Grossmanc795b642012-02-22 15:38:35 -0800636status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
637 Mutex::Autolock _l(mLock);
638
639 if (player == NULL) {
640 return UNKNOWN_ERROR;
641 }
642
643 if (mRetransmitEndpointValid) {
644 return player->setRetransmitEndpoint(&mRetransmitEndpoint);
645 }
646
647 return OK;
648}
649
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700650status_t MediaPlayer::reset()
651{
Steve Block3856b092011-10-20 11:56:00 +0100652 ALOGV("reset");
Wonsik Kim5f648972017-07-21 15:42:59 -0700653 mLockThreadId = getThreadId();
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700654 Mutex::Autolock _l(mLock);
Wonsik Kim5f648972017-07-21 15:42:59 -0700655 status_t result = reset_l();
656 mLockThreadId = 0;
657
658 return result;
Jamie Gennis61c7ef52011-07-13 12:59:34 -0700659}
660
Glenn Kastenfff6d712012-01-12 16:38:12 -0800661status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800662{
Steve Block3856b092011-10-20 11:56:00 +0100663 ALOGV("MediaPlayer::setAudioStreamType");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800664 Mutex::Autolock _l(mLock);
665 if (mStreamType == type) return NO_ERROR;
666 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
667 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
668 // Can't change the stream type after prepare
Steve Block29357bc2012-01-06 19:20:56 +0000669 ALOGE("setAudioStream called in state %d", mCurrentState);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800670 return INVALID_OPERATION;
671 }
672 // cache
673 mStreamType = type;
674 return OK;
675}
676
John Spurlockde9453f2014-03-19 13:05:45 -0400677status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type)
678{
679 ALOGV("getAudioStreamType");
680 Mutex::Autolock _l(mLock);
681 *type = mStreamType;
682 return OK;
683}
684
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800685status_t MediaPlayer::setLooping(int loop)
686{
Steve Block3856b092011-10-20 11:56:00 +0100687 ALOGV("MediaPlayer::setLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800688 Mutex::Autolock _l(mLock);
689 mLoop = (loop != 0);
690 if (mPlayer != 0) {
691 return mPlayer->setLooping(loop);
692 }
693 return OK;
694}
695
696bool MediaPlayer::isLooping() {
Steve Block3856b092011-10-20 11:56:00 +0100697 ALOGV("isLooping");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800698 Mutex::Autolock _l(mLock);
699 if (mPlayer != 0) {
700 return mLoop;
701 }
Steve Block3856b092011-10-20 11:56:00 +0100702 ALOGV("isLooping: no active player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800703 return false;
704}
705
706status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
707{
Steve Block3856b092011-10-20 11:56:00 +0100708 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800709 Mutex::Autolock _l(mLock);
710 mLeftVolume = leftVolume;
711 mRightVolume = rightVolume;
712 if (mPlayer != 0) {
713 return mPlayer->setVolume(leftVolume, rightVolume);
714 }
715 return OK;
716}
717
Glenn Kastend848eb42016-03-08 13:42:11 -0800718status_t MediaPlayer::setAudioSessionId(audio_session_t sessionId)
Eric Laurenta514bdb2010-06-21 09:27:30 -0700719{
Steve Block3856b092011-10-20 11:56:00 +0100720 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
Eric Laurenta514bdb2010-06-21 09:27:30 -0700721 Mutex::Autolock _l(mLock);
722 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
Steve Block29357bc2012-01-06 19:20:56 +0000723 ALOGE("setAudioSessionId called in state %d", mCurrentState);
Eric Laurenta514bdb2010-06-21 09:27:30 -0700724 return INVALID_OPERATION;
725 }
726 if (sessionId < 0) {
727 return BAD_VALUE;
728 }
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700729 if (sessionId != mAudioSessionId) {
Andy Hung8b0bfd92019-12-23 13:11:11 -0800730 AudioSystem::acquireAudioSessionId(sessionId, (pid_t)-1, (uid_t)-1);
731 AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700732 mAudioSessionId = sessionId;
Marco Nelissen3a34bef2011-08-02 13:33:41 -0700733 }
Eric Laurenta514bdb2010-06-21 09:27:30 -0700734 return NO_ERROR;
735}
736
Glenn Kastend848eb42016-03-08 13:42:11 -0800737audio_session_t MediaPlayer::getAudioSessionId()
Eric Laurenta514bdb2010-06-21 09:27:30 -0700738{
739 Mutex::Autolock _l(mLock);
740 return mAudioSessionId;
741}
742
Eric Laurent2beeb502010-07-16 07:43:46 -0700743status_t MediaPlayer::setAuxEffectSendLevel(float level)
744{
Steve Block3856b092011-10-20 11:56:00 +0100745 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
Eric Laurent2beeb502010-07-16 07:43:46 -0700746 Mutex::Autolock _l(mLock);
747 mSendLevel = level;
748 if (mPlayer != 0) {
749 return mPlayer->setAuxEffectSendLevel(level);
750 }
751 return OK;
752}
753
754status_t MediaPlayer::attachAuxEffect(int effectId)
755{
Steve Block3856b092011-10-20 11:56:00 +0100756 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -0700757 Mutex::Autolock _l(mLock);
758 if (mPlayer == 0 ||
759 (mCurrentState & MEDIA_PLAYER_IDLE) ||
760 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
Wei Jia848ebc62016-03-23 14:06:46 -0700761 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
Eric Laurent2beeb502010-07-16 07:43:46 -0700762 return INVALID_OPERATION;
763 }
764
765 return mPlayer->attachAuxEffect(effectId);
766}
767
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700768// always call with lock held
769status_t MediaPlayer::checkStateForKeySet_l(int key)
770{
771 switch(key) {
772 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
773 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
774 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) {
775 // Can't change the audio attributes after prepare
776 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
777 return INVALID_OPERATION;
778 }
779 break;
780 default:
781 // parameter doesn't require player state check
782 break;
783 }
784 return OK;
785}
786
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700787status_t MediaPlayer::setParameter(int key, const Parcel& request)
788{
Steve Block3856b092011-10-20 11:56:00 +0100789 ALOGV("MediaPlayer::setParameter(%d)", key);
Eric Laurent43562692015-07-15 16:49:07 -0700790 status_t status = INVALID_OPERATION;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700791 Mutex::Autolock _l(mLock);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700792 if (checkStateForKeySet_l(key) != OK) {
Eric Laurent43562692015-07-15 16:49:07 -0700793 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700794 }
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700795 switch (key) {
796 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
Eric Laurent43562692015-07-15 16:49:07 -0700797 // save the marshalled audio attributes
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700798 if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
799 mAudioAttributesParcel = new Parcel();
800 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
Eric Laurent43562692015-07-15 16:49:07 -0700801 status = OK;
802 break;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700803 default:
Eric Laurent43562692015-07-15 16:49:07 -0700804 ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
805 break;
Jean-Michel Trivi640adb32014-09-05 11:20:11 -0700806 }
Eric Laurent43562692015-07-15 16:49:07 -0700807
808 if (mPlayer != NULL) {
809 status = mPlayer->setParameter(key, request);
810 }
811 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700812}
813
814status_t MediaPlayer::getParameter(int key, Parcel *reply)
815{
Steve Block3856b092011-10-20 11:56:00 +0100816 ALOGV("MediaPlayer::getParameter(%d)", key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700817 Mutex::Autolock _l(mLock);
818 if (mPlayer != NULL) {
Ray Essickdb122142017-01-25 17:51:55 -0800819 status_t status = mPlayer->getParameter(key, reply);
820 if (status != OK) {
821 ALOGD("getParameter returns %d", status);
822 }
823 return status;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700824 }
Steve Block3856b092011-10-20 11:56:00 +0100825 ALOGV("getParameter: no active player");
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700826 return INVALID_OPERATION;
827}
828
John Grossmanc795b642012-02-22 15:38:35 -0800829status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
830 uint16_t port) {
831 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
832 addrString ? addrString : "(null)", port);
833
834 Mutex::Autolock _l(mLock);
835 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
836 return INVALID_OPERATION;
837
838 if (NULL == addrString) {
839 mRetransmitEndpointValid = false;
840 return OK;
841 }
842
843 struct in_addr saddr;
844 if(!inet_aton(addrString, &saddr)) {
845 return BAD_VALUE;
846 }
847
Glenn Kastenbe08f6a2013-12-19 09:09:33 -0800848 memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
John Grossmanc795b642012-02-22 15:38:35 -0800849 mRetransmitEndpoint.sin_family = AF_INET;
850 mRetransmitEndpoint.sin_addr = saddr;
851 mRetransmitEndpoint.sin_port = htons(port);
852 mRetransmitEndpointValid = true;
853
854 return OK;
855}
856
Gloria Wangb483c472011-04-11 17:23:27 -0700857void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800858{
Steve Block3856b092011-10-20 11:56:00 +0100859 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800860 bool send = true;
Jason Sams1af452f2009-03-24 18:45:22 -0700861 bool locked = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800862
863 // TODO: In the future, we might be on the same thread if the app is
864 // running in the same process as the media server. In that case,
865 // this will deadlock.
Nicolas Catania66095182009-06-11 16:33:49 -0700866 //
Chong Zhangd88adb92014-07-23 11:43:46 -0700867 // The threadId hack below works around this for the care of prepare,
Wonsik Kim5f648972017-07-21 15:42:59 -0700868 // seekTo, start, and reset within the same process.
Andreas Huber5cb07aa2009-03-24 20:48:51 -0700869 // FIXME: Remember, this is a hack, it's not even a hack that is applied
870 // consistently for all use-cases, this needs to be revisited.
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700871 if (mLockThreadId != getThreadId()) {
Jason Sams1af452f2009-03-24 18:45:22 -0700872 mLock.lock();
873 locked = true;
Nicolas Catania66095182009-06-11 16:33:49 -0700874 }
Jason Sams1af452f2009-03-24 18:45:22 -0700875
Eric Laurent3b268442010-08-03 07:49:49 -0700876 // Allows calls from JNI in idle state to notify errors
877 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
Steve Block3856b092011-10-20 11:56:00 +0100878 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
Jason Sams1af452f2009-03-24 18:45:22 -0700879 if (locked) mLock.unlock(); // release the lock when done.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800880 return;
881 }
882
883 switch (msg) {
884 case MEDIA_NOP: // interface test message
885 break;
886 case MEDIA_PREPARED:
Hassan Shojania071437a2017-01-23 09:19:40 -0800887 ALOGV("MediaPlayer::notify() prepared");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800888 mCurrentState = MEDIA_PLAYER_PREPARED;
889 if (mPrepareSync) {
Steve Block3856b092011-10-20 11:56:00 +0100890 ALOGV("signal application thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800891 mPrepareSync = false;
892 mPrepareStatus = NO_ERROR;
893 mSignal.signal();
894 }
895 break;
Hassan Shojania071437a2017-01-23 09:19:40 -0800896 case MEDIA_DRM_INFO:
897 ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
898 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800899 case MEDIA_PLAYBACK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +0100900 ALOGV("playback complete");
Marco Nelissen1c1503c2010-09-17 15:04:01 -0700901 if (mCurrentState == MEDIA_PLAYER_IDLE) {
Steve Block29357bc2012-01-06 19:20:56 +0000902 ALOGE("playback complete in idle state");
Marco Nelissen1c1503c2010-09-17 15:04:01 -0700903 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800904 if (!mLoop) {
905 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
906 }
907 break;
908 case MEDIA_ERROR:
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700909 // Always log errors.
910 // ext1: Media framework error code.
911 // ext2: Implementation dependant error code.
Steve Block29357bc2012-01-06 19:20:56 +0000912 ALOGE("error (%d, %d)", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800913 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
914 if (mPrepareSync)
915 {
Steve Block3856b092011-10-20 11:56:00 +0100916 ALOGV("signal application thread");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800917 mPrepareSync = false;
918 mPrepareStatus = ext1;
919 mSignal.signal();
920 send = false;
921 }
922 break;
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700923 case MEDIA_INFO:
924 // ext1: Media framework error code.
925 // ext2: Implementation dependant error code.
Andreas Huber145e68f2011-01-11 15:05:28 -0800926 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000927 ALOGW("info/warning (%d, %d)", ext1, ext2);
Andreas Huber145e68f2011-01-11 15:05:28 -0800928 }
The Android Open Source Project65e731f2009-03-11 12:11:56 -0700929 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800930 case MEDIA_SEEK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +0100931 ALOGV("Received seek complete");
Wei Jiac5de0912016-11-18 10:22:14 -0800932 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
933 ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800934 mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800935 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
936 seekTo_l(mCurrentPosition, mCurrentSeekMode);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800937 }
938 else {
Steve Block3856b092011-10-20 11:56:00 +0100939 ALOGV("All seeks complete - return to regularly scheduled program");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800940 mCurrentPosition = mSeekPosition = -1;
Wei Jiac5de0912016-11-18 10:22:14 -0800941 mCurrentSeekMode = mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800942 }
943 break;
944 case MEDIA_BUFFERING_UPDATE:
Steve Block3856b092011-10-20 11:56:00 +0100945 ALOGV("buffering %d", ext1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800946 break;
947 case MEDIA_SET_VIDEO_SIZE:
Steve Block3856b092011-10-20 11:56:00 +0100948 ALOGV("New video size %d x %d", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800949 mVideoWidth = ext1;
950 mVideoHeight = ext2;
951 break;
Wei Jia52c28512017-09-13 18:17:51 -0700952 case MEDIA_NOTIFY_TIME:
953 ALOGV("Received notify time message");
954 break;
Gloria Wangb483c472011-04-11 17:23:27 -0700955 case MEDIA_TIMED_TEXT:
Steve Block3856b092011-10-20 11:56:00 +0100956 ALOGV("Received timed text message");
Gloria Wangb483c472011-04-11 17:23:27 -0700957 break;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700958 case MEDIA_SUBTITLE_DATA:
959 ALOGV("Received subtitle data message");
960 break;
Robert Shih08528432015-04-08 09:06:54 -0700961 case MEDIA_META_DATA:
962 ALOGV("Received timed metadata message");
963 break;
Kim Sungyeond3c6b322018-03-02 14:41:19 +0900964 case MEDIA_IMS_RX_NOTICE:
965 ALOGV("Received IMS Rx notice message");
966 break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800967 default:
Steve Block3856b092011-10-20 11:56:00 +0100968 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800969 break;
970 }
971
972 sp<MediaPlayerListener> listener = mListener;
Jason Sams1af452f2009-03-24 18:45:22 -0700973 if (locked) mLock.unlock();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800974
975 // this prevents re-entrant calls into client code
976 if ((listener != 0) && send) {
977 Mutex::Autolock _l(mNotifyLock);
Steve Block3856b092011-10-20 11:56:00 +0100978 ALOGV("callback application");
Gloria Wangb483c472011-04-11 17:23:27 -0700979 listener->notify(msg, ext1, ext2, obj);
Steve Block3856b092011-10-20 11:56:00 +0100980 ALOGV("back from callback");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800981 }
982}
983
James Dongdd172fc2010-01-15 18:13:58 -0800984void MediaPlayer::died()
985{
Steve Block3856b092011-10-20 11:56:00 +0100986 ALOGV("died");
James Dongdd172fc2010-01-15 18:13:58 -0800987 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
988}
989
Marco Nelissen6b74d672012-02-28 16:07:44 -0800990status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
Wei Jia12438692016-03-28 14:12:57 -0700991 Mutex::Autolock _l(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -0800992 if (mPlayer == NULL) {
993 return NO_INIT;
994 }
Marco Nelissenb13820f2013-08-05 12:22:43 -0700995
996 if (next != NULL && !(next->mCurrentState &
997 (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
998 ALOGE("next player is not prepared");
999 return INVALID_OPERATION;
1000 }
1001
Marco Nelissen6b74d672012-02-28 16:07:44 -08001002 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
1003}
1004
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001005VolumeShaper::Status MediaPlayer::applyVolumeShaper(
1006 const sp<VolumeShaper::Configuration>& configuration,
1007 const sp<VolumeShaper::Operation>& operation)
1008{
1009 Mutex::Autolock _l(mLock);
1010 if (mPlayer == nullptr) {
1011 return VolumeShaper::Status(NO_INIT);
1012 }
1013 VolumeShaper::Status status = mPlayer->applyVolumeShaper(configuration, operation);
1014 return status;
1015}
1016
1017sp<VolumeShaper::State> MediaPlayer::getVolumeShaperState(int id)
1018{
1019 Mutex::Autolock _l(mLock);
1020 if (mPlayer == nullptr) {
1021 return nullptr;
1022 }
1023 return mPlayer->getVolumeShaperState(id);
1024}
1025
Hassan Shojaniacefac142017-02-06 21:02:02 -08001026// Modular DRM
1027status_t MediaPlayer::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
Hassan Shojania071437a2017-01-23 09:19:40 -08001028{
Hassan Shojaniacefac142017-02-06 21:02:02 -08001029 // TODO change to ALOGV
1030 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1031 drmSessionId.array(), drmSessionId.size());
Hassan Shojania071437a2017-01-23 09:19:40 -08001032 Mutex::Autolock _l(mLock);
1033 if (mPlayer == NULL) {
1034 return NO_INIT;
1035 }
1036
Hassan Shojania838be392017-05-23 14:14:24 -07001037 // Only allowed it in player's preparing/prepared state.
1038 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1039 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1040 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1041 if (!(mCurrentState & (MEDIA_PLAYER_PREPARING | MEDIA_PLAYER_PREPARED))) {
1042 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
Hassan Shojania071437a2017-01-23 09:19:40 -08001043 return INVALID_OPERATION;
1044 }
1045
Hassan Shojaniacefac142017-02-06 21:02:02 -08001046 if (drmSessionId.isEmpty()) {
1047 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1048 return INVALID_OPERATION;
1049 }
Hassan Shojania071437a2017-01-23 09:19:40 -08001050
Hassan Shojaniacefac142017-02-06 21:02:02 -08001051 // Passing down to mediaserver mainly for creating the crypto
1052 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1053 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1054
1055 // TODO change to ALOGV
1056 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1057
1058 return status;
Hassan Shojania071437a2017-01-23 09:19:40 -08001059}
1060
1061status_t MediaPlayer::releaseDrm()
1062{
1063 Mutex::Autolock _l(mLock);
1064 if (mPlayer == NULL) {
1065 return NO_INIT;
1066 }
1067
Hassan Shojaniacefac142017-02-06 21:02:02 -08001068 // Not allowing releaseDrm in an active/resumable state
1069 if (mCurrentState & (MEDIA_PLAYER_STARTED |
1070 MEDIA_PLAYER_PAUSED |
1071 MEDIA_PLAYER_PLAYBACK_COMPLETE |
1072 MEDIA_PLAYER_STATE_ERROR)) {
1073 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
Hassan Shojania071437a2017-01-23 09:19:40 -08001074 return INVALID_OPERATION;
1075 }
1076
Hassan Shojaniacefac142017-02-06 21:02:02 -08001077 status_t status = mPlayer->releaseDrm();
1078 // TODO change to ALOGV
1079 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1080 if (status != OK) {
1081 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1082 // Overriding to OK so the client proceed with its own cleanup
1083 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1084 status = OK;
Hassan Shojania071437a2017-01-23 09:19:40 -08001085 }
1086
Hassan Shojaniacefac142017-02-06 21:02:02 -08001087 return status;
Hassan Shojania071437a2017-01-23 09:19:40 -08001088}
1089
jiabin156c6872017-10-06 09:47:15 -07001090status_t MediaPlayer::setOutputDevice(audio_port_handle_t deviceId)
1091{
1092 Mutex::Autolock _l(mLock);
1093 if (mPlayer == NULL) {
1094 ALOGV("setOutputDevice: player not init");
1095 return NO_INIT;
1096 }
1097 return mPlayer->setOutputDevice(deviceId);
1098}
1099
1100audio_port_handle_t MediaPlayer::getRoutedDeviceId()
1101{
1102 Mutex::Autolock _l(mLock);
1103 if (mPlayer == NULL) {
1104 ALOGV("getRoutedDeviceId: player not init");
1105 return AUDIO_PORT_HANDLE_NONE;
1106 }
1107 audio_port_handle_t deviceId;
1108 status_t status = mPlayer->getRoutedDeviceId(&deviceId);
1109 if (status != NO_ERROR) {
1110 return AUDIO_PORT_HANDLE_NONE;
1111 }
1112 return deviceId;
1113}
1114
1115status_t MediaPlayer::enableAudioDeviceCallback(bool enabled)
1116{
1117 Mutex::Autolock _l(mLock);
1118 if (mPlayer == NULL) {
1119 ALOGV("addAudioDeviceCallback: player not init");
1120 return NO_INIT;
1121 }
1122 return mPlayer->enableAudioDeviceCallback(enabled);
1123}
1124
Glenn Kasten40bc9062015-03-20 09:09:33 -07001125} // namespace android