blob: 04a6f68892f2bfaf0bb82439f2d16596c5452dd1 [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
221sp<MediaPlayer2> MediaPlayer2::Create() {
222 sp<MediaPlayer2> player = new MediaPlayer2();
223
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
239MediaPlayer2::MediaPlayer2() {
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 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
255 AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
256 mSendLevel = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800257
258 // TODO: get pid and uid from JAVA
259 mPid = IPCThreadState::self()->getCallingPid();
260 mUid = IPCThreadState::self()->getCallingUid();
261
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000262 mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid, mPid, NULL /*attributes*/);
Wei Jia53692fa2017-12-11 10:33:46 -0800263}
264
Wei Jiaec044b02018-02-19 12:41:23 -0800265MediaPlayer2::~MediaPlayer2() {
Wei Jia53692fa2017-12-11 10:33:46 -0800266 ALOGV("destructor");
Wei Jia53692fa2017-12-11 10:33:46 -0800267 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
268 disconnect();
Wei Jiaec044b02018-02-19 12:41:23 -0800269 removePlayer(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800270}
271
Wei Jiaec044b02018-02-19 12:41:23 -0800272bool MediaPlayer2::init() {
273 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
274 // looper for notification.
275 return true;
276}
277
278void MediaPlayer2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800279 ALOGV("disconnect");
Wei Jiaec044b02018-02-19 12:41:23 -0800280 sp<MediaPlayer2Interface> p;
Wei Jia53692fa2017-12-11 10:33:46 -0800281 {
282 Mutex::Autolock _l(mLock);
283 p = mPlayer;
284 mPlayer.clear();
285 }
286
287 if (p != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800288 p->setListener(NULL);
289 p->reset();
290 }
291
292 {
293 Mutex::Autolock _l(mLock);
294 disconnectNativeWindow_l();
Wei Jia53692fa2017-12-11 10:33:46 -0800295 }
296}
297
Wei Jiaec044b02018-02-19 12:41:23 -0800298void MediaPlayer2::clear_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800299 mCurrentPosition = -1;
300 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
301 mSeekPosition = -1;
302 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
303 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800304}
305
Wei Jiaec044b02018-02-19 12:41:23 -0800306status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
Wei Jia53692fa2017-12-11 10:33:46 -0800307 ALOGV("setListener");
308 Mutex::Autolock _l(mLock);
309 mListener = listener;
310 return NO_ERROR;
311}
312
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800313status_t MediaPlayer2::getSrcId(int64_t *srcId) {
314 if (srcId == NULL) {
315 return BAD_VALUE;
316 }
Wei Jia53692fa2017-12-11 10:33:46 -0800317
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800318 Mutex::Autolock _l(mLock);
319 *srcId = mSrcId;
320 return OK;
321}
322
Wei Jiaec044b02018-02-19 12:41:23 -0800323status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jiac2636032018-02-01 09:15:25 -0800324 if (dsd == NULL) {
325 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800326 }
Wei Jiaf01e3122018-10-18 11:49:44 -0700327 // Microsecond is used in NuPlayer2.
Wei Jiae31ac8a2018-10-25 11:06:21 -0700328 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
329 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700330 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
331 }
Wei Jiae31ac8a2018-10-25 11:06:21 -0700332 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
333 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700334 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
335 }
Wei Jiaec044b02018-02-19 12:41:23 -0800336 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
337
338 sp<MediaPlayer2Interface> oldPlayer;
339
340 Mutex::Autolock _l(mLock);
341 {
342 if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
343 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
344 ALOGE("setDataSource called in wrong state %d", mCurrentState);
345 return INVALID_OPERATION;
346 }
347
348 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
349 status_t err = player->initCheck();
350 if (err != NO_ERROR) {
351 ALOGE("Failed to create player object, initCheck failed(%d)", err);
352 return err;
353 }
354
355 clear_l();
356
357 player->setListener(new proxyListener(this));
Wei Jiaec044b02018-02-19 12:41:23 -0800358 player->setAudioSink(mAudioOutput);
359
360 err = player->setDataSource(dsd);
361 if (err != OK) {
362 ALOGE("setDataSource error: %d", err);
363 return err;
364 }
365
366 sp<MediaPlayer2Interface> oldPlayer = mPlayer;
367 mPlayer = player;
368 mSrcId = dsd->mId;
369 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
Wei Jia53692fa2017-12-11 10:33:46 -0800370 }
Wei Jiaec044b02018-02-19 12:41:23 -0800371
372 if (oldPlayer != NULL) {
373 oldPlayer->setListener(NULL);
374 oldPlayer->reset();
375 }
376
377 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800378}
379
Wei Jia57aeffd2018-02-15 16:01:14 -0800380status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
381 if (dsd == NULL) {
382 return BAD_VALUE;
383 }
384 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
385
386 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800387 if (mPlayer == NULL) {
388 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
389 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800390 }
Wei Jiaec044b02018-02-19 12:41:23 -0800391 return mPlayer->prepareNextDataSource(dsd);
Wei Jia57aeffd2018-02-15 16:01:14 -0800392}
393
394status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
395 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
396
397 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800398 if (mPlayer == NULL) {
399 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
400 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800401 }
Wei Jiaec044b02018-02-19 12:41:23 -0800402 mSrcId = srcId;
403 return mPlayer->playNextDataSource(srcId);
Wei Jia57aeffd2018-02-15 16:01:14 -0800404}
405
Dongwon Kang9f631982018-07-10 12:34:41 -0700406status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800407 Mutex::Autolock _l(mLock);
408 const bool hasBeenInitialized =
409 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
410 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
Wei Jiaec044b02018-02-19 12:41:23 -0800411 if ((mPlayer == NULL) || !hasBeenInitialized) {
Dongwon Kang9f631982018-07-10 12:34:41 -0700412 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Wei Jiaec044b02018-02-19 12:41:23 -0800413 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800414 }
Wei Jiaec044b02018-02-19 12:41:23 -0800415 return mPlayer->invoke(request, reply);
Wei Jia53692fa2017-12-11 10:33:46 -0800416}
417
Wei Jiaec044b02018-02-19 12:41:23 -0800418void MediaPlayer2::disconnectNativeWindow_l() {
419 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
420 status_t err = native_window_api_disconnect(
421 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
422
423 if (err != OK) {
424 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
425 strerror(-err), err);
426 }
427 }
428 mConnectedWindow.clear();
429}
430
431status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
432 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
433 ALOGV("setVideoSurfaceTexture(%p)", anw);
434 Mutex::Autolock _l(mLock);
435 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800436 return NO_INIT;
437 }
Wei Jiaec044b02018-02-19 12:41:23 -0800438
439 if (anw != NULL) {
440 if (mConnectedWindow != NULL
441 && mConnectedWindow->getANativeWindow() == anw) {
442 return OK;
443 }
444 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
445
446 if (err != OK) {
447 ALOGE("setVideoSurfaceTexture failed: %d", err);
448 // Note that we must do the reset before disconnecting from the ANW.
449 // Otherwise queue/dequeue calls could be made on the disconnected
450 // ANW, which may result in errors.
451 mPlayer->reset();
452 disconnectNativeWindow_l();
453 return err;
454 }
455 }
456
457 // Note that we must set the player's new GraphicBufferProducer before
458 // disconnecting the old one. Otherwise queue/dequeue calls could be made
459 // on the disconnected ANW, which may result in errors.
460 status_t err = mPlayer->setVideoSurfaceTexture(nww);
461
462 disconnectNativeWindow_l();
463
464 if (err == OK) {
465 mConnectedWindow = nww;
466 mLock.unlock();
467 } else if (anw != NULL) {
468 mLock.unlock();
469 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
470
471 if (err != OK) {
472 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
473 strerror(-err), err);
474 }
475 }
476
477 return err;
Wei Jia53692fa2017-12-11 10:33:46 -0800478}
479
Wei Jiaec044b02018-02-19 12:41:23 -0800480status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800481 ALOGV("getBufferingSettings");
482
483 Mutex::Autolock _l(mLock);
484 if (mPlayer == 0) {
485 return NO_INIT;
486 }
Wei Jiaec044b02018-02-19 12:41:23 -0800487
488 status_t ret = mPlayer->getBufferingSettings(buffering);
489 if (ret == NO_ERROR) {
490 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
491 } else {
492 ALOGE("getBufferingSettings returned %d", ret);
493 }
494 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800495}
496
Wei Jiaec044b02018-02-19 12:41:23 -0800497status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
498 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Wei Jia53692fa2017-12-11 10:33:46 -0800499
500 Mutex::Autolock _l(mLock);
501 if (mPlayer == 0) {
502 return NO_INIT;
503 }
504 return mPlayer->setBufferingSettings(buffering);
505}
506
Dichen Zhangc2465c52018-11-12 11:56:05 -0800507status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
508 if (mAudioOutput != NULL) {
509 mAudioOutput->setAudioAttributes(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800510 }
511 return NO_ERROR;
512}
513
514status_t MediaPlayer2::prepareAsync() {
515 ALOGV("prepareAsync");
516 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700517 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
Dichen Zhangc2465c52018-11-12 11:56:05 -0800518 if (mAudioAttributes != NULL) {
519 status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
Wei Jiaec044b02018-02-19 12:41:23 -0800520 if (err != OK) {
521 return err;
522 }
Wei Jia53692fa2017-12-11 10:33:46 -0800523 }
524 mCurrentState = MEDIA_PLAYER2_PREPARING;
525 return mPlayer->prepareAsync();
526 }
527 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
528 return INVALID_OPERATION;
529}
530
Wei Jiaec044b02018-02-19 12:41:23 -0800531status_t MediaPlayer2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800532 ALOGV("start");
533
534 status_t ret = NO_ERROR;
535 Mutex::Autolock _l(mLock);
536
537 mLockThreadId = getThreadId();
538
539 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
540 ret = NO_ERROR;
541 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
542 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
543 mPlayer->setLooping(mLoop);
Wei Jiaec044b02018-02-19 12:41:23 -0800544
545 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700546 mAudioOutput->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800547 }
548
549 if (mAudioOutput != 0) {
550 mAudioOutput->setAuxEffectSendLevel(mSendLevel);
551 }
Wei Jia53692fa2017-12-11 10:33:46 -0800552 mCurrentState = MEDIA_PLAYER2_STARTED;
553 ret = mPlayer->start();
554 if (ret != NO_ERROR) {
555 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
556 } else {
557 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
558 ALOGV("playback completed immediately following start()");
559 }
560 }
561 } else {
562 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
563 ret = INVALID_OPERATION;
564 }
565
566 mLockThreadId = 0;
567
568 return ret;
569}
570
Wei Jiaec044b02018-02-19 12:41:23 -0800571status_t MediaPlayer2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800572 ALOGV("pause");
573 Mutex::Autolock _l(mLock);
574 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
575 return NO_ERROR;
Wei Jia6376cd52018-09-26 11:42:55 -0700576 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
Wei Jia53692fa2017-12-11 10:33:46 -0800577 status_t ret = mPlayer->pause();
578 if (ret != NO_ERROR) {
579 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
580 } else {
581 mCurrentState = MEDIA_PLAYER2_PAUSED;
582 }
583 return ret;
584 }
585 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
586 return INVALID_OPERATION;
587}
588
Wei Jiaec044b02018-02-19 12:41:23 -0800589bool MediaPlayer2::isPlaying() {
Wei Jia53692fa2017-12-11 10:33:46 -0800590 Mutex::Autolock _l(mLock);
591 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800592 bool temp = mPlayer->isPlaying();
Wei Jia53692fa2017-12-11 10:33:46 -0800593 ALOGV("isPlaying: %d", temp);
594 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
595 ALOGE("internal/external state mismatch corrected");
596 mCurrentState = MEDIA_PLAYER2_PAUSED;
597 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
598 ALOGE("internal/external state mismatch corrected");
599 mCurrentState = MEDIA_PLAYER2_STARTED;
600 }
601 return temp;
602 }
603 ALOGV("isPlaying: no active player");
604 return false;
605}
606
Wei Jia1f043e42018-06-20 16:52:50 -0700607mediaplayer2_states MediaPlayer2::getState() {
Wei Jia98787a72018-03-02 14:33:06 -0800608 Mutex::Autolock _l(mLock);
609 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
610 return MEDIAPLAYER2_STATE_ERROR;
611 }
612 if (mPlayer == 0
613 || (mCurrentState &
614 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
615 return MEDIAPLAYER2_STATE_IDLE;
616 }
617 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
618 return MEDIAPLAYER2_STATE_PLAYING;
619 }
Wei Jia0151ef42018-08-24 16:40:21 -0700620 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
Wei Jia98787a72018-03-02 14:33:06 -0800621 return MEDIAPLAYER2_STATE_PAUSED;
622 }
623 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
624 return MEDIAPLAYER2_STATE_PREPARED;
625}
626
Wei Jiaec044b02018-02-19 12:41:23 -0800627status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
Wei Jia53692fa2017-12-11 10:33:46 -0800628 ALOGV("setPlaybackSettings: %f %f %d %d",
629 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
630 // Negative speed and pitch does not make sense. Further validation will
631 // be done by the respective mediaplayers.
Wei Jiaec044b02018-02-19 12:41:23 -0800632 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
Wei Jia53692fa2017-12-11 10:33:46 -0800633 return BAD_VALUE;
634 }
635 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700636 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800637 return INVALID_OPERATION;
638 }
639
Wei Jia53692fa2017-12-11 10:33:46 -0800640 status_t err = mPlayer->setPlaybackSettings(rate);
Wei Jia53692fa2017-12-11 10:33:46 -0800641 return err;
642}
643
Wei Jiaec044b02018-02-19 12:41:23 -0800644status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800645 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800646 if (mPlayer == 0) {
647 return INVALID_OPERATION;
648 }
Wei Jiaec044b02018-02-19 12:41:23 -0800649 status_t ret = mPlayer->getPlaybackSettings(rate);
650 if (ret == NO_ERROR) {
651 ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
652 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
653 } else {
654 ALOGV("getPlaybackSettings returned %d", ret);
655 }
656 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800657}
658
Wei Jiaec044b02018-02-19 12:41:23 -0800659status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
Wei Jia53692fa2017-12-11 10:33:46 -0800660 ALOGV("setSyncSettings: %u %u %f %f",
661 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
662 Mutex::Autolock _l(mLock);
663 if (mPlayer == 0) return INVALID_OPERATION;
664 return mPlayer->setSyncSettings(sync, videoFpsHint);
665}
666
667status_t MediaPlayer2::getSyncSettings(
Wei Jiaec044b02018-02-19 12:41:23 -0800668 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800669 Mutex::Autolock _l(mLock);
Wei Jia334adf02018-03-23 14:08:23 -0700670 if (mPlayer == 0) {
671 return INVALID_OPERATION;
672 }
Wei Jiaec044b02018-02-19 12:41:23 -0800673 status_t ret = mPlayer->getSyncSettings(sync, videoFps);
674 if (ret == NO_ERROR) {
675 ALOGV("getSyncSettings(%u, %u, %f, %f)",
676 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
677 } else {
678 ALOGV("getSyncSettings returned %d", ret);
679 }
680 return ret;
681
Wei Jia53692fa2017-12-11 10:33:46 -0800682}
683
Wei Jiaec044b02018-02-19 12:41:23 -0800684status_t MediaPlayer2::getVideoWidth(int *w) {
Wei Jia53692fa2017-12-11 10:33:46 -0800685 ALOGV("getVideoWidth");
686 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800687 if (mPlayer == 0) {
688 return INVALID_OPERATION;
689 }
Wei Jia53692fa2017-12-11 10:33:46 -0800690 *w = mVideoWidth;
691 return NO_ERROR;
692}
693
Wei Jiaec044b02018-02-19 12:41:23 -0800694status_t MediaPlayer2::getVideoHeight(int *h) {
Wei Jia53692fa2017-12-11 10:33:46 -0800695 ALOGV("getVideoHeight");
696 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800697 if (mPlayer == 0) {
698 return INVALID_OPERATION;
699 }
Wei Jia53692fa2017-12-11 10:33:46 -0800700 *h = mVideoHeight;
701 return NO_ERROR;
702}
703
Wei Jia800fe372018-02-20 15:00:45 -0800704status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800705 ALOGV("getCurrentPosition");
706 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800707 if (mPlayer == 0) {
708 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800709 }
Wei Jiaec044b02018-02-19 12:41:23 -0800710 if (mCurrentPosition >= 0) {
Wei Jia800fe372018-02-20 15:00:45 -0800711 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
Wei Jiaec044b02018-02-19 12:41:23 -0800712 *msec = mCurrentPosition;
713 return NO_ERROR;
714 }
715 status_t ret = mPlayer->getCurrentPosition(msec);
716 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800717 ALOGV("getCurrentPosition = %lld", (long long)*msec);
Wei Jiaec044b02018-02-19 12:41:23 -0800718 } else {
719 ALOGE("getCurrentPosition returned %d", ret);
720 }
721 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800722}
723
Wei Jia800fe372018-02-20 15:00:45 -0800724status_t MediaPlayer2::getDuration(int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800725 Mutex::Autolock _l(mLock);
Wei Jia53692fa2017-12-11 10:33:46 -0800726 ALOGV("getDuration_l");
727 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700728 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800729 if (mPlayer == 0 || !isValidState) {
730 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
731 mPlayer.get(), mCurrentState);
732 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800733 }
Wei Jia800fe372018-02-20 15:00:45 -0800734 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800735 status_t ret = mPlayer->getDuration(&durationMs);
736
737 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800738 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800739 } else {
740 ALOGE("getDuration returned %d", ret);
741 // Do not enter error state just because no duration was available.
742 durationMs = -1;
743 }
744
745 if (msec) {
746 *msec = durationMs;
747 }
748 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800749}
750
Wei Jia800fe372018-02-20 15:00:45 -0800751status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
752 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
753 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
754 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
755 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
756 mPlayer.get(), mCurrentState);
757 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800758 }
Wei Jia800fe372018-02-20 15:00:45 -0800759 if (msec < 0) {
760 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
761 msec = 0;
762 }
763
764 int64_t durationMs;
765 status_t err = mPlayer->getDuration(&durationMs);
766
767 if (err != OK) {
768 ALOGW("Stream has no duration and is therefore not seekable.");
769 return err;
770 }
771
772 if (msec > durationMs) {
773 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
774 (long long)msec, (long long)durationMs);
775
776 msec = durationMs;
777 }
778
779 // cache duration
780 mCurrentPosition = msec;
781 mCurrentSeekMode = mode;
782 if (mSeekPosition < 0) {
783 mSeekPosition = msec;
784 mSeekMode = mode;
785 return mPlayer->seekTo(msec, mode);
786 }
787 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
788 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800789}
790
Wei Jia800fe372018-02-20 15:00:45 -0800791status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800792 mLockThreadId = getThreadId();
793 Mutex::Autolock _l(mLock);
794 status_t result = seekTo_l(msec, mode);
795 mLockThreadId = 0;
796
797 return result;
798}
799
Wei Jiaec044b02018-02-19 12:41:23 -0800800status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800801 Mutex::Autolock _l(mLock);
802 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800803 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800804 }
Wei Jiaec044b02018-02-19 12:41:23 -0800805
806 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800807}
808
Wei Jiaec044b02018-02-19 12:41:23 -0800809status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800810 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800811 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
812 return NO_ERROR;
813 }
Wei Jia53692fa2017-12-11 10:33:46 -0800814 if (mPlayer != 0) {
815 status_t ret = mPlayer->reset();
816 if (ret != NO_ERROR) {
817 ALOGE("reset() failed with return code (%d)", ret);
818 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
819 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800820 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800821 mCurrentState = MEDIA_PLAYER2_IDLE;
822 }
823 // setDataSource has to be called again to create a
824 // new mediaplayer.
825 mPlayer = 0;
826 return ret;
827 }
828 clear_l();
829 return NO_ERROR;
830}
831
Wei Jiaec044b02018-02-19 12:41:23 -0800832status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800833 ALOGV("reset");
834 mLockThreadId = getThreadId();
835 Mutex::Autolock _l(mLock);
836 status_t result = reset_l();
837 mLockThreadId = 0;
838
839 return result;
840}
841
Wei Jiaec044b02018-02-19 12:41:23 -0800842status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800843 ALOGV("MediaPlayer2::setAudioStreamType");
844 Mutex::Autolock _l(mLock);
845 if (mStreamType == type) return NO_ERROR;
846 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
847 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
848 // Can't change the stream type after prepare
849 ALOGE("setAudioStream called in state %d", mCurrentState);
850 return INVALID_OPERATION;
851 }
852 // cache
853 mStreamType = type;
854 return OK;
855}
856
Wei Jiaec044b02018-02-19 12:41:23 -0800857status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800858 ALOGV("getAudioStreamType");
859 Mutex::Autolock _l(mLock);
860 *type = mStreamType;
861 return OK;
862}
863
Wei Jiaec044b02018-02-19 12:41:23 -0800864status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800865 ALOGV("MediaPlayer2::setLooping");
866 Mutex::Autolock _l(mLock);
867 mLoop = (loop != 0);
868 if (mPlayer != 0) {
869 return mPlayer->setLooping(loop);
870 }
871 return OK;
872}
873
874bool MediaPlayer2::isLooping() {
875 ALOGV("isLooping");
876 Mutex::Autolock _l(mLock);
877 if (mPlayer != 0) {
878 return mLoop;
879 }
880 ALOGV("isLooping: no active player");
881 return false;
882}
883
Dichen Zhang7398ca02018-10-15 10:25:12 -0700884status_t MediaPlayer2::setVolume(float volume) {
885 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800886 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700887 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800888 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700889 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800890 }
891 return OK;
892}
893
Wei Jiaec044b02018-02-19 12:41:23 -0800894status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800895 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
896 Mutex::Autolock _l(mLock);
897 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
898 ALOGE("setAudioSessionId called in state %d", mCurrentState);
899 return INVALID_OPERATION;
900 }
901 if (sessionId < 0) {
902 return BAD_VALUE;
903 }
904 if (sessionId != mAudioSessionId) {
905 AudioSystem::acquireAudioSessionId(sessionId, -1);
906 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
907 mAudioSessionId = sessionId;
908 }
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000909 if (mAudioOutput != NULL && mAudioSessionId != mAudioOutput->getSessionId()) {
910 mAudioOutput->setSessionId(sessionId);
911 }
Wei Jia53692fa2017-12-11 10:33:46 -0800912 return NO_ERROR;
913}
914
Wei Jiaec044b02018-02-19 12:41:23 -0800915audio_session_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800916 Mutex::Autolock _l(mLock);
917 return mAudioSessionId;
918}
919
Wei Jiaec044b02018-02-19 12:41:23 -0800920status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800921 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
922 Mutex::Autolock _l(mLock);
923 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800924 if (mAudioOutput != 0) {
925 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -0800926 }
927 return OK;
928}
929
Wei Jiaec044b02018-02-19 12:41:23 -0800930status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800931 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
932 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800933 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -0800934 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
935 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
936 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
937 return INVALID_OPERATION;
938 }
939
Wei Jiaec044b02018-02-19 12:41:23 -0800940 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -0800941}
942
943// always call with lock held
Dichen Zhangc2465c52018-11-12 11:56:05 -0800944status_t MediaPlayer2::checkState_l() {
945 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
946 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
947 // Can't change the audio attributes after prepare
948 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
949 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800950 }
951 return OK;
952}
953
Dichen Zhangc2465c52018-11-12 11:56:05 -0800954status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
955 ALOGV("MediaPlayer2::setAudioAttributes");
Wei Jia53692fa2017-12-11 10:33:46 -0800956 status_t status = INVALID_OPERATION;
957 Mutex::Autolock _l(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800958 if (checkState_l() != OK) {
Wei Jia53692fa2017-12-11 10:33:46 -0800959 return status;
960 }
Dichen Zhangc2465c52018-11-12 11:56:05 -0800961 mAudioAttributes = new JObjectHolder(attributes);
962 status = setAudioAttributes_l(attributes);
Wei Jia53692fa2017-12-11 10:33:46 -0800963 return status;
964}
965
Dichen Zhangc2465c52018-11-12 11:56:05 -0800966jobject MediaPlayer2::getAudioAttributes() {
967 ALOGV("MediaPlayer2::getAudioAttributes)");
968 Mutex::Autolock _l(mLock);
969 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
970}
971
Wei Jiaec044b02018-02-19 12:41:23 -0800972status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800973 ALOGV("MediaPlayer2::getParameter(%d)", key);
974 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800975 if (mPlayer == NULL) {
976 ALOGV("getParameter: no active player");
977 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800978 }
Wei Jiaec044b02018-02-19 12:41:23 -0800979
980 status_t status = mPlayer->getParameter(key, reply);
981 if (status != OK) {
982 ALOGD("getParameter returns %d", status);
983 }
984 return status;
Wei Jia53692fa2017-12-11 10:33:46 -0800985}
986
Dongwon Kang41929fb2018-09-09 08:29:56 -0700987void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800988 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
989 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -0800990
Wei Jia53692fa2017-12-11 10:33:46 -0800991 bool send = true;
992 bool locked = false;
993
994 // TODO: In the future, we might be on the same thread if the app is
995 // running in the same process as the media server. In that case,
996 // this will deadlock.
997 //
998 // The threadId hack below works around this for the care of prepare,
999 // seekTo, start, and reset within the same process.
1000 // FIXME: Remember, this is a hack, it's not even a hack that is applied
1001 // consistently for all use-cases, this needs to be revisited.
1002 if (mLockThreadId != getThreadId()) {
1003 mLock.lock();
1004 locked = true;
1005 }
1006
1007 // Allows calls from JNI in idle state to notify errors
1008 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001009 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1010 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001011 if (locked) mLock.unlock(); // release the lock when done.
1012 return;
1013 }
1014
1015 switch (msg) {
1016 case MEDIA2_NOP: // interface test message
1017 break;
1018 case MEDIA2_PREPARED:
1019 ALOGV("MediaPlayer2::notify() prepared");
1020 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001021 break;
1022 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001023 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1024 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001025 break;
1026 case MEDIA2_PLAYBACK_COMPLETE:
1027 ALOGV("playback complete");
1028 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1029 ALOGE("playback complete in idle state");
1030 }
1031 if (!mLoop) {
1032 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1033 }
1034 break;
1035 case MEDIA2_ERROR:
1036 // Always log errors.
1037 // ext1: Media framework error code.
1038 // ext2: Implementation dependant error code.
1039 ALOGE("error (%d, %d)", ext1, ext2);
1040 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001041 break;
1042 case MEDIA2_INFO:
1043 // ext1: Media framework error code.
1044 // ext2: Implementation dependant error code.
1045 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1046 ALOGW("info/warning (%d, %d)", ext1, ext2);
1047 }
1048 break;
1049 case MEDIA2_SEEK_COMPLETE:
1050 ALOGV("Received seek complete");
1051 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001052 ALOGV("Executing queued seekTo(%lld, %d)",
1053 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001054 mSeekPosition = -1;
1055 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1056 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1057 }
1058 else {
1059 ALOGV("All seeks complete - return to regularly scheduled program");
1060 mCurrentPosition = mSeekPosition = -1;
1061 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1062 }
1063 break;
1064 case MEDIA2_BUFFERING_UPDATE:
1065 ALOGV("buffering %d", ext1);
1066 break;
1067 case MEDIA2_SET_VIDEO_SIZE:
1068 ALOGV("New video size %d x %d", ext1, ext2);
1069 mVideoWidth = ext1;
1070 mVideoHeight = ext2;
1071 break;
1072 case MEDIA2_NOTIFY_TIME:
1073 ALOGV("Received notify time message");
1074 break;
1075 case MEDIA2_TIMED_TEXT:
1076 ALOGV("Received timed text message");
1077 break;
1078 case MEDIA2_SUBTITLE_DATA:
1079 ALOGV("Received subtitle data message");
1080 break;
1081 case MEDIA2_META_DATA:
1082 ALOGV("Received timed metadata message");
1083 break;
1084 default:
1085 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1086 break;
1087 }
1088
1089 sp<MediaPlayer2Listener> listener = mListener;
1090 if (locked) mLock.unlock();
1091
1092 // this prevents re-entrant calls into client code
1093 if ((listener != 0) && send) {
1094 Mutex::Autolock _l(mNotifyLock);
1095 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001096 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001097 ALOGV("back from callback");
1098 }
1099}
1100
Wei Jia53692fa2017-12-11 10:33:46 -08001101// Modular DRM
Wei Jiaec044b02018-02-19 12:41:23 -08001102status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001103 // TODO change to ALOGV
1104 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1105 drmSessionId.array(), drmSessionId.size());
1106 Mutex::Autolock _l(mLock);
1107 if (mPlayer == NULL) {
1108 return NO_INIT;
1109 }
1110
1111 // Only allowed it in player's preparing/prepared state.
1112 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1113 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1114 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1115 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
1116 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
1117 return INVALID_OPERATION;
1118 }
1119
1120 if (drmSessionId.isEmpty()) {
1121 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1122 return INVALID_OPERATION;
1123 }
1124
1125 // Passing down to mediaserver mainly for creating the crypto
1126 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1127 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1128
1129 // TODO change to ALOGV
1130 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1131
1132 return status;
1133}
1134
Wei Jiaec044b02018-02-19 12:41:23 -08001135status_t MediaPlayer2::releaseDrm() {
Wei Jia53692fa2017-12-11 10:33:46 -08001136 Mutex::Autolock _l(mLock);
1137 if (mPlayer == NULL) {
1138 return NO_INIT;
1139 }
1140
1141 // Not allowing releaseDrm in an active/resumable state
1142 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
1143 MEDIA_PLAYER2_PAUSED |
1144 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
1145 MEDIA_PLAYER2_STATE_ERROR)) {
1146 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
1147 return INVALID_OPERATION;
1148 }
1149
1150 status_t status = mPlayer->releaseDrm();
1151 // TODO change to ALOGV
1152 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1153 if (status != OK) {
1154 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1155 // Overriding to OK so the client proceed with its own cleanup
1156 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1157 status = OK;
1158 }
1159
1160 return status;
1161}
1162
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001163status_t MediaPlayer2::setPreferredDevice(jobject device) {
Wei Jia53692fa2017-12-11 10:33:46 -08001164 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001165 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001166 ALOGV("setPreferredDevice: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001167 return NO_INIT;
1168 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001169 return mAudioOutput->setPreferredDevice(device);
Wei Jia53692fa2017-12-11 10:33:46 -08001170}
1171
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001172jobject MediaPlayer2::getRoutedDevice() {
Wei Jia53692fa2017-12-11 10:33:46 -08001173 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001174 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001175 ALOGV("getRoutedDevice: audio sink not init");
1176 return nullptr;
Wei Jia53692fa2017-12-11 10:33:46 -08001177 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001178 return mAudioOutput->getRoutedDevice();
Wei Jia53692fa2017-12-11 10:33:46 -08001179}
1180
Dichen Zhangf8726912018-10-17 13:31:26 -07001181status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
1182 Mutex::Autolock _l(mLock);
1183 if (mAudioOutput == NULL) {
1184 ALOGV("addAudioDeviceCallback: player not init");
Dichen Zhangf8726912018-10-17 13:31:26 -07001185 return NO_INIT;
1186 }
1187 return mAudioOutput->addAudioDeviceCallback(routingDelegate);
1188}
1189
1190status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
Wei Jia53692fa2017-12-11 10:33:46 -08001191 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001192 if (mAudioOutput == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001193 ALOGV("addAudioDeviceCallback: player not init");
1194 return NO_INIT;
1195 }
Dichen Zhangf8726912018-10-17 13:31:26 -07001196 return mAudioOutput->removeAudioDeviceCallback(listener);
Wei Jiaec044b02018-02-19 12:41:23 -08001197}
1198
1199status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
1200 const size_t SIZE = 256;
1201 char buffer[SIZE];
1202 String8 result;
1203 result.append(" MediaPlayer2\n");
1204 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
1205 result.append(buffer);
1206
1207 sp<MediaPlayer2Interface> player;
1208 sp<MediaPlayer2AudioOutput> audioOutput;
1209 bool locked = false;
1210 for (int i = 0; i < kDumpLockRetries; ++i) {
1211 if (mLock.tryLock() == NO_ERROR) {
1212 locked = true;
1213 break;
1214 }
1215 usleep(kDumpLockSleepUs);
1216 }
1217
1218 if (locked) {
1219 player = mPlayer;
1220 audioOutput = mAudioOutput;
1221 mLock.unlock();
1222 } else {
1223 result.append(" lock is taken, no dump from player and audio output\n");
1224 }
1225 write(fd, result.string(), result.size());
1226
1227 if (player != NULL) {
1228 player->dump(fd, args);
1229 }
1230 if (audioOutput != 0) {
1231 audioOutput->dump(fd, args);
1232 }
1233 write(fd, "\n", 1);
1234 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001235}
1236
1237} // namespace android