blob: f43205920f1a101dca785ccef64880f6b8397d08 [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2**
3** Copyright 2017, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaPlayer2Native"
20
Wei Jia53692fa2017-12-11 10:33:46 -080021#include <binder/IServiceManager.h>
22#include <binder/IPCThreadState.h>
23
Wei Jia53692fa2017-12-11 10:33:46 -080024#include <media/AudioSystem.h>
Wei Jiac2636032018-02-01 09:15:25 -080025#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080026#include <media/MediaAnalyticsItem.h>
Wei Jiaec044b02018-02-19 12:41:23 -080027#include <media/MemoryLeakTrackUtil.h>
28#include <media/Metadata.h>
Wei Jia28288fb2017-12-15 13:45:29 -080029#include <media/NdkWrapper.h>
Wei Jiaec044b02018-02-19 12:41:23 -080030#include <media/stagefright/foundation/ADebug.h>
31#include <media/stagefright/foundation/ALooperRoster.h>
32#include <mediaplayer2/MediaPlayer2AudioOutput.h>
Wei Jia51b69562018-02-05 16:17:13 -080033#include <mediaplayer2/mediaplayer2.h>
Wei Jia53692fa2017-12-11 10:33:46 -080034
Wei Jiaec044b02018-02-19 12:41:23 -080035#include <utils/Log.h>
36#include <utils/SortedVector.h>
Wei Jia53692fa2017-12-11 10:33:46 -080037#include <utils/String8.h>
38
39#include <system/audio.h>
40#include <system/window.h>
41
Wei Jiaec044b02018-02-19 12:41:23 -080042#include <nuplayer2/NuPlayer2Driver.h>
43
44#include <dirent.h>
45#include <sys/stat.h>
Wei Jia53692fa2017-12-11 10:33:46 -080046
47namespace android {
48
Wei Jiaec044b02018-02-19 12:41:23 -080049extern ALooperRoster gLooperRoster;
50
51namespace {
52
53const int kDumpLockRetries = 50;
54const int kDumpLockSleepUs = 20000;
55
Wei Jiaec044b02018-02-19 12:41:23 -080056class proxyListener : public MediaPlayer2InterfaceListener {
57public:
58 proxyListener(const wp<MediaPlayer2> &player)
59 : mPlayer(player) { }
60
61 ~proxyListener() { };
62
Dongwon Kang41929fb2018-09-09 08:29:56 -070063 virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
64 const PlayerMessage *obj) override {
Wei Jiaec044b02018-02-19 12:41:23 -080065 sp<MediaPlayer2> player = mPlayer.promote();
66 if (player != NULL) {
67 player->notify(srcId, msg, ext1, ext2, obj);
68 }
69 }
70
71private:
72 wp<MediaPlayer2> mPlayer;
73};
74
75Mutex sRecordLock;
76SortedVector<wp<MediaPlayer2> > *sPlayers;
77
78void ensureInit_l() {
79 if (sPlayers == NULL) {
80 sPlayers = new SortedVector<wp<MediaPlayer2> >();
81 }
82}
83
84void addPlayer(const wp<MediaPlayer2>& player) {
85 Mutex::Autolock lock(sRecordLock);
86 ensureInit_l();
87 sPlayers->add(player);
88}
89
90void removePlayer(const wp<MediaPlayer2>& player) {
91 Mutex::Autolock lock(sRecordLock);
92 ensureInit_l();
93 sPlayers->remove(player);
94}
95
96/**
97 * The only arguments this understands right now are -c, -von and -voff,
98 * which are parsed by ALooperRoster::dump()
99 */
100status_t dumpPlayers(int fd, const Vector<String16>& args) {
101 const size_t SIZE = 256;
102 char buffer[SIZE];
103 String8 result;
104 SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
105
106 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
107 snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
108 result.append(buffer);
109 } else {
110 {
111 Mutex::Autolock lock(sRecordLock);
112 ensureInit_l();
113 for (int i = 0, n = sPlayers->size(); i < n; ++i) {
114 sp<MediaPlayer2> p = (*sPlayers)[i].promote();
115 if (p != 0) {
116 p->dump(fd, args);
117 }
118 players.add(p);
119 }
120 }
121
122 result.append(" Files opened and/or mapped:\n");
123 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
124 FILE *f = fopen(buffer, "r");
125 if (f) {
126 while (!feof(f)) {
127 fgets(buffer, SIZE, f);
128 if (strstr(buffer, " /storage/") ||
129 strstr(buffer, " /system/sounds/") ||
130 strstr(buffer, " /data/") ||
131 strstr(buffer, " /system/media/")) {
132 result.append(" ");
133 result.append(buffer);
134 }
135 }
136 fclose(f);
137 } else {
138 result.append("couldn't open ");
139 result.append(buffer);
140 result.append("\n");
141 }
142
143 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
144 DIR *d = opendir(buffer);
145 if (d) {
146 struct dirent *ent;
147 while((ent = readdir(d)) != NULL) {
148 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
149 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
150 struct stat s;
151 if (lstat(buffer, &s) == 0) {
152 if ((s.st_mode & S_IFMT) == S_IFLNK) {
153 char linkto[256];
154 int len = readlink(buffer, linkto, sizeof(linkto));
155 if(len > 0) {
156 if(len > 255) {
157 linkto[252] = '.';
158 linkto[253] = '.';
159 linkto[254] = '.';
160 linkto[255] = 0;
161 } else {
162 linkto[len] = 0;
163 }
164 if (strstr(linkto, "/storage/") == linkto ||
165 strstr(linkto, "/system/sounds/") == linkto ||
166 strstr(linkto, "/data/") == linkto ||
167 strstr(linkto, "/system/media/") == linkto) {
168 result.append(" ");
169 result.append(buffer);
170 result.append(" -> ");
171 result.append(linkto);
172 result.append("\n");
173 }
174 }
175 } else {
176 result.append(" unexpected type for ");
177 result.append(buffer);
178 result.append("\n");
179 }
180 }
181 }
182 }
183 closedir(d);
184 } else {
185 result.append("couldn't open ");
186 result.append(buffer);
187 result.append("\n");
188 }
189
190 gLooperRoster.dump(fd, args);
191
192 bool dumpMem = false;
193 bool unreachableMemory = false;
194 for (size_t i = 0; i < args.size(); i++) {
195 if (args[i] == String16("-m")) {
196 dumpMem = true;
197 } else if (args[i] == String16("--unreachable")) {
198 unreachableMemory = true;
199 }
200 }
201 if (dumpMem) {
202 result.append("\nDumping memory:\n");
203 std::string s = dumpMemoryAddresses(100 /* limit */);
204 result.append(s.c_str(), s.size());
205 }
206 if (unreachableMemory) {
207 result.append("\nDumping unreachable memory:\n");
208 // TODO - should limit be an argument parameter?
209 // TODO: enable GetUnreachableMemoryString if it's part of stable API
210 //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
211 //result.append(s.c_str(), s.size());
212 }
213 }
214 write(fd, result.string(), result.size());
215 return NO_ERROR;
216}
217
218} // anonymous namespace
219
220//static
Dichen Zhang23658642018-11-15 10:26:16 -0800221sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
222 sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
Wei Jiaec044b02018-02-19 12:41:23 -0800223
224 if (!player->init()) {
225 return NULL;
226 }
227
228 ALOGV("Create new player(%p)", player.get());
229
230 addPlayer(player);
231 return player;
232}
233
234// static
235status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
236 return dumpPlayers(fd, args);
237}
238
Dichen Zhang23658642018-11-15 10:26:16 -0800239MediaPlayer2::MediaPlayer2(int32_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800240 ALOGV("constructor");
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800241 mSrcId = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800242 mLockThreadId = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800243 mListener = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800244 mStreamType = AUDIO_STREAM_MUSIC;
Dichen Zhangc2465c52018-11-12 11:56:05 -0800245 mAudioAttributes = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800246 mCurrentPosition = -1;
247 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
248 mSeekPosition = -1;
249 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
250 mCurrentState = MEDIA_PLAYER2_IDLE;
Wei Jia53692fa2017-12-11 10:33:46 -0800251 mLoop = false;
Dichen Zhang7398ca02018-10-15 10:25:12 -0700252 mVolume = 1.0;
Wei Jia53692fa2017-12-11 10:33:46 -0800253 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800254 mSendLevel = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800255
256 // TODO: get pid and uid from JAVA
257 mPid = IPCThreadState::self()->getCallingPid();
258 mUid = IPCThreadState::self()->getCallingUid();
259
Dichen Zhang23658642018-11-15 10:26:16 -0800260 mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
Wei Jia53692fa2017-12-11 10:33:46 -0800261}
262
Wei Jiaec044b02018-02-19 12:41:23 -0800263MediaPlayer2::~MediaPlayer2() {
Wei Jia53692fa2017-12-11 10:33:46 -0800264 ALOGV("destructor");
Wei Jia53692fa2017-12-11 10:33:46 -0800265 disconnect();
Wei Jiaec044b02018-02-19 12:41:23 -0800266 removePlayer(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800267}
268
Wei Jiaec044b02018-02-19 12:41:23 -0800269bool MediaPlayer2::init() {
270 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
271 // looper for notification.
272 return true;
273}
274
275void MediaPlayer2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800276 ALOGV("disconnect");
Wei Jiaec044b02018-02-19 12:41:23 -0800277 sp<MediaPlayer2Interface> p;
Wei Jia53692fa2017-12-11 10:33:46 -0800278 {
279 Mutex::Autolock _l(mLock);
280 p = mPlayer;
281 mPlayer.clear();
282 }
283
284 if (p != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800285 p->setListener(NULL);
286 p->reset();
287 }
288
289 {
290 Mutex::Autolock _l(mLock);
291 disconnectNativeWindow_l();
Wei Jia53692fa2017-12-11 10:33:46 -0800292 }
293}
294
Wei Jiaec044b02018-02-19 12:41:23 -0800295void MediaPlayer2::clear_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800296 mCurrentPosition = -1;
297 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
298 mSeekPosition = -1;
299 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
300 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800301}
302
Wei Jiaec044b02018-02-19 12:41:23 -0800303status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
Wei Jia53692fa2017-12-11 10:33:46 -0800304 ALOGV("setListener");
305 Mutex::Autolock _l(mLock);
306 mListener = listener;
307 return NO_ERROR;
308}
309
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800310status_t MediaPlayer2::getSrcId(int64_t *srcId) {
311 if (srcId == NULL) {
312 return BAD_VALUE;
313 }
Wei Jia53692fa2017-12-11 10:33:46 -0800314
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800315 Mutex::Autolock _l(mLock);
316 *srcId = mSrcId;
317 return OK;
318}
319
Wei Jiaec044b02018-02-19 12:41:23 -0800320status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jiac2636032018-02-01 09:15:25 -0800321 if (dsd == NULL) {
322 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800323 }
Wei Jiaf01e3122018-10-18 11:49:44 -0700324 // Microsecond is used in NuPlayer2.
Wei Jiae31ac8a2018-10-25 11:06:21 -0700325 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
326 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700327 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
328 }
Wei Jiae31ac8a2018-10-25 11:06:21 -0700329 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
330 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700331 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
332 }
Wei Jiaec044b02018-02-19 12:41:23 -0800333 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
334
335 sp<MediaPlayer2Interface> oldPlayer;
336
337 Mutex::Autolock _l(mLock);
338 {
339 if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
340 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
341 ALOGE("setDataSource called in wrong state %d", mCurrentState);
342 return INVALID_OPERATION;
343 }
344
345 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
346 status_t err = player->initCheck();
347 if (err != NO_ERROR) {
348 ALOGE("Failed to create player object, initCheck failed(%d)", err);
349 return err;
350 }
351
352 clear_l();
353
354 player->setListener(new proxyListener(this));
Wei Jiaec044b02018-02-19 12:41:23 -0800355 player->setAudioSink(mAudioOutput);
356
357 err = player->setDataSource(dsd);
358 if (err != OK) {
359 ALOGE("setDataSource error: %d", err);
360 return err;
361 }
362
363 sp<MediaPlayer2Interface> oldPlayer = mPlayer;
364 mPlayer = player;
365 mSrcId = dsd->mId;
366 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
Wei Jia53692fa2017-12-11 10:33:46 -0800367 }
Wei Jiaec044b02018-02-19 12:41:23 -0800368
369 if (oldPlayer != NULL) {
370 oldPlayer->setListener(NULL);
371 oldPlayer->reset();
372 }
373
374 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800375}
376
Wei Jia57aeffd2018-02-15 16:01:14 -0800377status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
378 if (dsd == NULL) {
379 return BAD_VALUE;
380 }
381 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
382
383 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800384 if (mPlayer == NULL) {
385 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
386 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800387 }
Wei Jiaec044b02018-02-19 12:41:23 -0800388 return mPlayer->prepareNextDataSource(dsd);
Wei Jia57aeffd2018-02-15 16:01:14 -0800389}
390
391status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
392 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
393
394 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800395 if (mPlayer == NULL) {
396 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
397 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800398 }
Wei Jiaec044b02018-02-19 12:41:23 -0800399 mSrcId = srcId;
400 return mPlayer->playNextDataSource(srcId);
Wei Jia57aeffd2018-02-15 16:01:14 -0800401}
402
Dongwon Kang9f631982018-07-10 12:34:41 -0700403status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800404 Mutex::Autolock _l(mLock);
405 const bool hasBeenInitialized =
406 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
407 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
Wei Jiaec044b02018-02-19 12:41:23 -0800408 if ((mPlayer == NULL) || !hasBeenInitialized) {
Dongwon Kang9f631982018-07-10 12:34:41 -0700409 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Wei Jiaec044b02018-02-19 12:41:23 -0800410 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800411 }
Wei Jiaec044b02018-02-19 12:41:23 -0800412 return mPlayer->invoke(request, reply);
Wei Jia53692fa2017-12-11 10:33:46 -0800413}
414
Wei Jiaec044b02018-02-19 12:41:23 -0800415void MediaPlayer2::disconnectNativeWindow_l() {
416 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
417 status_t err = native_window_api_disconnect(
418 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
419
420 if (err != OK) {
421 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
422 strerror(-err), err);
423 }
424 }
425 mConnectedWindow.clear();
426}
427
428status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
429 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
430 ALOGV("setVideoSurfaceTexture(%p)", anw);
431 Mutex::Autolock _l(mLock);
432 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800433 return NO_INIT;
434 }
Wei Jiaec044b02018-02-19 12:41:23 -0800435
436 if (anw != NULL) {
437 if (mConnectedWindow != NULL
438 && mConnectedWindow->getANativeWindow() == anw) {
439 return OK;
440 }
441 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
442
443 if (err != OK) {
444 ALOGE("setVideoSurfaceTexture failed: %d", err);
445 // Note that we must do the reset before disconnecting from the ANW.
446 // Otherwise queue/dequeue calls could be made on the disconnected
447 // ANW, which may result in errors.
448 mPlayer->reset();
449 disconnectNativeWindow_l();
450 return err;
451 }
452 }
453
454 // Note that we must set the player's new GraphicBufferProducer before
455 // disconnecting the old one. Otherwise queue/dequeue calls could be made
456 // on the disconnected ANW, which may result in errors.
457 status_t err = mPlayer->setVideoSurfaceTexture(nww);
458
459 disconnectNativeWindow_l();
460
461 if (err == OK) {
462 mConnectedWindow = nww;
463 mLock.unlock();
464 } else if (anw != NULL) {
465 mLock.unlock();
466 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
467
468 if (err != OK) {
469 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
470 strerror(-err), err);
471 }
472 }
473
474 return err;
Wei Jia53692fa2017-12-11 10:33:46 -0800475}
476
Wei Jiaec044b02018-02-19 12:41:23 -0800477status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800478 ALOGV("getBufferingSettings");
479
480 Mutex::Autolock _l(mLock);
481 if (mPlayer == 0) {
482 return NO_INIT;
483 }
Wei Jiaec044b02018-02-19 12:41:23 -0800484
485 status_t ret = mPlayer->getBufferingSettings(buffering);
486 if (ret == NO_ERROR) {
487 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
488 } else {
489 ALOGE("getBufferingSettings returned %d", ret);
490 }
491 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800492}
493
Wei Jiaec044b02018-02-19 12:41:23 -0800494status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
495 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Wei Jia53692fa2017-12-11 10:33:46 -0800496
497 Mutex::Autolock _l(mLock);
498 if (mPlayer == 0) {
499 return NO_INIT;
500 }
501 return mPlayer->setBufferingSettings(buffering);
502}
503
Dichen Zhangc2465c52018-11-12 11:56:05 -0800504status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
505 if (mAudioOutput != NULL) {
506 mAudioOutput->setAudioAttributes(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800507 }
508 return NO_ERROR;
509}
510
511status_t MediaPlayer2::prepareAsync() {
512 ALOGV("prepareAsync");
513 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700514 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
Dichen Zhangc2465c52018-11-12 11:56:05 -0800515 if (mAudioAttributes != NULL) {
516 status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
Wei Jiaec044b02018-02-19 12:41:23 -0800517 if (err != OK) {
518 return err;
519 }
Wei Jia53692fa2017-12-11 10:33:46 -0800520 }
521 mCurrentState = MEDIA_PLAYER2_PREPARING;
522 return mPlayer->prepareAsync();
523 }
524 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
525 return INVALID_OPERATION;
526}
527
Wei Jiaec044b02018-02-19 12:41:23 -0800528status_t MediaPlayer2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800529 ALOGV("start");
530
531 status_t ret = NO_ERROR;
532 Mutex::Autolock _l(mLock);
533
534 mLockThreadId = getThreadId();
535
536 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
537 ret = NO_ERROR;
538 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
539 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
540 mPlayer->setLooping(mLoop);
Wei Jiaec044b02018-02-19 12:41:23 -0800541
542 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700543 mAudioOutput->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800544 }
545
546 if (mAudioOutput != 0) {
547 mAudioOutput->setAuxEffectSendLevel(mSendLevel);
548 }
Wei Jia53692fa2017-12-11 10:33:46 -0800549 mCurrentState = MEDIA_PLAYER2_STARTED;
550 ret = mPlayer->start();
551 if (ret != NO_ERROR) {
552 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
553 } else {
554 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
555 ALOGV("playback completed immediately following start()");
556 }
557 }
558 } else {
559 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
560 ret = INVALID_OPERATION;
561 }
562
563 mLockThreadId = 0;
564
565 return ret;
566}
567
Wei Jiaec044b02018-02-19 12:41:23 -0800568status_t MediaPlayer2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800569 ALOGV("pause");
570 Mutex::Autolock _l(mLock);
571 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
572 return NO_ERROR;
Wei Jia6376cd52018-09-26 11:42:55 -0700573 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
Wei Jia53692fa2017-12-11 10:33:46 -0800574 status_t ret = mPlayer->pause();
575 if (ret != NO_ERROR) {
576 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
577 } else {
578 mCurrentState = MEDIA_PLAYER2_PAUSED;
579 }
580 return ret;
581 }
582 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
583 return INVALID_OPERATION;
584}
585
Wei Jiaec044b02018-02-19 12:41:23 -0800586bool MediaPlayer2::isPlaying() {
Wei Jia53692fa2017-12-11 10:33:46 -0800587 Mutex::Autolock _l(mLock);
588 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800589 bool temp = mPlayer->isPlaying();
Wei Jia53692fa2017-12-11 10:33:46 -0800590 ALOGV("isPlaying: %d", temp);
591 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
592 ALOGE("internal/external state mismatch corrected");
593 mCurrentState = MEDIA_PLAYER2_PAUSED;
594 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
595 ALOGE("internal/external state mismatch corrected");
596 mCurrentState = MEDIA_PLAYER2_STARTED;
597 }
598 return temp;
599 }
600 ALOGV("isPlaying: no active player");
601 return false;
602}
603
Wei Jia1f043e42018-06-20 16:52:50 -0700604mediaplayer2_states MediaPlayer2::getState() {
Wei Jia98787a72018-03-02 14:33:06 -0800605 Mutex::Autolock _l(mLock);
606 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
607 return MEDIAPLAYER2_STATE_ERROR;
608 }
609 if (mPlayer == 0
610 || (mCurrentState &
611 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
612 return MEDIAPLAYER2_STATE_IDLE;
613 }
614 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
615 return MEDIAPLAYER2_STATE_PLAYING;
616 }
Wei Jia0151ef42018-08-24 16:40:21 -0700617 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
Wei Jia98787a72018-03-02 14:33:06 -0800618 return MEDIAPLAYER2_STATE_PAUSED;
619 }
620 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
621 return MEDIAPLAYER2_STATE_PREPARED;
622}
623
Wei Jiaec044b02018-02-19 12:41:23 -0800624status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
Wei Jia53692fa2017-12-11 10:33:46 -0800625 ALOGV("setPlaybackSettings: %f %f %d %d",
626 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
627 // Negative speed and pitch does not make sense. Further validation will
628 // be done by the respective mediaplayers.
Wei Jiaec044b02018-02-19 12:41:23 -0800629 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
Wei Jia53692fa2017-12-11 10:33:46 -0800630 return BAD_VALUE;
631 }
632 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700633 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800634 return INVALID_OPERATION;
635 }
636
Wei Jia53692fa2017-12-11 10:33:46 -0800637 status_t err = mPlayer->setPlaybackSettings(rate);
Wei Jia53692fa2017-12-11 10:33:46 -0800638 return err;
639}
640
Wei Jiaec044b02018-02-19 12:41:23 -0800641status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800642 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800643 if (mPlayer == 0) {
644 return INVALID_OPERATION;
645 }
Wei Jiaec044b02018-02-19 12:41:23 -0800646 status_t ret = mPlayer->getPlaybackSettings(rate);
647 if (ret == NO_ERROR) {
648 ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
649 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
650 } else {
651 ALOGV("getPlaybackSettings returned %d", ret);
652 }
653 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800654}
655
Wei Jiaec044b02018-02-19 12:41:23 -0800656status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
Wei Jia53692fa2017-12-11 10:33:46 -0800657 ALOGV("setSyncSettings: %u %u %f %f",
658 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
659 Mutex::Autolock _l(mLock);
660 if (mPlayer == 0) return INVALID_OPERATION;
661 return mPlayer->setSyncSettings(sync, videoFpsHint);
662}
663
664status_t MediaPlayer2::getSyncSettings(
Wei Jiaec044b02018-02-19 12:41:23 -0800665 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800666 Mutex::Autolock _l(mLock);
Wei Jia334adf02018-03-23 14:08:23 -0700667 if (mPlayer == 0) {
668 return INVALID_OPERATION;
669 }
Wei Jiaec044b02018-02-19 12:41:23 -0800670 status_t ret = mPlayer->getSyncSettings(sync, videoFps);
671 if (ret == NO_ERROR) {
672 ALOGV("getSyncSettings(%u, %u, %f, %f)",
673 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
674 } else {
675 ALOGV("getSyncSettings returned %d", ret);
676 }
677 return ret;
678
Wei Jia53692fa2017-12-11 10:33:46 -0800679}
680
Wei Jiaec044b02018-02-19 12:41:23 -0800681status_t MediaPlayer2::getVideoWidth(int *w) {
Wei Jia53692fa2017-12-11 10:33:46 -0800682 ALOGV("getVideoWidth");
683 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800684 if (mPlayer == 0) {
685 return INVALID_OPERATION;
686 }
Wei Jia53692fa2017-12-11 10:33:46 -0800687 *w = mVideoWidth;
688 return NO_ERROR;
689}
690
Wei Jiaec044b02018-02-19 12:41:23 -0800691status_t MediaPlayer2::getVideoHeight(int *h) {
Wei Jia53692fa2017-12-11 10:33:46 -0800692 ALOGV("getVideoHeight");
693 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800694 if (mPlayer == 0) {
695 return INVALID_OPERATION;
696 }
Wei Jia53692fa2017-12-11 10:33:46 -0800697 *h = mVideoHeight;
698 return NO_ERROR;
699}
700
Wei Jia800fe372018-02-20 15:00:45 -0800701status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800702 ALOGV("getCurrentPosition");
703 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800704 if (mPlayer == 0) {
705 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800706 }
Wei Jiaec044b02018-02-19 12:41:23 -0800707 if (mCurrentPosition >= 0) {
Wei Jia800fe372018-02-20 15:00:45 -0800708 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
Wei Jiaec044b02018-02-19 12:41:23 -0800709 *msec = mCurrentPosition;
710 return NO_ERROR;
711 }
712 status_t ret = mPlayer->getCurrentPosition(msec);
713 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800714 ALOGV("getCurrentPosition = %lld", (long long)*msec);
Wei Jiaec044b02018-02-19 12:41:23 -0800715 } else {
716 ALOGE("getCurrentPosition returned %d", ret);
717 }
718 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800719}
720
Wei Jia17944af2018-12-13 18:13:10 -0800721status_t MediaPlayer2::getDuration(int64_t srcId, int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800722 Mutex::Autolock _l(mLock);
Wei Jia17944af2018-12-13 18:13:10 -0800723 // TODO: cache duration for currentSrcId and nextSrcId, and return correct
724 // value for nextSrcId.
725 if (srcId != mSrcId) {
726 *msec = -1;
727 return OK;
728 }
729
Wei Jia53692fa2017-12-11 10:33:46 -0800730 ALOGV("getDuration_l");
731 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700732 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800733 if (mPlayer == 0 || !isValidState) {
734 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
735 mPlayer.get(), mCurrentState);
736 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800737 }
Wei Jia800fe372018-02-20 15:00:45 -0800738 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800739 status_t ret = mPlayer->getDuration(&durationMs);
740
741 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800742 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800743 } else {
744 ALOGE("getDuration returned %d", ret);
745 // Do not enter error state just because no duration was available.
746 durationMs = -1;
747 }
748
749 if (msec) {
750 *msec = durationMs;
751 }
752 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800753}
754
Wei Jia800fe372018-02-20 15:00:45 -0800755status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
756 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
757 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
758 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
759 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
760 mPlayer.get(), mCurrentState);
761 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800762 }
Wei Jia800fe372018-02-20 15:00:45 -0800763 if (msec < 0) {
764 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
765 msec = 0;
766 }
767
768 int64_t durationMs;
769 status_t err = mPlayer->getDuration(&durationMs);
770
771 if (err != OK) {
772 ALOGW("Stream has no duration and is therefore not seekable.");
773 return err;
774 }
775
776 if (msec > durationMs) {
777 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
778 (long long)msec, (long long)durationMs);
779
780 msec = durationMs;
781 }
782
783 // cache duration
784 mCurrentPosition = msec;
785 mCurrentSeekMode = mode;
786 if (mSeekPosition < 0) {
787 mSeekPosition = msec;
788 mSeekMode = mode;
789 return mPlayer->seekTo(msec, mode);
790 }
791 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
792 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800793}
794
Wei Jia800fe372018-02-20 15:00:45 -0800795status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800796 mLockThreadId = getThreadId();
797 Mutex::Autolock _l(mLock);
798 status_t result = seekTo_l(msec, mode);
799 mLockThreadId = 0;
800
801 return result;
802}
803
Wei Jiaec044b02018-02-19 12:41:23 -0800804status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800805 Mutex::Autolock _l(mLock);
806 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800807 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800808 }
Wei Jiaec044b02018-02-19 12:41:23 -0800809
810 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800811}
812
Wei Jiaec044b02018-02-19 12:41:23 -0800813status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800814 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800815 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
816 return NO_ERROR;
817 }
Wei Jia53692fa2017-12-11 10:33:46 -0800818 if (mPlayer != 0) {
819 status_t ret = mPlayer->reset();
820 if (ret != NO_ERROR) {
821 ALOGE("reset() failed with return code (%d)", ret);
822 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
823 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800824 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800825 mCurrentState = MEDIA_PLAYER2_IDLE;
826 }
827 // setDataSource has to be called again to create a
828 // new mediaplayer.
829 mPlayer = 0;
830 return ret;
831 }
832 clear_l();
833 return NO_ERROR;
834}
835
Wei Jiaec044b02018-02-19 12:41:23 -0800836status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800837 ALOGV("reset");
838 mLockThreadId = getThreadId();
839 Mutex::Autolock _l(mLock);
840 status_t result = reset_l();
841 mLockThreadId = 0;
842
843 return result;
844}
845
Wei Jiaec044b02018-02-19 12:41:23 -0800846status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800847 ALOGV("MediaPlayer2::setAudioStreamType");
848 Mutex::Autolock _l(mLock);
849 if (mStreamType == type) return NO_ERROR;
850 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
851 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
852 // Can't change the stream type after prepare
853 ALOGE("setAudioStream called in state %d", mCurrentState);
854 return INVALID_OPERATION;
855 }
856 // cache
857 mStreamType = type;
858 return OK;
859}
860
Wei Jiaec044b02018-02-19 12:41:23 -0800861status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800862 ALOGV("getAudioStreamType");
863 Mutex::Autolock _l(mLock);
864 *type = mStreamType;
865 return OK;
866}
867
Wei Jiaec044b02018-02-19 12:41:23 -0800868status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800869 ALOGV("MediaPlayer2::setLooping");
870 Mutex::Autolock _l(mLock);
871 mLoop = (loop != 0);
872 if (mPlayer != 0) {
873 return mPlayer->setLooping(loop);
874 }
875 return OK;
876}
877
878bool MediaPlayer2::isLooping() {
879 ALOGV("isLooping");
880 Mutex::Autolock _l(mLock);
881 if (mPlayer != 0) {
882 return mLoop;
883 }
884 ALOGV("isLooping: no active player");
885 return false;
886}
887
Dichen Zhang7398ca02018-10-15 10:25:12 -0700888status_t MediaPlayer2::setVolume(float volume) {
889 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800890 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700891 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800892 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700893 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800894 }
895 return OK;
896}
897
Dichen Zhang23658642018-11-15 10:26:16 -0800898status_t MediaPlayer2::setAudioSessionId(int32_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800899 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
900 Mutex::Autolock _l(mLock);
901 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
902 ALOGE("setAudioSessionId called in state %d", mCurrentState);
903 return INVALID_OPERATION;
904 }
905 if (sessionId < 0) {
906 return BAD_VALUE;
907 }
Dichen Zhang23658642018-11-15 10:26:16 -0800908 if (mAudioOutput != NULL && sessionId != mAudioOutput->getSessionId()) {
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000909 mAudioOutput->setSessionId(sessionId);
910 }
Wei Jia53692fa2017-12-11 10:33:46 -0800911 return NO_ERROR;
912}
913
Dichen Zhang23658642018-11-15 10:26:16 -0800914int32_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800915 Mutex::Autolock _l(mLock);
Dichen Zhang23658642018-11-15 10:26:16 -0800916 if (mAudioOutput != NULL) {
917 return mAudioOutput->getSessionId();
918 }
919 return 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800920}
921
Wei Jiaec044b02018-02-19 12:41:23 -0800922status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800923 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
924 Mutex::Autolock _l(mLock);
925 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800926 if (mAudioOutput != 0) {
927 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -0800928 }
929 return OK;
930}
931
Wei Jiaec044b02018-02-19 12:41:23 -0800932status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800933 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
934 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800935 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -0800936 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
937 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
938 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
939 return INVALID_OPERATION;
940 }
941
Wei Jiaec044b02018-02-19 12:41:23 -0800942 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -0800943}
944
945// always call with lock held
Dichen Zhangc2465c52018-11-12 11:56:05 -0800946status_t MediaPlayer2::checkState_l() {
947 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
948 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
949 // Can't change the audio attributes after prepare
950 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
951 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800952 }
953 return OK;
954}
955
Dichen Zhangc2465c52018-11-12 11:56:05 -0800956status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
957 ALOGV("MediaPlayer2::setAudioAttributes");
Wei Jia53692fa2017-12-11 10:33:46 -0800958 status_t status = INVALID_OPERATION;
959 Mutex::Autolock _l(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800960 if (checkState_l() != OK) {
Wei Jia53692fa2017-12-11 10:33:46 -0800961 return status;
962 }
Dichen Zhangc2465c52018-11-12 11:56:05 -0800963 mAudioAttributes = new JObjectHolder(attributes);
964 status = setAudioAttributes_l(attributes);
Wei Jia53692fa2017-12-11 10:33:46 -0800965 return status;
966}
967
Dichen Zhangc2465c52018-11-12 11:56:05 -0800968jobject MediaPlayer2::getAudioAttributes() {
969 ALOGV("MediaPlayer2::getAudioAttributes)");
970 Mutex::Autolock _l(mLock);
971 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
972}
973
Wei Jiaec044b02018-02-19 12:41:23 -0800974status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800975 ALOGV("MediaPlayer2::getParameter(%d)", key);
976 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800977 if (mPlayer == NULL) {
978 ALOGV("getParameter: no active player");
979 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800980 }
Wei Jiaec044b02018-02-19 12:41:23 -0800981
982 status_t status = mPlayer->getParameter(key, reply);
983 if (status != OK) {
984 ALOGD("getParameter returns %d", status);
985 }
986 return status;
Wei Jia53692fa2017-12-11 10:33:46 -0800987}
988
Dongwon Kang41929fb2018-09-09 08:29:56 -0700989void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800990 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
991 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -0800992
Wei Jia53692fa2017-12-11 10:33:46 -0800993 bool send = true;
994 bool locked = false;
995
996 // TODO: In the future, we might be on the same thread if the app is
997 // running in the same process as the media server. In that case,
998 // this will deadlock.
999 //
1000 // The threadId hack below works around this for the care of prepare,
1001 // seekTo, start, and reset within the same process.
1002 // FIXME: Remember, this is a hack, it's not even a hack that is applied
1003 // consistently for all use-cases, this needs to be revisited.
1004 if (mLockThreadId != getThreadId()) {
1005 mLock.lock();
1006 locked = true;
1007 }
1008
1009 // Allows calls from JNI in idle state to notify errors
1010 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001011 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1012 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001013 if (locked) mLock.unlock(); // release the lock when done.
1014 return;
1015 }
1016
1017 switch (msg) {
1018 case MEDIA2_NOP: // interface test message
1019 break;
1020 case MEDIA2_PREPARED:
1021 ALOGV("MediaPlayer2::notify() prepared");
1022 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001023 break;
1024 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001025 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1026 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001027 break;
1028 case MEDIA2_PLAYBACK_COMPLETE:
1029 ALOGV("playback complete");
1030 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1031 ALOGE("playback complete in idle state");
1032 }
1033 if (!mLoop) {
1034 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1035 }
1036 break;
1037 case MEDIA2_ERROR:
1038 // Always log errors.
1039 // ext1: Media framework error code.
1040 // ext2: Implementation dependant error code.
1041 ALOGE("error (%d, %d)", ext1, ext2);
1042 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001043 break;
1044 case MEDIA2_INFO:
1045 // ext1: Media framework error code.
1046 // ext2: Implementation dependant error code.
1047 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1048 ALOGW("info/warning (%d, %d)", ext1, ext2);
1049 }
1050 break;
1051 case MEDIA2_SEEK_COMPLETE:
1052 ALOGV("Received seek complete");
1053 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001054 ALOGV("Executing queued seekTo(%lld, %d)",
1055 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001056 mSeekPosition = -1;
1057 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1058 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1059 }
1060 else {
1061 ALOGV("All seeks complete - return to regularly scheduled program");
1062 mCurrentPosition = mSeekPosition = -1;
1063 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1064 }
1065 break;
1066 case MEDIA2_BUFFERING_UPDATE:
1067 ALOGV("buffering %d", ext1);
1068 break;
1069 case MEDIA2_SET_VIDEO_SIZE:
1070 ALOGV("New video size %d x %d", ext1, ext2);
1071 mVideoWidth = ext1;
1072 mVideoHeight = ext2;
1073 break;
1074 case MEDIA2_NOTIFY_TIME:
1075 ALOGV("Received notify time message");
1076 break;
1077 case MEDIA2_TIMED_TEXT:
1078 ALOGV("Received timed text message");
1079 break;
1080 case MEDIA2_SUBTITLE_DATA:
1081 ALOGV("Received subtitle data message");
1082 break;
1083 case MEDIA2_META_DATA:
1084 ALOGV("Received timed metadata message");
1085 break;
1086 default:
1087 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1088 break;
1089 }
1090
1091 sp<MediaPlayer2Listener> listener = mListener;
1092 if (locked) mLock.unlock();
1093
1094 // this prevents re-entrant calls into client code
1095 if ((listener != 0) && send) {
1096 Mutex::Autolock _l(mNotifyLock);
1097 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001098 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001099 ALOGV("back from callback");
1100 }
1101}
1102
Wei Jia53692fa2017-12-11 10:33:46 -08001103// Modular DRM
Robert Shih3c3728d2018-12-04 17:06:36 -08001104status_t MediaPlayer2::prepareDrm(
1105 int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001106 // TODO change to ALOGV
1107 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1108 drmSessionId.array(), drmSessionId.size());
1109 Mutex::Autolock _l(mLock);
1110 if (mPlayer == NULL) {
1111 return NO_INIT;
1112 }
1113
1114 // Only allowed it in player's preparing/prepared state.
1115 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1116 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1117 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1118 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
1119 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
1120 return INVALID_OPERATION;
1121 }
1122
1123 if (drmSessionId.isEmpty()) {
1124 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1125 return INVALID_OPERATION;
1126 }
1127
1128 // Passing down to mediaserver mainly for creating the crypto
Robert Shih3c3728d2018-12-04 17:06:36 -08001129 status_t status = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
Wei Jia53692fa2017-12-11 10:33:46 -08001130 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1131
1132 // TODO change to ALOGV
1133 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1134
1135 return status;
1136}
1137
Robert Shih3c3728d2018-12-04 17:06:36 -08001138status_t MediaPlayer2::releaseDrm(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001139 Mutex::Autolock _l(mLock);
1140 if (mPlayer == NULL) {
1141 return NO_INIT;
1142 }
1143
1144 // Not allowing releaseDrm in an active/resumable state
1145 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
1146 MEDIA_PLAYER2_PAUSED |
1147 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
1148 MEDIA_PLAYER2_STATE_ERROR)) {
1149 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
1150 return INVALID_OPERATION;
1151 }
1152
Robert Shih3c3728d2018-12-04 17:06:36 -08001153 status_t status = mPlayer->releaseDrm(srcId);
Wei Jia53692fa2017-12-11 10:33:46 -08001154 // TODO change to ALOGV
1155 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1156 if (status != OK) {
1157 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1158 // Overriding to OK so the client proceed with its own cleanup
1159 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1160 status = OK;
1161 }
1162
1163 return status;
1164}
1165
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001166status_t MediaPlayer2::setPreferredDevice(jobject device) {
Wei Jia53692fa2017-12-11 10:33:46 -08001167 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001168 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001169 ALOGV("setPreferredDevice: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001170 return NO_INIT;
1171 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001172 return mAudioOutput->setPreferredDevice(device);
Wei Jia53692fa2017-12-11 10:33:46 -08001173}
1174
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001175jobject MediaPlayer2::getRoutedDevice() {
Wei Jia53692fa2017-12-11 10:33:46 -08001176 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001177 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001178 ALOGV("getRoutedDevice: audio sink not init");
1179 return nullptr;
Wei Jia53692fa2017-12-11 10:33:46 -08001180 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001181 return mAudioOutput->getRoutedDevice();
Wei Jia53692fa2017-12-11 10:33:46 -08001182}
1183
Dichen Zhangf8726912018-10-17 13:31:26 -07001184status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
1185 Mutex::Autolock _l(mLock);
1186 if (mAudioOutput == NULL) {
1187 ALOGV("addAudioDeviceCallback: player not init");
Dichen Zhangf8726912018-10-17 13:31:26 -07001188 return NO_INIT;
1189 }
1190 return mAudioOutput->addAudioDeviceCallback(routingDelegate);
1191}
1192
1193status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
Wei Jia53692fa2017-12-11 10:33:46 -08001194 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001195 if (mAudioOutput == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001196 ALOGV("addAudioDeviceCallback: player not init");
1197 return NO_INIT;
1198 }
Dichen Zhangf8726912018-10-17 13:31:26 -07001199 return mAudioOutput->removeAudioDeviceCallback(listener);
Wei Jiaec044b02018-02-19 12:41:23 -08001200}
1201
1202status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
1203 const size_t SIZE = 256;
1204 char buffer[SIZE];
1205 String8 result;
1206 result.append(" MediaPlayer2\n");
1207 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
1208 result.append(buffer);
1209
1210 sp<MediaPlayer2Interface> player;
1211 sp<MediaPlayer2AudioOutput> audioOutput;
1212 bool locked = false;
1213 for (int i = 0; i < kDumpLockRetries; ++i) {
1214 if (mLock.tryLock() == NO_ERROR) {
1215 locked = true;
1216 break;
1217 }
1218 usleep(kDumpLockSleepUs);
1219 }
1220
1221 if (locked) {
1222 player = mPlayer;
1223 audioOutput = mAudioOutput;
1224 mLock.unlock();
1225 } else {
1226 result.append(" lock is taken, no dump from player and audio output\n");
1227 }
1228 write(fd, result.string(), result.size());
1229
1230 if (player != NULL) {
1231 player->dump(fd, args);
1232 }
1233 if (audioOutput != 0) {
1234 audioOutput->dump(fd, args);
1235 }
1236 write(fd, "\n", 1);
1237 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001238}
1239
1240} // namespace android