blob: 921a5b760dac8ab44fcc5a469079d9bd72d6a4e7 [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 Jia800fe372018-02-20 15:00:45 -0800721status_t MediaPlayer2::getDuration(int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800722 Mutex::Autolock _l(mLock);
Wei Jia53692fa2017-12-11 10:33:46 -0800723 ALOGV("getDuration_l");
724 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700725 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800726 if (mPlayer == 0 || !isValidState) {
727 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
728 mPlayer.get(), mCurrentState);
729 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800730 }
Wei Jia800fe372018-02-20 15:00:45 -0800731 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800732 status_t ret = mPlayer->getDuration(&durationMs);
733
734 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800735 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800736 } else {
737 ALOGE("getDuration returned %d", ret);
738 // Do not enter error state just because no duration was available.
739 durationMs = -1;
740 }
741
742 if (msec) {
743 *msec = durationMs;
744 }
745 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800746}
747
Wei Jia800fe372018-02-20 15:00:45 -0800748status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
749 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
750 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
751 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
752 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
753 mPlayer.get(), mCurrentState);
754 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800755 }
Wei Jia800fe372018-02-20 15:00:45 -0800756 if (msec < 0) {
757 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
758 msec = 0;
759 }
760
761 int64_t durationMs;
762 status_t err = mPlayer->getDuration(&durationMs);
763
764 if (err != OK) {
765 ALOGW("Stream has no duration and is therefore not seekable.");
766 return err;
767 }
768
769 if (msec > durationMs) {
770 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
771 (long long)msec, (long long)durationMs);
772
773 msec = durationMs;
774 }
775
776 // cache duration
777 mCurrentPosition = msec;
778 mCurrentSeekMode = mode;
779 if (mSeekPosition < 0) {
780 mSeekPosition = msec;
781 mSeekMode = mode;
782 return mPlayer->seekTo(msec, mode);
783 }
784 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
785 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800786}
787
Wei Jia800fe372018-02-20 15:00:45 -0800788status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800789 mLockThreadId = getThreadId();
790 Mutex::Autolock _l(mLock);
791 status_t result = seekTo_l(msec, mode);
792 mLockThreadId = 0;
793
794 return result;
795}
796
Wei Jiaec044b02018-02-19 12:41:23 -0800797status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800798 Mutex::Autolock _l(mLock);
799 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800800 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800801 }
Wei Jiaec044b02018-02-19 12:41:23 -0800802
803 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800804}
805
Wei Jiaec044b02018-02-19 12:41:23 -0800806status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800807 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800808 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
809 return NO_ERROR;
810 }
Wei Jia53692fa2017-12-11 10:33:46 -0800811 if (mPlayer != 0) {
812 status_t ret = mPlayer->reset();
813 if (ret != NO_ERROR) {
814 ALOGE("reset() failed with return code (%d)", ret);
815 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
816 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800817 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800818 mCurrentState = MEDIA_PLAYER2_IDLE;
819 }
820 // setDataSource has to be called again to create a
821 // new mediaplayer.
822 mPlayer = 0;
823 return ret;
824 }
825 clear_l();
826 return NO_ERROR;
827}
828
Wei Jiaec044b02018-02-19 12:41:23 -0800829status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800830 ALOGV("reset");
831 mLockThreadId = getThreadId();
832 Mutex::Autolock _l(mLock);
833 status_t result = reset_l();
834 mLockThreadId = 0;
835
836 return result;
837}
838
Wei Jiaec044b02018-02-19 12:41:23 -0800839status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800840 ALOGV("MediaPlayer2::setAudioStreamType");
841 Mutex::Autolock _l(mLock);
842 if (mStreamType == type) return NO_ERROR;
843 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
844 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
845 // Can't change the stream type after prepare
846 ALOGE("setAudioStream called in state %d", mCurrentState);
847 return INVALID_OPERATION;
848 }
849 // cache
850 mStreamType = type;
851 return OK;
852}
853
Wei Jiaec044b02018-02-19 12:41:23 -0800854status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800855 ALOGV("getAudioStreamType");
856 Mutex::Autolock _l(mLock);
857 *type = mStreamType;
858 return OK;
859}
860
Wei Jiaec044b02018-02-19 12:41:23 -0800861status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800862 ALOGV("MediaPlayer2::setLooping");
863 Mutex::Autolock _l(mLock);
864 mLoop = (loop != 0);
865 if (mPlayer != 0) {
866 return mPlayer->setLooping(loop);
867 }
868 return OK;
869}
870
871bool MediaPlayer2::isLooping() {
872 ALOGV("isLooping");
873 Mutex::Autolock _l(mLock);
874 if (mPlayer != 0) {
875 return mLoop;
876 }
877 ALOGV("isLooping: no active player");
878 return false;
879}
880
Dichen Zhang7398ca02018-10-15 10:25:12 -0700881status_t MediaPlayer2::setVolume(float volume) {
882 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800883 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700884 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800885 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700886 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800887 }
888 return OK;
889}
890
Dichen Zhang23658642018-11-15 10:26:16 -0800891status_t MediaPlayer2::setAudioSessionId(int32_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800892 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
893 Mutex::Autolock _l(mLock);
894 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
895 ALOGE("setAudioSessionId called in state %d", mCurrentState);
896 return INVALID_OPERATION;
897 }
898 if (sessionId < 0) {
899 return BAD_VALUE;
900 }
Dichen Zhang23658642018-11-15 10:26:16 -0800901 if (mAudioOutput != NULL && sessionId != mAudioOutput->getSessionId()) {
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000902 mAudioOutput->setSessionId(sessionId);
903 }
Wei Jia53692fa2017-12-11 10:33:46 -0800904 return NO_ERROR;
905}
906
Dichen Zhang23658642018-11-15 10:26:16 -0800907int32_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800908 Mutex::Autolock _l(mLock);
Dichen Zhang23658642018-11-15 10:26:16 -0800909 if (mAudioOutput != NULL) {
910 return mAudioOutput->getSessionId();
911 }
912 return 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800913}
914
Wei Jiaec044b02018-02-19 12:41:23 -0800915status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800916 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
917 Mutex::Autolock _l(mLock);
918 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800919 if (mAudioOutput != 0) {
920 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -0800921 }
922 return OK;
923}
924
Wei Jiaec044b02018-02-19 12:41:23 -0800925status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800926 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
927 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800928 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -0800929 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
930 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
931 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
932 return INVALID_OPERATION;
933 }
934
Wei Jiaec044b02018-02-19 12:41:23 -0800935 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -0800936}
937
938// always call with lock held
Dichen Zhangc2465c52018-11-12 11:56:05 -0800939status_t MediaPlayer2::checkState_l() {
940 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
941 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
942 // Can't change the audio attributes after prepare
943 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
944 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800945 }
946 return OK;
947}
948
Dichen Zhangc2465c52018-11-12 11:56:05 -0800949status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
950 ALOGV("MediaPlayer2::setAudioAttributes");
Wei Jia53692fa2017-12-11 10:33:46 -0800951 status_t status = INVALID_OPERATION;
952 Mutex::Autolock _l(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800953 if (checkState_l() != OK) {
Wei Jia53692fa2017-12-11 10:33:46 -0800954 return status;
955 }
Dichen Zhangc2465c52018-11-12 11:56:05 -0800956 mAudioAttributes = new JObjectHolder(attributes);
957 status = setAudioAttributes_l(attributes);
Wei Jia53692fa2017-12-11 10:33:46 -0800958 return status;
959}
960
Dichen Zhangc2465c52018-11-12 11:56:05 -0800961jobject MediaPlayer2::getAudioAttributes() {
962 ALOGV("MediaPlayer2::getAudioAttributes)");
963 Mutex::Autolock _l(mLock);
964 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
965}
966
Wei Jiaec044b02018-02-19 12:41:23 -0800967status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800968 ALOGV("MediaPlayer2::getParameter(%d)", key);
969 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800970 if (mPlayer == NULL) {
971 ALOGV("getParameter: no active player");
972 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800973 }
Wei Jiaec044b02018-02-19 12:41:23 -0800974
975 status_t status = mPlayer->getParameter(key, reply);
976 if (status != OK) {
977 ALOGD("getParameter returns %d", status);
978 }
979 return status;
Wei Jia53692fa2017-12-11 10:33:46 -0800980}
981
Dongwon Kang41929fb2018-09-09 08:29:56 -0700982void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800983 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
984 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -0800985
Wei Jia53692fa2017-12-11 10:33:46 -0800986 bool send = true;
987 bool locked = false;
988
989 // TODO: In the future, we might be on the same thread if the app is
990 // running in the same process as the media server. In that case,
991 // this will deadlock.
992 //
993 // The threadId hack below works around this for the care of prepare,
994 // seekTo, start, and reset within the same process.
995 // FIXME: Remember, this is a hack, it's not even a hack that is applied
996 // consistently for all use-cases, this needs to be revisited.
997 if (mLockThreadId != getThreadId()) {
998 mLock.lock();
999 locked = true;
1000 }
1001
1002 // Allows calls from JNI in idle state to notify errors
1003 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001004 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1005 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001006 if (locked) mLock.unlock(); // release the lock when done.
1007 return;
1008 }
1009
1010 switch (msg) {
1011 case MEDIA2_NOP: // interface test message
1012 break;
1013 case MEDIA2_PREPARED:
1014 ALOGV("MediaPlayer2::notify() prepared");
1015 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001016 break;
1017 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001018 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1019 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001020 break;
1021 case MEDIA2_PLAYBACK_COMPLETE:
1022 ALOGV("playback complete");
1023 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1024 ALOGE("playback complete in idle state");
1025 }
1026 if (!mLoop) {
1027 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1028 }
1029 break;
1030 case MEDIA2_ERROR:
1031 // Always log errors.
1032 // ext1: Media framework error code.
1033 // ext2: Implementation dependant error code.
1034 ALOGE("error (%d, %d)", ext1, ext2);
1035 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001036 break;
1037 case MEDIA2_INFO:
1038 // ext1: Media framework error code.
1039 // ext2: Implementation dependant error code.
1040 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1041 ALOGW("info/warning (%d, %d)", ext1, ext2);
1042 }
1043 break;
1044 case MEDIA2_SEEK_COMPLETE:
1045 ALOGV("Received seek complete");
1046 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001047 ALOGV("Executing queued seekTo(%lld, %d)",
1048 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001049 mSeekPosition = -1;
1050 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1051 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1052 }
1053 else {
1054 ALOGV("All seeks complete - return to regularly scheduled program");
1055 mCurrentPosition = mSeekPosition = -1;
1056 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1057 }
1058 break;
1059 case MEDIA2_BUFFERING_UPDATE:
1060 ALOGV("buffering %d", ext1);
1061 break;
1062 case MEDIA2_SET_VIDEO_SIZE:
1063 ALOGV("New video size %d x %d", ext1, ext2);
1064 mVideoWidth = ext1;
1065 mVideoHeight = ext2;
1066 break;
1067 case MEDIA2_NOTIFY_TIME:
1068 ALOGV("Received notify time message");
1069 break;
1070 case MEDIA2_TIMED_TEXT:
1071 ALOGV("Received timed text message");
1072 break;
1073 case MEDIA2_SUBTITLE_DATA:
1074 ALOGV("Received subtitle data message");
1075 break;
1076 case MEDIA2_META_DATA:
1077 ALOGV("Received timed metadata message");
1078 break;
1079 default:
1080 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1081 break;
1082 }
1083
1084 sp<MediaPlayer2Listener> listener = mListener;
1085 if (locked) mLock.unlock();
1086
1087 // this prevents re-entrant calls into client code
1088 if ((listener != 0) && send) {
1089 Mutex::Autolock _l(mNotifyLock);
1090 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001091 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001092 ALOGV("back from callback");
1093 }
1094}
1095
Wei Jia53692fa2017-12-11 10:33:46 -08001096// Modular DRM
Wei Jiaec044b02018-02-19 12:41:23 -08001097status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001098 // TODO change to ALOGV
1099 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1100 drmSessionId.array(), drmSessionId.size());
1101 Mutex::Autolock _l(mLock);
1102 if (mPlayer == NULL) {
1103 return NO_INIT;
1104 }
1105
1106 // Only allowed it in player's preparing/prepared state.
1107 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1108 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1109 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1110 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
1111 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
1112 return INVALID_OPERATION;
1113 }
1114
1115 if (drmSessionId.isEmpty()) {
1116 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1117 return INVALID_OPERATION;
1118 }
1119
1120 // Passing down to mediaserver mainly for creating the crypto
1121 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1122 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1123
1124 // TODO change to ALOGV
1125 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1126
1127 return status;
1128}
1129
Wei Jiaec044b02018-02-19 12:41:23 -08001130status_t MediaPlayer2::releaseDrm() {
Wei Jia53692fa2017-12-11 10:33:46 -08001131 Mutex::Autolock _l(mLock);
1132 if (mPlayer == NULL) {
1133 return NO_INIT;
1134 }
1135
1136 // Not allowing releaseDrm in an active/resumable state
1137 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
1138 MEDIA_PLAYER2_PAUSED |
1139 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
1140 MEDIA_PLAYER2_STATE_ERROR)) {
1141 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
1142 return INVALID_OPERATION;
1143 }
1144
1145 status_t status = mPlayer->releaseDrm();
1146 // TODO change to ALOGV
1147 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1148 if (status != OK) {
1149 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1150 // Overriding to OK so the client proceed with its own cleanup
1151 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1152 status = OK;
1153 }
1154
1155 return status;
1156}
1157
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001158status_t MediaPlayer2::setPreferredDevice(jobject device) {
Wei Jia53692fa2017-12-11 10:33:46 -08001159 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001160 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001161 ALOGV("setPreferredDevice: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001162 return NO_INIT;
1163 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001164 return mAudioOutput->setPreferredDevice(device);
Wei Jia53692fa2017-12-11 10:33:46 -08001165}
1166
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001167jobject MediaPlayer2::getRoutedDevice() {
Wei Jia53692fa2017-12-11 10:33:46 -08001168 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001169 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001170 ALOGV("getRoutedDevice: audio sink not init");
1171 return nullptr;
Wei Jia53692fa2017-12-11 10:33:46 -08001172 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001173 return mAudioOutput->getRoutedDevice();
Wei Jia53692fa2017-12-11 10:33:46 -08001174}
1175
Dichen Zhangf8726912018-10-17 13:31:26 -07001176status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
1177 Mutex::Autolock _l(mLock);
1178 if (mAudioOutput == NULL) {
1179 ALOGV("addAudioDeviceCallback: player not init");
Dichen Zhangf8726912018-10-17 13:31:26 -07001180 return NO_INIT;
1181 }
1182 return mAudioOutput->addAudioDeviceCallback(routingDelegate);
1183}
1184
1185status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
Wei Jia53692fa2017-12-11 10:33:46 -08001186 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001187 if (mAudioOutput == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001188 ALOGV("addAudioDeviceCallback: player not init");
1189 return NO_INIT;
1190 }
Dichen Zhangf8726912018-10-17 13:31:26 -07001191 return mAudioOutput->removeAudioDeviceCallback(listener);
Wei Jiaec044b02018-02-19 12:41:23 -08001192}
1193
1194status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
1195 const size_t SIZE = 256;
1196 char buffer[SIZE];
1197 String8 result;
1198 result.append(" MediaPlayer2\n");
1199 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
1200 result.append(buffer);
1201
1202 sp<MediaPlayer2Interface> player;
1203 sp<MediaPlayer2AudioOutput> audioOutput;
1204 bool locked = false;
1205 for (int i = 0; i < kDumpLockRetries; ++i) {
1206 if (mLock.tryLock() == NO_ERROR) {
1207 locked = true;
1208 break;
1209 }
1210 usleep(kDumpLockSleepUs);
1211 }
1212
1213 if (locked) {
1214 player = mPlayer;
1215 audioOutput = mAudioOutput;
1216 mLock.unlock();
1217 } else {
1218 result.append(" lock is taken, no dump from player and audio output\n");
1219 }
1220 write(fd, result.string(), result.size());
1221
1222 if (player != NULL) {
1223 player->dump(fd, args);
1224 }
1225 if (audioOutput != 0) {
1226 audioOutput->dump(fd, args);
1227 }
1228 write(fd, "\n", 1);
1229 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001230}
1231
1232} // namespace android