blob: 07442a1fdadf93385bcaac54f2462a477c3d3c81 [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();
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 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
266 disconnect();
Wei Jiaec044b02018-02-19 12:41:23 -0800267 removePlayer(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800268}
269
Wei Jiaec044b02018-02-19 12:41:23 -0800270bool MediaPlayer2::init() {
271 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
272 // looper for notification.
273 return true;
274}
275
276void MediaPlayer2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800277 ALOGV("disconnect");
Wei Jiaec044b02018-02-19 12:41:23 -0800278 sp<MediaPlayer2Interface> p;
Wei Jia53692fa2017-12-11 10:33:46 -0800279 {
280 Mutex::Autolock _l(mLock);
281 p = mPlayer;
282 mPlayer.clear();
283 }
284
285 if (p != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800286 p->setListener(NULL);
287 p->reset();
288 }
289
290 {
291 Mutex::Autolock _l(mLock);
292 disconnectNativeWindow_l();
Wei Jia53692fa2017-12-11 10:33:46 -0800293 }
294}
295
Wei Jiaec044b02018-02-19 12:41:23 -0800296void MediaPlayer2::clear_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800297 mCurrentPosition = -1;
298 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
299 mSeekPosition = -1;
300 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
301 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800302}
303
Wei Jiaec044b02018-02-19 12:41:23 -0800304status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
Wei Jia53692fa2017-12-11 10:33:46 -0800305 ALOGV("setListener");
306 Mutex::Autolock _l(mLock);
307 mListener = listener;
308 return NO_ERROR;
309}
310
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800311status_t MediaPlayer2::getSrcId(int64_t *srcId) {
312 if (srcId == NULL) {
313 return BAD_VALUE;
314 }
Wei Jia53692fa2017-12-11 10:33:46 -0800315
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800316 Mutex::Autolock _l(mLock);
317 *srcId = mSrcId;
318 return OK;
319}
320
Wei Jiaec044b02018-02-19 12:41:23 -0800321status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jiac2636032018-02-01 09:15:25 -0800322 if (dsd == NULL) {
323 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800324 }
Wei Jiaf01e3122018-10-18 11:49:44 -0700325 // Microsecond is used in NuPlayer2.
Wei Jiae31ac8a2018-10-25 11:06:21 -0700326 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
327 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700328 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
329 }
Wei Jiae31ac8a2018-10-25 11:06:21 -0700330 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
331 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700332 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
333 }
Wei Jiaec044b02018-02-19 12:41:23 -0800334 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
335
336 sp<MediaPlayer2Interface> oldPlayer;
337
338 Mutex::Autolock _l(mLock);
339 {
340 if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
341 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
342 ALOGE("setDataSource called in wrong state %d", mCurrentState);
343 return INVALID_OPERATION;
344 }
345
346 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
347 status_t err = player->initCheck();
348 if (err != NO_ERROR) {
349 ALOGE("Failed to create player object, initCheck failed(%d)", err);
350 return err;
351 }
352
353 clear_l();
354
Dichen Zhangf8726912018-10-17 13:31:26 -0700355 if (mAudioOutput != NULL) {
356 mAudioOutput->copyAudioDeviceCallback(mRoutingDelegates);
357 }
358
Wei Jiaec044b02018-02-19 12:41:23 -0800359 player->setListener(new proxyListener(this));
360 mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800361 mPid, mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL,
362 mRoutingDelegates);
Wei Jiaec044b02018-02-19 12:41:23 -0800363 player->setAudioSink(mAudioOutput);
364
365 err = player->setDataSource(dsd);
366 if (err != OK) {
367 ALOGE("setDataSource error: %d", err);
368 return err;
369 }
370
371 sp<MediaPlayer2Interface> oldPlayer = mPlayer;
372 mPlayer = player;
373 mSrcId = dsd->mId;
374 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
Wei Jia53692fa2017-12-11 10:33:46 -0800375 }
Wei Jiaec044b02018-02-19 12:41:23 -0800376
377 if (oldPlayer != NULL) {
378 oldPlayer->setListener(NULL);
379 oldPlayer->reset();
380 }
381
382 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800383}
384
Wei Jia57aeffd2018-02-15 16:01:14 -0800385status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
386 if (dsd == NULL) {
387 return BAD_VALUE;
388 }
389 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
390
391 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800392 if (mPlayer == NULL) {
393 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
394 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800395 }
Wei Jiaec044b02018-02-19 12:41:23 -0800396 return mPlayer->prepareNextDataSource(dsd);
Wei Jia57aeffd2018-02-15 16:01:14 -0800397}
398
399status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
400 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
401
402 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800403 if (mPlayer == NULL) {
404 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
405 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800406 }
Wei Jiaec044b02018-02-19 12:41:23 -0800407 mSrcId = srcId;
408 return mPlayer->playNextDataSource(srcId);
Wei Jia57aeffd2018-02-15 16:01:14 -0800409}
410
Dongwon Kang9f631982018-07-10 12:34:41 -0700411status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800412 Mutex::Autolock _l(mLock);
413 const bool hasBeenInitialized =
414 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
415 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
Wei Jiaec044b02018-02-19 12:41:23 -0800416 if ((mPlayer == NULL) || !hasBeenInitialized) {
Dongwon Kang9f631982018-07-10 12:34:41 -0700417 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Wei Jiaec044b02018-02-19 12:41:23 -0800418 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800419 }
Wei Jiaec044b02018-02-19 12:41:23 -0800420 return mPlayer->invoke(request, reply);
Wei Jia53692fa2017-12-11 10:33:46 -0800421}
422
Wei Jiaec044b02018-02-19 12:41:23 -0800423void MediaPlayer2::disconnectNativeWindow_l() {
424 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
425 status_t err = native_window_api_disconnect(
426 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
427
428 if (err != OK) {
429 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
430 strerror(-err), err);
431 }
432 }
433 mConnectedWindow.clear();
434}
435
436status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
437 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
438 ALOGV("setVideoSurfaceTexture(%p)", anw);
439 Mutex::Autolock _l(mLock);
440 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800441 return NO_INIT;
442 }
Wei Jiaec044b02018-02-19 12:41:23 -0800443
444 if (anw != NULL) {
445 if (mConnectedWindow != NULL
446 && mConnectedWindow->getANativeWindow() == anw) {
447 return OK;
448 }
449 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
450
451 if (err != OK) {
452 ALOGE("setVideoSurfaceTexture failed: %d", err);
453 // Note that we must do the reset before disconnecting from the ANW.
454 // Otherwise queue/dequeue calls could be made on the disconnected
455 // ANW, which may result in errors.
456 mPlayer->reset();
457 disconnectNativeWindow_l();
458 return err;
459 }
460 }
461
462 // Note that we must set the player's new GraphicBufferProducer before
463 // disconnecting the old one. Otherwise queue/dequeue calls could be made
464 // on the disconnected ANW, which may result in errors.
465 status_t err = mPlayer->setVideoSurfaceTexture(nww);
466
467 disconnectNativeWindow_l();
468
469 if (err == OK) {
470 mConnectedWindow = nww;
471 mLock.unlock();
472 } else if (anw != NULL) {
473 mLock.unlock();
474 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
475
476 if (err != OK) {
477 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
478 strerror(-err), err);
479 }
480 }
481
482 return err;
Wei Jia53692fa2017-12-11 10:33:46 -0800483}
484
Wei Jiaec044b02018-02-19 12:41:23 -0800485status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800486 ALOGV("getBufferingSettings");
487
488 Mutex::Autolock _l(mLock);
489 if (mPlayer == 0) {
490 return NO_INIT;
491 }
Wei Jiaec044b02018-02-19 12:41:23 -0800492
493 status_t ret = mPlayer->getBufferingSettings(buffering);
494 if (ret == NO_ERROR) {
495 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
496 } else {
497 ALOGE("getBufferingSettings returned %d", ret);
498 }
499 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800500}
501
Wei Jiaec044b02018-02-19 12:41:23 -0800502status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
503 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Wei Jia53692fa2017-12-11 10:33:46 -0800504
505 Mutex::Autolock _l(mLock);
506 if (mPlayer == 0) {
507 return NO_INIT;
508 }
509 return mPlayer->setBufferingSettings(buffering);
510}
511
Dichen Zhangc2465c52018-11-12 11:56:05 -0800512status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
513 if (mAudioOutput != NULL) {
514 mAudioOutput->setAudioAttributes(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800515 }
516 return NO_ERROR;
517}
518
519status_t MediaPlayer2::prepareAsync() {
520 ALOGV("prepareAsync");
521 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700522 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
Dichen Zhangc2465c52018-11-12 11:56:05 -0800523 if (mAudioAttributes != NULL) {
524 status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
Wei Jiaec044b02018-02-19 12:41:23 -0800525 if (err != OK) {
526 return err;
527 }
Wei Jia53692fa2017-12-11 10:33:46 -0800528 }
529 mCurrentState = MEDIA_PLAYER2_PREPARING;
530 return mPlayer->prepareAsync();
531 }
532 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
533 return INVALID_OPERATION;
534}
535
Wei Jiaec044b02018-02-19 12:41:23 -0800536status_t MediaPlayer2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800537 ALOGV("start");
538
539 status_t ret = NO_ERROR;
540 Mutex::Autolock _l(mLock);
541
542 mLockThreadId = getThreadId();
543
544 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
545 ret = NO_ERROR;
546 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
547 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
548 mPlayer->setLooping(mLoop);
Wei Jiaec044b02018-02-19 12:41:23 -0800549
550 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700551 mAudioOutput->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800552 }
553
554 if (mAudioOutput != 0) {
555 mAudioOutput->setAuxEffectSendLevel(mSendLevel);
556 }
Wei Jia53692fa2017-12-11 10:33:46 -0800557 mCurrentState = MEDIA_PLAYER2_STARTED;
558 ret = mPlayer->start();
559 if (ret != NO_ERROR) {
560 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
561 } else {
562 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
563 ALOGV("playback completed immediately following start()");
564 }
565 }
566 } else {
567 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
568 ret = INVALID_OPERATION;
569 }
570
571 mLockThreadId = 0;
572
573 return ret;
574}
575
Wei Jiaec044b02018-02-19 12:41:23 -0800576status_t MediaPlayer2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800577 ALOGV("pause");
578 Mutex::Autolock _l(mLock);
579 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
580 return NO_ERROR;
Wei Jia6376cd52018-09-26 11:42:55 -0700581 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
Wei Jia53692fa2017-12-11 10:33:46 -0800582 status_t ret = mPlayer->pause();
583 if (ret != NO_ERROR) {
584 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
585 } else {
586 mCurrentState = MEDIA_PLAYER2_PAUSED;
587 }
588 return ret;
589 }
590 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
591 return INVALID_OPERATION;
592}
593
Wei Jiaec044b02018-02-19 12:41:23 -0800594bool MediaPlayer2::isPlaying() {
Wei Jia53692fa2017-12-11 10:33:46 -0800595 Mutex::Autolock _l(mLock);
596 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800597 bool temp = mPlayer->isPlaying();
Wei Jia53692fa2017-12-11 10:33:46 -0800598 ALOGV("isPlaying: %d", temp);
599 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
600 ALOGE("internal/external state mismatch corrected");
601 mCurrentState = MEDIA_PLAYER2_PAUSED;
602 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
603 ALOGE("internal/external state mismatch corrected");
604 mCurrentState = MEDIA_PLAYER2_STARTED;
605 }
606 return temp;
607 }
608 ALOGV("isPlaying: no active player");
609 return false;
610}
611
Wei Jia1f043e42018-06-20 16:52:50 -0700612mediaplayer2_states MediaPlayer2::getState() {
Wei Jia98787a72018-03-02 14:33:06 -0800613 Mutex::Autolock _l(mLock);
614 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
615 return MEDIAPLAYER2_STATE_ERROR;
616 }
617 if (mPlayer == 0
618 || (mCurrentState &
619 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
620 return MEDIAPLAYER2_STATE_IDLE;
621 }
622 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
623 return MEDIAPLAYER2_STATE_PLAYING;
624 }
Wei Jia0151ef42018-08-24 16:40:21 -0700625 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
Wei Jia98787a72018-03-02 14:33:06 -0800626 return MEDIAPLAYER2_STATE_PAUSED;
627 }
628 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
629 return MEDIAPLAYER2_STATE_PREPARED;
630}
631
Wei Jiaec044b02018-02-19 12:41:23 -0800632status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
Wei Jia53692fa2017-12-11 10:33:46 -0800633 ALOGV("setPlaybackSettings: %f %f %d %d",
634 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
635 // Negative speed and pitch does not make sense. Further validation will
636 // be done by the respective mediaplayers.
Wei Jiaec044b02018-02-19 12:41:23 -0800637 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
Wei Jia53692fa2017-12-11 10:33:46 -0800638 return BAD_VALUE;
639 }
640 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700641 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800642 return INVALID_OPERATION;
643 }
644
Wei Jia53692fa2017-12-11 10:33:46 -0800645 status_t err = mPlayer->setPlaybackSettings(rate);
Wei Jia53692fa2017-12-11 10:33:46 -0800646 return err;
647}
648
Wei Jiaec044b02018-02-19 12:41:23 -0800649status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800650 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800651 if (mPlayer == 0) {
652 return INVALID_OPERATION;
653 }
Wei Jiaec044b02018-02-19 12:41:23 -0800654 status_t ret = mPlayer->getPlaybackSettings(rate);
655 if (ret == NO_ERROR) {
656 ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
657 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
658 } else {
659 ALOGV("getPlaybackSettings returned %d", ret);
660 }
661 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800662}
663
Wei Jiaec044b02018-02-19 12:41:23 -0800664status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
Wei Jia53692fa2017-12-11 10:33:46 -0800665 ALOGV("setSyncSettings: %u %u %f %f",
666 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
667 Mutex::Autolock _l(mLock);
668 if (mPlayer == 0) return INVALID_OPERATION;
669 return mPlayer->setSyncSettings(sync, videoFpsHint);
670}
671
672status_t MediaPlayer2::getSyncSettings(
Wei Jiaec044b02018-02-19 12:41:23 -0800673 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800674 Mutex::Autolock _l(mLock);
Wei Jia334adf02018-03-23 14:08:23 -0700675 if (mPlayer == 0) {
676 return INVALID_OPERATION;
677 }
Wei Jiaec044b02018-02-19 12:41:23 -0800678 status_t ret = mPlayer->getSyncSettings(sync, videoFps);
679 if (ret == NO_ERROR) {
680 ALOGV("getSyncSettings(%u, %u, %f, %f)",
681 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
682 } else {
683 ALOGV("getSyncSettings returned %d", ret);
684 }
685 return ret;
686
Wei Jia53692fa2017-12-11 10:33:46 -0800687}
688
Wei Jiaec044b02018-02-19 12:41:23 -0800689status_t MediaPlayer2::getVideoWidth(int *w) {
Wei Jia53692fa2017-12-11 10:33:46 -0800690 ALOGV("getVideoWidth");
691 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800692 if (mPlayer == 0) {
693 return INVALID_OPERATION;
694 }
Wei Jia53692fa2017-12-11 10:33:46 -0800695 *w = mVideoWidth;
696 return NO_ERROR;
697}
698
Wei Jiaec044b02018-02-19 12:41:23 -0800699status_t MediaPlayer2::getVideoHeight(int *h) {
Wei Jia53692fa2017-12-11 10:33:46 -0800700 ALOGV("getVideoHeight");
701 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800702 if (mPlayer == 0) {
703 return INVALID_OPERATION;
704 }
Wei Jia53692fa2017-12-11 10:33:46 -0800705 *h = mVideoHeight;
706 return NO_ERROR;
707}
708
Wei Jia800fe372018-02-20 15:00:45 -0800709status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800710 ALOGV("getCurrentPosition");
711 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800712 if (mPlayer == 0) {
713 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800714 }
Wei Jiaec044b02018-02-19 12:41:23 -0800715 if (mCurrentPosition >= 0) {
Wei Jia800fe372018-02-20 15:00:45 -0800716 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
Wei Jiaec044b02018-02-19 12:41:23 -0800717 *msec = mCurrentPosition;
718 return NO_ERROR;
719 }
720 status_t ret = mPlayer->getCurrentPosition(msec);
721 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800722 ALOGV("getCurrentPosition = %lld", (long long)*msec);
Wei Jiaec044b02018-02-19 12:41:23 -0800723 } else {
724 ALOGE("getCurrentPosition returned %d", ret);
725 }
726 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800727}
728
Wei Jia800fe372018-02-20 15:00:45 -0800729status_t MediaPlayer2::getDuration(int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800730 Mutex::Autolock _l(mLock);
Wei Jia53692fa2017-12-11 10:33:46 -0800731 ALOGV("getDuration_l");
732 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700733 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800734 if (mPlayer == 0 || !isValidState) {
735 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
736 mPlayer.get(), mCurrentState);
737 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800738 }
Wei Jia800fe372018-02-20 15:00:45 -0800739 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800740 status_t ret = mPlayer->getDuration(&durationMs);
741
742 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800743 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800744 } else {
745 ALOGE("getDuration returned %d", ret);
746 // Do not enter error state just because no duration was available.
747 durationMs = -1;
748 }
749
750 if (msec) {
751 *msec = durationMs;
752 }
753 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800754}
755
Wei Jia800fe372018-02-20 15:00:45 -0800756status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
757 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
758 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
759 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
760 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
761 mPlayer.get(), mCurrentState);
762 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800763 }
Wei Jia800fe372018-02-20 15:00:45 -0800764 if (msec < 0) {
765 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
766 msec = 0;
767 }
768
769 int64_t durationMs;
770 status_t err = mPlayer->getDuration(&durationMs);
771
772 if (err != OK) {
773 ALOGW("Stream has no duration and is therefore not seekable.");
774 return err;
775 }
776
777 if (msec > durationMs) {
778 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
779 (long long)msec, (long long)durationMs);
780
781 msec = durationMs;
782 }
783
784 // cache duration
785 mCurrentPosition = msec;
786 mCurrentSeekMode = mode;
787 if (mSeekPosition < 0) {
788 mSeekPosition = msec;
789 mSeekMode = mode;
790 return mPlayer->seekTo(msec, mode);
791 }
792 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
793 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800794}
795
Wei Jia800fe372018-02-20 15:00:45 -0800796status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800797 mLockThreadId = getThreadId();
798 Mutex::Autolock _l(mLock);
799 status_t result = seekTo_l(msec, mode);
800 mLockThreadId = 0;
801
802 return result;
803}
804
Wei Jiaec044b02018-02-19 12:41:23 -0800805status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800806 Mutex::Autolock _l(mLock);
807 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800808 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800809 }
Wei Jiaec044b02018-02-19 12:41:23 -0800810
811 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800812}
813
Wei Jiaec044b02018-02-19 12:41:23 -0800814status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800815 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800816 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
817 return NO_ERROR;
818 }
Wei Jia53692fa2017-12-11 10:33:46 -0800819 if (mPlayer != 0) {
820 status_t ret = mPlayer->reset();
821 if (ret != NO_ERROR) {
822 ALOGE("reset() failed with return code (%d)", ret);
823 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
824 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800825 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800826 mCurrentState = MEDIA_PLAYER2_IDLE;
827 }
828 // setDataSource has to be called again to create a
829 // new mediaplayer.
830 mPlayer = 0;
831 return ret;
832 }
833 clear_l();
834 return NO_ERROR;
835}
836
Wei Jiaec044b02018-02-19 12:41:23 -0800837status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800838 ALOGV("reset");
839 mLockThreadId = getThreadId();
840 Mutex::Autolock _l(mLock);
841 status_t result = reset_l();
842 mLockThreadId = 0;
843
844 return result;
845}
846
Wei Jiaec044b02018-02-19 12:41:23 -0800847status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800848 ALOGV("MediaPlayer2::setAudioStreamType");
849 Mutex::Autolock _l(mLock);
850 if (mStreamType == type) return NO_ERROR;
851 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
852 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
853 // Can't change the stream type after prepare
854 ALOGE("setAudioStream called in state %d", mCurrentState);
855 return INVALID_OPERATION;
856 }
857 // cache
858 mStreamType = type;
859 return OK;
860}
861
Wei Jiaec044b02018-02-19 12:41:23 -0800862status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800863 ALOGV("getAudioStreamType");
864 Mutex::Autolock _l(mLock);
865 *type = mStreamType;
866 return OK;
867}
868
Wei Jiaec044b02018-02-19 12:41:23 -0800869status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800870 ALOGV("MediaPlayer2::setLooping");
871 Mutex::Autolock _l(mLock);
872 mLoop = (loop != 0);
873 if (mPlayer != 0) {
874 return mPlayer->setLooping(loop);
875 }
876 return OK;
877}
878
879bool MediaPlayer2::isLooping() {
880 ALOGV("isLooping");
881 Mutex::Autolock _l(mLock);
882 if (mPlayer != 0) {
883 return mLoop;
884 }
885 ALOGV("isLooping: no active player");
886 return false;
887}
888
Dichen Zhang7398ca02018-10-15 10:25:12 -0700889status_t MediaPlayer2::setVolume(float volume) {
890 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800891 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700892 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800893 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700894 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800895 }
896 return OK;
897}
898
Wei Jiaec044b02018-02-19 12:41:23 -0800899status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800900 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
901 Mutex::Autolock _l(mLock);
902 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
903 ALOGE("setAudioSessionId called in state %d", mCurrentState);
904 return INVALID_OPERATION;
905 }
906 if (sessionId < 0) {
907 return BAD_VALUE;
908 }
909 if (sessionId != mAudioSessionId) {
910 AudioSystem::acquireAudioSessionId(sessionId, -1);
911 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
912 mAudioSessionId = sessionId;
913 }
914 return NO_ERROR;
915}
916
Wei Jiaec044b02018-02-19 12:41:23 -0800917audio_session_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800918 Mutex::Autolock _l(mLock);
919 return mAudioSessionId;
920}
921
Wei Jiaec044b02018-02-19 12:41:23 -0800922status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800923 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
924 Mutex::Autolock _l(mLock);
925 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800926 if (mAudioOutput != 0) {
927 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -0800928 }
929 return OK;
930}
931
Wei Jiaec044b02018-02-19 12:41:23 -0800932status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800933 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
934 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800935 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -0800936 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
937 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
938 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
939 return INVALID_OPERATION;
940 }
941
Wei Jiaec044b02018-02-19 12:41:23 -0800942 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -0800943}
944
945// always call with lock held
Dichen Zhangc2465c52018-11-12 11:56:05 -0800946status_t MediaPlayer2::checkState_l() {
947 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
948 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
949 // Can't change the audio attributes after prepare
950 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
951 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800952 }
953 return OK;
954}
955
Dichen Zhangc2465c52018-11-12 11:56:05 -0800956status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
957 ALOGV("MediaPlayer2::setAudioAttributes");
Wei Jia53692fa2017-12-11 10:33:46 -0800958 status_t status = INVALID_OPERATION;
959 Mutex::Autolock _l(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800960 if (checkState_l() != OK) {
Wei Jia53692fa2017-12-11 10:33:46 -0800961 return status;
962 }
Dichen Zhangc2465c52018-11-12 11:56:05 -0800963 mAudioAttributes = new JObjectHolder(attributes);
964 status = setAudioAttributes_l(attributes);
Wei Jia53692fa2017-12-11 10:33:46 -0800965 return status;
966}
967
Dichen Zhangc2465c52018-11-12 11:56:05 -0800968jobject MediaPlayer2::getAudioAttributes() {
969 ALOGV("MediaPlayer2::getAudioAttributes)");
970 Mutex::Autolock _l(mLock);
971 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
972}
973
Wei Jiaec044b02018-02-19 12:41:23 -0800974status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800975 ALOGV("MediaPlayer2::getParameter(%d)", key);
976 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800977 if (mPlayer == NULL) {
978 ALOGV("getParameter: no active player");
979 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800980 }
Wei Jiaec044b02018-02-19 12:41:23 -0800981
982 status_t status = mPlayer->getParameter(key, reply);
983 if (status != OK) {
984 ALOGD("getParameter returns %d", status);
985 }
986 return status;
Wei Jia53692fa2017-12-11 10:33:46 -0800987}
988
Dongwon Kang41929fb2018-09-09 08:29:56 -0700989void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800990 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
991 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -0800992
Wei Jia53692fa2017-12-11 10:33:46 -0800993 bool send = true;
994 bool locked = false;
995
996 // TODO: In the future, we might be on the same thread if the app is
997 // running in the same process as the media server. In that case,
998 // this will deadlock.
999 //
1000 // The threadId hack below works around this for the care of prepare,
1001 // seekTo, start, and reset within the same process.
1002 // FIXME: Remember, this is a hack, it's not even a hack that is applied
1003 // consistently for all use-cases, this needs to be revisited.
1004 if (mLockThreadId != getThreadId()) {
1005 mLock.lock();
1006 locked = true;
1007 }
1008
1009 // Allows calls from JNI in idle state to notify errors
1010 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001011 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1012 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001013 if (locked) mLock.unlock(); // release the lock when done.
1014 return;
1015 }
1016
1017 switch (msg) {
1018 case MEDIA2_NOP: // interface test message
1019 break;
1020 case MEDIA2_PREPARED:
1021 ALOGV("MediaPlayer2::notify() prepared");
1022 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001023 break;
1024 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001025 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1026 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001027 break;
1028 case MEDIA2_PLAYBACK_COMPLETE:
1029 ALOGV("playback complete");
1030 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1031 ALOGE("playback complete in idle state");
1032 }
1033 if (!mLoop) {
1034 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1035 }
1036 break;
1037 case MEDIA2_ERROR:
1038 // Always log errors.
1039 // ext1: Media framework error code.
1040 // ext2: Implementation dependant error code.
1041 ALOGE("error (%d, %d)", ext1, ext2);
1042 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001043 break;
1044 case MEDIA2_INFO:
1045 // ext1: Media framework error code.
1046 // ext2: Implementation dependant error code.
1047 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1048 ALOGW("info/warning (%d, %d)", ext1, ext2);
1049 }
1050 break;
1051 case MEDIA2_SEEK_COMPLETE:
1052 ALOGV("Received seek complete");
1053 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001054 ALOGV("Executing queued seekTo(%lld, %d)",
1055 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001056 mSeekPosition = -1;
1057 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1058 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1059 }
1060 else {
1061 ALOGV("All seeks complete - return to regularly scheduled program");
1062 mCurrentPosition = mSeekPosition = -1;
1063 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1064 }
1065 break;
1066 case MEDIA2_BUFFERING_UPDATE:
1067 ALOGV("buffering %d", ext1);
1068 break;
1069 case MEDIA2_SET_VIDEO_SIZE:
1070 ALOGV("New video size %d x %d", ext1, ext2);
1071 mVideoWidth = ext1;
1072 mVideoHeight = ext2;
1073 break;
1074 case MEDIA2_NOTIFY_TIME:
1075 ALOGV("Received notify time message");
1076 break;
1077 case MEDIA2_TIMED_TEXT:
1078 ALOGV("Received timed text message");
1079 break;
1080 case MEDIA2_SUBTITLE_DATA:
1081 ALOGV("Received subtitle data message");
1082 break;
1083 case MEDIA2_META_DATA:
1084 ALOGV("Received timed metadata message");
1085 break;
1086 default:
1087 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1088 break;
1089 }
1090
1091 sp<MediaPlayer2Listener> listener = mListener;
1092 if (locked) mLock.unlock();
1093
1094 // this prevents re-entrant calls into client code
1095 if ((listener != 0) && send) {
1096 Mutex::Autolock _l(mNotifyLock);
1097 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001098 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001099 ALOGV("back from callback");
1100 }
1101}
1102
Wei Jia53692fa2017-12-11 10:33:46 -08001103// Modular DRM
Wei Jiaec044b02018-02-19 12:41:23 -08001104status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001105 // TODO change to ALOGV
1106 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1107 drmSessionId.array(), drmSessionId.size());
1108 Mutex::Autolock _l(mLock);
1109 if (mPlayer == NULL) {
1110 return NO_INIT;
1111 }
1112
1113 // Only allowed it in player's preparing/prepared state.
1114 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1115 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1116 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1117 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
1118 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
1119 return INVALID_OPERATION;
1120 }
1121
1122 if (drmSessionId.isEmpty()) {
1123 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1124 return INVALID_OPERATION;
1125 }
1126
1127 // Passing down to mediaserver mainly for creating the crypto
1128 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1129 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1130
1131 // TODO change to ALOGV
1132 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1133
1134 return status;
1135}
1136
Wei Jiaec044b02018-02-19 12:41:23 -08001137status_t MediaPlayer2::releaseDrm() {
Wei Jia53692fa2017-12-11 10:33:46 -08001138 Mutex::Autolock _l(mLock);
1139 if (mPlayer == NULL) {
1140 return NO_INIT;
1141 }
1142
1143 // Not allowing releaseDrm in an active/resumable state
1144 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
1145 MEDIA_PLAYER2_PAUSED |
1146 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
1147 MEDIA_PLAYER2_STATE_ERROR)) {
1148 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
1149 return INVALID_OPERATION;
1150 }
1151
1152 status_t status = mPlayer->releaseDrm();
1153 // TODO change to ALOGV
1154 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1155 if (status != OK) {
1156 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1157 // Overriding to OK so the client proceed with its own cleanup
1158 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1159 status = OK;
1160 }
1161
1162 return status;
1163}
1164
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001165status_t MediaPlayer2::setPreferredDevice(jobject device) {
Wei Jia53692fa2017-12-11 10:33:46 -08001166 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001167 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001168 ALOGV("setPreferredDevice: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001169 return NO_INIT;
1170 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001171 return mAudioOutput->setPreferredDevice(device);
Wei Jia53692fa2017-12-11 10:33:46 -08001172}
1173
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001174jobject MediaPlayer2::getRoutedDevice() {
Wei Jia53692fa2017-12-11 10:33:46 -08001175 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001176 if (mAudioOutput == NULL) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001177 ALOGV("getRoutedDevice: audio sink not init");
1178 return nullptr;
Wei Jia53692fa2017-12-11 10:33:46 -08001179 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -07001180 return mAudioOutput->getRoutedDevice();
Wei Jia53692fa2017-12-11 10:33:46 -08001181}
1182
Dichen Zhangf8726912018-10-17 13:31:26 -07001183status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
1184 Mutex::Autolock _l(mLock);
1185 if (mAudioOutput == NULL) {
1186 ALOGV("addAudioDeviceCallback: player not init");
1187 mRoutingDelegates.push_back(routingDelegate);
1188 return NO_INIT;
1189 }
1190 return mAudioOutput->addAudioDeviceCallback(routingDelegate);
1191}
1192
1193status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
Wei Jia53692fa2017-12-11 10:33:46 -08001194 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001195 if (mAudioOutput == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001196 ALOGV("addAudioDeviceCallback: player not init");
1197 return NO_INIT;
1198 }
Dichen Zhangf8726912018-10-17 13:31:26 -07001199 return mAudioOutput->removeAudioDeviceCallback(listener);
Wei Jiaec044b02018-02-19 12:41:23 -08001200}
1201
1202status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
1203 const size_t SIZE = 256;
1204 char buffer[SIZE];
1205 String8 result;
1206 result.append(" MediaPlayer2\n");
1207 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
1208 result.append(buffer);
1209
1210 sp<MediaPlayer2Interface> player;
1211 sp<MediaPlayer2AudioOutput> audioOutput;
1212 bool locked = false;
1213 for (int i = 0; i < kDumpLockRetries; ++i) {
1214 if (mLock.tryLock() == NO_ERROR) {
1215 locked = true;
1216 break;
1217 }
1218 usleep(kDumpLockSleepUs);
1219 }
1220
1221 if (locked) {
1222 player = mPlayer;
1223 audioOutput = mAudioOutput;
1224 mLock.unlock();
1225 } else {
1226 result.append(" lock is taken, no dump from player and audio output\n");
1227 }
1228 write(fd, result.string(), result.size());
1229
1230 if (player != NULL) {
1231 player->dump(fd, args);
1232 }
1233 if (audioOutput != 0) {
1234 audioOutput->dump(fd, args);
1235 }
1236 write(fd, "\n", 1);
1237 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001238}
1239
1240} // namespace android