blob: e088a01199eda88e1985da441b3f2d117bed7f90 [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
Dongwon Kang919f85f2019-01-07 14:58:00 -080021#include <android/binder_ibinder.h>
Wei Jia53692fa2017-12-11 10:33:46 -080022#include <media/AudioSystem.h>
Wei Jiac2636032018-02-01 09:15:25 -080023#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080024#include <media/MediaAnalyticsItem.h>
Wei Jiaec044b02018-02-19 12:41:23 -080025#include <media/MemoryLeakTrackUtil.h>
Wei Jia28288fb2017-12-15 13:45:29 -080026#include <media/NdkWrapper.h>
Wei Jiaec044b02018-02-19 12:41:23 -080027#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/ALooperRoster.h>
29#include <mediaplayer2/MediaPlayer2AudioOutput.h>
Wei Jia51b69562018-02-05 16:17:13 -080030#include <mediaplayer2/mediaplayer2.h>
Wei Jia53692fa2017-12-11 10:33:46 -080031
Wei Jiaec044b02018-02-19 12:41:23 -080032#include <utils/Log.h>
33#include <utils/SortedVector.h>
Wei Jia53692fa2017-12-11 10:33:46 -080034#include <utils/String8.h>
35
36#include <system/audio.h>
37#include <system/window.h>
38
Wei Jiaec044b02018-02-19 12:41:23 -080039#include <nuplayer2/NuPlayer2Driver.h>
40
41#include <dirent.h>
42#include <sys/stat.h>
Wei Jia53692fa2017-12-11 10:33:46 -080043
44namespace android {
45
Wei Jiaec044b02018-02-19 12:41:23 -080046extern ALooperRoster gLooperRoster;
47
48namespace {
49
50const int kDumpLockRetries = 50;
51const int kDumpLockSleepUs = 20000;
52
Wei Jiaec044b02018-02-19 12:41:23 -080053class proxyListener : public MediaPlayer2InterfaceListener {
54public:
55 proxyListener(const wp<MediaPlayer2> &player)
56 : mPlayer(player) { }
57
58 ~proxyListener() { };
59
Dongwon Kang41929fb2018-09-09 08:29:56 -070060 virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
61 const PlayerMessage *obj) override {
Wei Jiaec044b02018-02-19 12:41:23 -080062 sp<MediaPlayer2> player = mPlayer.promote();
63 if (player != NULL) {
64 player->notify(srcId, msg, ext1, ext2, obj);
65 }
66 }
67
68private:
69 wp<MediaPlayer2> mPlayer;
70};
71
72Mutex sRecordLock;
73SortedVector<wp<MediaPlayer2> > *sPlayers;
74
75void ensureInit_l() {
76 if (sPlayers == NULL) {
77 sPlayers = new SortedVector<wp<MediaPlayer2> >();
78 }
79}
80
81void addPlayer(const wp<MediaPlayer2>& player) {
82 Mutex::Autolock lock(sRecordLock);
83 ensureInit_l();
84 sPlayers->add(player);
85}
86
87void removePlayer(const wp<MediaPlayer2>& player) {
88 Mutex::Autolock lock(sRecordLock);
89 ensureInit_l();
90 sPlayers->remove(player);
91}
92
93/**
94 * The only arguments this understands right now are -c, -von and -voff,
95 * which are parsed by ALooperRoster::dump()
96 */
97status_t dumpPlayers(int fd, const Vector<String16>& args) {
98 const size_t SIZE = 256;
99 char buffer[SIZE];
100 String8 result;
101 SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
102
Dongwon Kang919f85f2019-01-07 14:58:00 -0800103 {
104 Mutex::Autolock lock(sRecordLock);
105 ensureInit_l();
106 for (int i = 0, n = sPlayers->size(); i < n; ++i) {
107 sp<MediaPlayer2> p = (*sPlayers)[i].promote();
108 if (p != 0) {
109 p->dump(fd, args);
110 }
111 players.add(p);
112 }
113 }
114
115 result.append(" Files opened and/or mapped:\n");
116 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
117 FILE *f = fopen(buffer, "r");
118 if (f) {
119 while (!feof(f)) {
120 fgets(buffer, SIZE, f);
121 if (strstr(buffer, " /storage/") ||
122 strstr(buffer, " /system/sounds/") ||
123 strstr(buffer, " /data/") ||
124 strstr(buffer, " /system/media/")) {
125 result.append(" ");
126 result.append(buffer);
127 }
128 }
129 fclose(f);
Wei Jiaec044b02018-02-19 12:41:23 -0800130 } else {
Dongwon Kang919f85f2019-01-07 14:58:00 -0800131 result.append("couldn't open ");
132 result.append(buffer);
133 result.append("\n");
134 }
Wei Jiaec044b02018-02-19 12:41:23 -0800135
Dongwon Kang919f85f2019-01-07 14:58:00 -0800136 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
137 DIR *d = opendir(buffer);
138 if (d) {
139 struct dirent *ent;
140 while((ent = readdir(d)) != NULL) {
141 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
142 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
143 struct stat s;
144 if (lstat(buffer, &s) == 0) {
145 if ((s.st_mode & S_IFMT) == S_IFLNK) {
146 char linkto[256];
147 int len = readlink(buffer, linkto, sizeof(linkto));
148 if(len > 0) {
149 if(len > 255) {
150 linkto[252] = '.';
151 linkto[253] = '.';
152 linkto[254] = '.';
153 linkto[255] = 0;
154 } else {
155 linkto[len] = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800156 }
Dongwon Kang919f85f2019-01-07 14:58:00 -0800157 if (strstr(linkto, "/storage/") == linkto ||
158 strstr(linkto, "/system/sounds/") == linkto ||
159 strstr(linkto, "/data/") == linkto ||
160 strstr(linkto, "/system/media/") == linkto) {
161 result.append(" ");
162 result.append(buffer);
163 result.append(" -> ");
164 result.append(linkto);
165 result.append("\n");
166 }
Wei Jiaec044b02018-02-19 12:41:23 -0800167 }
Dongwon Kang919f85f2019-01-07 14:58:00 -0800168 } else {
169 result.append(" unexpected type for ");
170 result.append(buffer);
171 result.append("\n");
Wei Jiaec044b02018-02-19 12:41:23 -0800172 }
173 }
174 }
Wei Jiaec044b02018-02-19 12:41:23 -0800175 }
Dongwon Kang919f85f2019-01-07 14:58:00 -0800176 closedir(d);
177 } else {
178 result.append("couldn't open ");
179 result.append(buffer);
180 result.append("\n");
181 }
Wei Jiaec044b02018-02-19 12:41:23 -0800182
Dongwon Kang919f85f2019-01-07 14:58:00 -0800183 gLooperRoster.dump(fd, args);
Wei Jiaec044b02018-02-19 12:41:23 -0800184
Dongwon Kang919f85f2019-01-07 14:58:00 -0800185 bool dumpMem = false;
186 bool unreachableMemory = false;
187 for (size_t i = 0; i < args.size(); i++) {
188 if (args[i] == String16("-m")) {
189 dumpMem = true;
190 } else if (args[i] == String16("--unreachable")) {
191 unreachableMemory = true;
Wei Jiaec044b02018-02-19 12:41:23 -0800192 }
193 }
Dongwon Kang919f85f2019-01-07 14:58:00 -0800194 if (dumpMem) {
195 result.append("\nDumping memory:\n");
196 std::string s = dumpMemoryAddresses(100 /* limit */);
197 result.append(s.c_str(), s.size());
198 }
199 if (unreachableMemory) {
200 result.append("\nDumping unreachable memory:\n");
201 // TODO - should limit be an argument parameter?
202 // TODO: enable GetUnreachableMemoryString if it's part of stable API
203 //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
204 //result.append(s.c_str(), s.size());
205 }
206
Wei Jiaec044b02018-02-19 12:41:23 -0800207 write(fd, result.string(), result.size());
208 return NO_ERROR;
209}
210
211} // anonymous namespace
212
213//static
Dichen Zhang23658642018-11-15 10:26:16 -0800214sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
215 sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
Wei Jiaec044b02018-02-19 12:41:23 -0800216
217 if (!player->init()) {
218 return NULL;
219 }
220
221 ALOGV("Create new player(%p)", player.get());
222
223 addPlayer(player);
224 return player;
225}
226
227// static
228status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
229 return dumpPlayers(fd, args);
230}
231
Dichen Zhang23658642018-11-15 10:26:16 -0800232MediaPlayer2::MediaPlayer2(int32_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800233 ALOGV("constructor");
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800234 mSrcId = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800235 mLockThreadId = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800236 mListener = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800237 mStreamType = AUDIO_STREAM_MUSIC;
Dichen Zhangc2465c52018-11-12 11:56:05 -0800238 mAudioAttributes = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800239 mCurrentPosition = -1;
240 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
241 mSeekPosition = -1;
242 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
243 mCurrentState = MEDIA_PLAYER2_IDLE;
Wei Jia53692fa2017-12-11 10:33:46 -0800244 mLoop = false;
Dichen Zhang7398ca02018-10-15 10:25:12 -0700245 mVolume = 1.0;
Wei Jia53692fa2017-12-11 10:33:46 -0800246 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800247 mSendLevel = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800248
Dongwon Kang919f85f2019-01-07 14:58:00 -0800249 mPid = AIBinder_getCallingPid();
250 mUid = AIBinder_getCallingUid();
Wei Jiaec044b02018-02-19 12:41:23 -0800251
Dichen Zhang23658642018-11-15 10:26:16 -0800252 mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
Wei Jia53692fa2017-12-11 10:33:46 -0800253}
254
Wei Jiaec044b02018-02-19 12:41:23 -0800255MediaPlayer2::~MediaPlayer2() {
Wei Jia53692fa2017-12-11 10:33:46 -0800256 ALOGV("destructor");
Wei Jia53692fa2017-12-11 10:33:46 -0800257 disconnect();
Wei Jiaec044b02018-02-19 12:41:23 -0800258 removePlayer(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800259}
260
Wei Jiaec044b02018-02-19 12:41:23 -0800261bool MediaPlayer2::init() {
262 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
263 // looper for notification.
264 return true;
265}
266
267void MediaPlayer2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800268 ALOGV("disconnect");
Wei Jiaec044b02018-02-19 12:41:23 -0800269 sp<MediaPlayer2Interface> p;
Wei Jia53692fa2017-12-11 10:33:46 -0800270 {
271 Mutex::Autolock _l(mLock);
272 p = mPlayer;
273 mPlayer.clear();
274 }
275
276 if (p != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800277 p->setListener(NULL);
278 p->reset();
279 }
280
281 {
282 Mutex::Autolock _l(mLock);
283 disconnectNativeWindow_l();
Wei Jia53692fa2017-12-11 10:33:46 -0800284 }
285}
286
Wei Jiaec044b02018-02-19 12:41:23 -0800287void MediaPlayer2::clear_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800288 mCurrentPosition = -1;
289 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
290 mSeekPosition = -1;
291 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
292 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800293}
294
Wei Jiaec044b02018-02-19 12:41:23 -0800295status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
Wei Jia53692fa2017-12-11 10:33:46 -0800296 ALOGV("setListener");
297 Mutex::Autolock _l(mLock);
298 mListener = listener;
299 return NO_ERROR;
300}
301
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800302status_t MediaPlayer2::getSrcId(int64_t *srcId) {
303 if (srcId == NULL) {
304 return BAD_VALUE;
305 }
Wei Jia53692fa2017-12-11 10:33:46 -0800306
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800307 Mutex::Autolock _l(mLock);
308 *srcId = mSrcId;
309 return OK;
310}
311
Wei Jiaec044b02018-02-19 12:41:23 -0800312status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jiac2636032018-02-01 09:15:25 -0800313 if (dsd == NULL) {
314 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800315 }
Wei Jiaf01e3122018-10-18 11:49:44 -0700316 // Microsecond is used in NuPlayer2.
Wei Jiae31ac8a2018-10-25 11:06:21 -0700317 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
318 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700319 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
320 }
Wei Jiae31ac8a2018-10-25 11:06:21 -0700321 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
322 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700323 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
324 }
Wei Jiaec044b02018-02-19 12:41:23 -0800325 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
326
327 sp<MediaPlayer2Interface> oldPlayer;
328
329 Mutex::Autolock _l(mLock);
330 {
331 if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
332 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
333 ALOGE("setDataSource called in wrong state %d", mCurrentState);
334 return INVALID_OPERATION;
335 }
336
337 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
338 status_t err = player->initCheck();
339 if (err != NO_ERROR) {
340 ALOGE("Failed to create player object, initCheck failed(%d)", err);
341 return err;
342 }
343
344 clear_l();
345
346 player->setListener(new proxyListener(this));
Wei Jiaec044b02018-02-19 12:41:23 -0800347 player->setAudioSink(mAudioOutput);
348
349 err = player->setDataSource(dsd);
350 if (err != OK) {
351 ALOGE("setDataSource error: %d", err);
352 return err;
353 }
354
355 sp<MediaPlayer2Interface> oldPlayer = mPlayer;
356 mPlayer = player;
357 mSrcId = dsd->mId;
358 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
Wei Jia53692fa2017-12-11 10:33:46 -0800359 }
Wei Jiaec044b02018-02-19 12:41:23 -0800360
361 if (oldPlayer != NULL) {
362 oldPlayer->setListener(NULL);
363 oldPlayer->reset();
364 }
365
366 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800367}
368
Wei Jia57aeffd2018-02-15 16:01:14 -0800369status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
370 if (dsd == NULL) {
371 return BAD_VALUE;
372 }
373 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
374
375 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800376 if (mPlayer == NULL) {
377 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
378 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800379 }
Wei Jiaec044b02018-02-19 12:41:23 -0800380 return mPlayer->prepareNextDataSource(dsd);
Wei Jia57aeffd2018-02-15 16:01:14 -0800381}
382
383status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
384 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
385
386 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800387 if (mPlayer == NULL) {
388 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
389 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800390 }
Wei Jiaec044b02018-02-19 12:41:23 -0800391 mSrcId = srcId;
392 return mPlayer->playNextDataSource(srcId);
Wei Jia57aeffd2018-02-15 16:01:14 -0800393}
394
Dongwon Kang9f631982018-07-10 12:34:41 -0700395status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800396 Mutex::Autolock _l(mLock);
397 const bool hasBeenInitialized =
398 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
399 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
Wei Jiaec044b02018-02-19 12:41:23 -0800400 if ((mPlayer == NULL) || !hasBeenInitialized) {
Dongwon Kang9f631982018-07-10 12:34:41 -0700401 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Wei Jiaec044b02018-02-19 12:41:23 -0800402 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800403 }
Wei Jiaec044b02018-02-19 12:41:23 -0800404 return mPlayer->invoke(request, reply);
Wei Jia53692fa2017-12-11 10:33:46 -0800405}
406
Wei Jiaec044b02018-02-19 12:41:23 -0800407void MediaPlayer2::disconnectNativeWindow_l() {
408 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
409 status_t err = native_window_api_disconnect(
410 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
411
412 if (err != OK) {
413 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
414 strerror(-err), err);
415 }
416 }
417 mConnectedWindow.clear();
418}
419
420status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
421 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
422 ALOGV("setVideoSurfaceTexture(%p)", anw);
423 Mutex::Autolock _l(mLock);
424 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800425 return NO_INIT;
426 }
Wei Jiaec044b02018-02-19 12:41:23 -0800427
428 if (anw != NULL) {
429 if (mConnectedWindow != NULL
430 && mConnectedWindow->getANativeWindow() == anw) {
431 return OK;
432 }
433 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
434
435 if (err != OK) {
436 ALOGE("setVideoSurfaceTexture failed: %d", err);
437 // Note that we must do the reset before disconnecting from the ANW.
438 // Otherwise queue/dequeue calls could be made on the disconnected
439 // ANW, which may result in errors.
440 mPlayer->reset();
441 disconnectNativeWindow_l();
442 return err;
443 }
444 }
445
446 // Note that we must set the player's new GraphicBufferProducer before
447 // disconnecting the old one. Otherwise queue/dequeue calls could be made
448 // on the disconnected ANW, which may result in errors.
449 status_t err = mPlayer->setVideoSurfaceTexture(nww);
450
451 disconnectNativeWindow_l();
452
453 if (err == OK) {
454 mConnectedWindow = nww;
455 mLock.unlock();
456 } else if (anw != NULL) {
457 mLock.unlock();
458 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
459
460 if (err != OK) {
461 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
462 strerror(-err), err);
463 }
464 }
465
466 return err;
Wei Jia53692fa2017-12-11 10:33:46 -0800467}
468
Wei Jiaec044b02018-02-19 12:41:23 -0800469status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800470 ALOGV("getBufferingSettings");
471
472 Mutex::Autolock _l(mLock);
473 if (mPlayer == 0) {
474 return NO_INIT;
475 }
Wei Jiaec044b02018-02-19 12:41:23 -0800476
477 status_t ret = mPlayer->getBufferingSettings(buffering);
478 if (ret == NO_ERROR) {
479 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
480 } else {
481 ALOGE("getBufferingSettings returned %d", ret);
482 }
483 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800484}
485
Wei Jiaec044b02018-02-19 12:41:23 -0800486status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
487 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Wei Jia53692fa2017-12-11 10:33:46 -0800488
489 Mutex::Autolock _l(mLock);
490 if (mPlayer == 0) {
491 return NO_INIT;
492 }
493 return mPlayer->setBufferingSettings(buffering);
494}
495
Dichen Zhangc2465c52018-11-12 11:56:05 -0800496status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
497 if (mAudioOutput != NULL) {
498 mAudioOutput->setAudioAttributes(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800499 }
500 return NO_ERROR;
501}
502
503status_t MediaPlayer2::prepareAsync() {
504 ALOGV("prepareAsync");
505 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700506 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
Dichen Zhangc2465c52018-11-12 11:56:05 -0800507 if (mAudioAttributes != NULL) {
508 status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
Wei Jiaec044b02018-02-19 12:41:23 -0800509 if (err != OK) {
510 return err;
511 }
Wei Jia53692fa2017-12-11 10:33:46 -0800512 }
513 mCurrentState = MEDIA_PLAYER2_PREPARING;
514 return mPlayer->prepareAsync();
515 }
516 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
517 return INVALID_OPERATION;
518}
519
Wei Jiaec044b02018-02-19 12:41:23 -0800520status_t MediaPlayer2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800521 ALOGV("start");
522
523 status_t ret = NO_ERROR;
524 Mutex::Autolock _l(mLock);
525
526 mLockThreadId = getThreadId();
527
528 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
529 ret = NO_ERROR;
530 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
531 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
532 mPlayer->setLooping(mLoop);
Wei Jiaec044b02018-02-19 12:41:23 -0800533
534 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700535 mAudioOutput->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800536 }
537
538 if (mAudioOutput != 0) {
539 mAudioOutput->setAuxEffectSendLevel(mSendLevel);
540 }
Wei Jia53692fa2017-12-11 10:33:46 -0800541 mCurrentState = MEDIA_PLAYER2_STARTED;
542 ret = mPlayer->start();
543 if (ret != NO_ERROR) {
544 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
545 } else {
546 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
547 ALOGV("playback completed immediately following start()");
548 }
549 }
550 } else {
551 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
552 ret = INVALID_OPERATION;
553 }
554
555 mLockThreadId = 0;
556
557 return ret;
558}
559
Wei Jiaec044b02018-02-19 12:41:23 -0800560status_t MediaPlayer2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800561 ALOGV("pause");
562 Mutex::Autolock _l(mLock);
563 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
564 return NO_ERROR;
Wei Jia6376cd52018-09-26 11:42:55 -0700565 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
Wei Jia53692fa2017-12-11 10:33:46 -0800566 status_t ret = mPlayer->pause();
567 if (ret != NO_ERROR) {
568 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
569 } else {
570 mCurrentState = MEDIA_PLAYER2_PAUSED;
571 }
572 return ret;
573 }
574 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
575 return INVALID_OPERATION;
576}
577
Wei Jiaec044b02018-02-19 12:41:23 -0800578bool MediaPlayer2::isPlaying() {
Wei Jia53692fa2017-12-11 10:33:46 -0800579 Mutex::Autolock _l(mLock);
580 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800581 bool temp = mPlayer->isPlaying();
Wei Jia53692fa2017-12-11 10:33:46 -0800582 ALOGV("isPlaying: %d", temp);
583 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
584 ALOGE("internal/external state mismatch corrected");
585 mCurrentState = MEDIA_PLAYER2_PAUSED;
586 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
587 ALOGE("internal/external state mismatch corrected");
588 mCurrentState = MEDIA_PLAYER2_STARTED;
589 }
590 return temp;
591 }
592 ALOGV("isPlaying: no active player");
593 return false;
594}
595
Wei Jia1f043e42018-06-20 16:52:50 -0700596mediaplayer2_states MediaPlayer2::getState() {
Wei Jia98787a72018-03-02 14:33:06 -0800597 Mutex::Autolock _l(mLock);
598 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
599 return MEDIAPLAYER2_STATE_ERROR;
600 }
601 if (mPlayer == 0
602 || (mCurrentState &
603 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
604 return MEDIAPLAYER2_STATE_IDLE;
605 }
606 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
607 return MEDIAPLAYER2_STATE_PLAYING;
608 }
Wei Jia0151ef42018-08-24 16:40:21 -0700609 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
Wei Jia98787a72018-03-02 14:33:06 -0800610 return MEDIAPLAYER2_STATE_PAUSED;
611 }
612 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
613 return MEDIAPLAYER2_STATE_PREPARED;
614}
615
Wei Jiaec044b02018-02-19 12:41:23 -0800616status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
Wei Jia53692fa2017-12-11 10:33:46 -0800617 ALOGV("setPlaybackSettings: %f %f %d %d",
618 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
619 // Negative speed and pitch does not make sense. Further validation will
620 // be done by the respective mediaplayers.
Wei Jiaec044b02018-02-19 12:41:23 -0800621 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
Wei Jia53692fa2017-12-11 10:33:46 -0800622 return BAD_VALUE;
623 }
624 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700625 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800626 return INVALID_OPERATION;
627 }
628
Wei Jia53692fa2017-12-11 10:33:46 -0800629 status_t err = mPlayer->setPlaybackSettings(rate);
Wei Jia53692fa2017-12-11 10:33:46 -0800630 return err;
631}
632
Wei Jiaec044b02018-02-19 12:41:23 -0800633status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800634 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800635 if (mPlayer == 0) {
636 return INVALID_OPERATION;
637 }
Wei Jiaec044b02018-02-19 12:41:23 -0800638 status_t ret = mPlayer->getPlaybackSettings(rate);
639 if (ret == NO_ERROR) {
640 ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
641 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
642 } else {
643 ALOGV("getPlaybackSettings returned %d", ret);
644 }
645 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800646}
647
Wei Jiaec044b02018-02-19 12:41:23 -0800648status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
Wei Jia53692fa2017-12-11 10:33:46 -0800649 ALOGV("setSyncSettings: %u %u %f %f",
650 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
651 Mutex::Autolock _l(mLock);
652 if (mPlayer == 0) return INVALID_OPERATION;
653 return mPlayer->setSyncSettings(sync, videoFpsHint);
654}
655
656status_t MediaPlayer2::getSyncSettings(
Wei Jiaec044b02018-02-19 12:41:23 -0800657 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800658 Mutex::Autolock _l(mLock);
Wei Jia334adf02018-03-23 14:08:23 -0700659 if (mPlayer == 0) {
660 return INVALID_OPERATION;
661 }
Wei Jiaec044b02018-02-19 12:41:23 -0800662 status_t ret = mPlayer->getSyncSettings(sync, videoFps);
663 if (ret == NO_ERROR) {
664 ALOGV("getSyncSettings(%u, %u, %f, %f)",
665 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
666 } else {
667 ALOGV("getSyncSettings returned %d", ret);
668 }
669 return ret;
670
Wei Jia53692fa2017-12-11 10:33:46 -0800671}
672
Wei Jiaec044b02018-02-19 12:41:23 -0800673status_t MediaPlayer2::getVideoWidth(int *w) {
Wei Jia53692fa2017-12-11 10:33:46 -0800674 ALOGV("getVideoWidth");
675 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800676 if (mPlayer == 0) {
677 return INVALID_OPERATION;
678 }
Wei Jia53692fa2017-12-11 10:33:46 -0800679 *w = mVideoWidth;
680 return NO_ERROR;
681}
682
Wei Jiaec044b02018-02-19 12:41:23 -0800683status_t MediaPlayer2::getVideoHeight(int *h) {
Wei Jia53692fa2017-12-11 10:33:46 -0800684 ALOGV("getVideoHeight");
685 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800686 if (mPlayer == 0) {
687 return INVALID_OPERATION;
688 }
Wei Jia53692fa2017-12-11 10:33:46 -0800689 *h = mVideoHeight;
690 return NO_ERROR;
691}
692
Wei Jia800fe372018-02-20 15:00:45 -0800693status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800694 ALOGV("getCurrentPosition");
695 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800696 if (mPlayer == 0) {
697 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800698 }
Wei Jiaec044b02018-02-19 12:41:23 -0800699 if (mCurrentPosition >= 0) {
Wei Jia800fe372018-02-20 15:00:45 -0800700 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
Wei Jiaec044b02018-02-19 12:41:23 -0800701 *msec = mCurrentPosition;
702 return NO_ERROR;
703 }
704 status_t ret = mPlayer->getCurrentPosition(msec);
705 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800706 ALOGV("getCurrentPosition = %lld", (long long)*msec);
Wei Jiaec044b02018-02-19 12:41:23 -0800707 } else {
708 ALOGE("getCurrentPosition returned %d", ret);
709 }
710 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800711}
712
Wei Jia17944af2018-12-13 18:13:10 -0800713status_t MediaPlayer2::getDuration(int64_t srcId, int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800714 Mutex::Autolock _l(mLock);
Wei Jia17944af2018-12-13 18:13:10 -0800715 // TODO: cache duration for currentSrcId and nextSrcId, and return correct
716 // value for nextSrcId.
717 if (srcId != mSrcId) {
718 *msec = -1;
719 return OK;
720 }
721
Wei Jia53692fa2017-12-11 10:33:46 -0800722 ALOGV("getDuration_l");
723 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700724 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800725 if (mPlayer == 0 || !isValidState) {
726 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
727 mPlayer.get(), mCurrentState);
728 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800729 }
Wei Jia800fe372018-02-20 15:00:45 -0800730 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800731 status_t ret = mPlayer->getDuration(&durationMs);
732
733 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800734 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800735 } else {
736 ALOGE("getDuration returned %d", ret);
737 // Do not enter error state just because no duration was available.
738 durationMs = -1;
739 }
740
741 if (msec) {
742 *msec = durationMs;
743 }
744 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800745}
746
Wei Jia800fe372018-02-20 15:00:45 -0800747status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
748 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
749 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
750 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
751 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
752 mPlayer.get(), mCurrentState);
753 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800754 }
Wei Jia800fe372018-02-20 15:00:45 -0800755 if (msec < 0) {
756 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
757 msec = 0;
758 }
759
760 int64_t durationMs;
761 status_t err = mPlayer->getDuration(&durationMs);
762
763 if (err != OK) {
764 ALOGW("Stream has no duration and is therefore not seekable.");
765 return err;
766 }
767
768 if (msec > durationMs) {
769 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
770 (long long)msec, (long long)durationMs);
771
772 msec = durationMs;
773 }
774
775 // cache duration
776 mCurrentPosition = msec;
777 mCurrentSeekMode = mode;
778 if (mSeekPosition < 0) {
779 mSeekPosition = msec;
780 mSeekMode = mode;
781 return mPlayer->seekTo(msec, mode);
782 }
783 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
784 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800785}
786
Wei Jia800fe372018-02-20 15:00:45 -0800787status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800788 mLockThreadId = getThreadId();
789 Mutex::Autolock _l(mLock);
790 status_t result = seekTo_l(msec, mode);
791 mLockThreadId = 0;
792
793 return result;
794}
795
Wei Jiaec044b02018-02-19 12:41:23 -0800796status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800797 Mutex::Autolock _l(mLock);
798 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800799 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800800 }
Wei Jiaec044b02018-02-19 12:41:23 -0800801
802 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800803}
804
Wei Jiaec044b02018-02-19 12:41:23 -0800805status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800806 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800807 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
808 return NO_ERROR;
809 }
Wei Jia53692fa2017-12-11 10:33:46 -0800810 if (mPlayer != 0) {
811 status_t ret = mPlayer->reset();
812 if (ret != NO_ERROR) {
813 ALOGE("reset() failed with return code (%d)", ret);
814 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
815 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800816 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800817 mCurrentState = MEDIA_PLAYER2_IDLE;
818 }
819 // setDataSource has to be called again to create a
820 // new mediaplayer.
821 mPlayer = 0;
822 return ret;
823 }
824 clear_l();
825 return NO_ERROR;
826}
827
Wei Jiaec044b02018-02-19 12:41:23 -0800828status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800829 ALOGV("reset");
830 mLockThreadId = getThreadId();
831 Mutex::Autolock _l(mLock);
832 status_t result = reset_l();
833 mLockThreadId = 0;
834
835 return result;
836}
837
Wei Jiaec044b02018-02-19 12:41:23 -0800838status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800839 ALOGV("MediaPlayer2::setAudioStreamType");
840 Mutex::Autolock _l(mLock);
841 if (mStreamType == type) return NO_ERROR;
842 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
843 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
844 // Can't change the stream type after prepare
845 ALOGE("setAudioStream called in state %d", mCurrentState);
846 return INVALID_OPERATION;
847 }
848 // cache
849 mStreamType = type;
850 return OK;
851}
852
Wei Jiaec044b02018-02-19 12:41:23 -0800853status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800854 ALOGV("getAudioStreamType");
855 Mutex::Autolock _l(mLock);
856 *type = mStreamType;
857 return OK;
858}
859
Wei Jiaec044b02018-02-19 12:41:23 -0800860status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800861 ALOGV("MediaPlayer2::setLooping");
862 Mutex::Autolock _l(mLock);
863 mLoop = (loop != 0);
864 if (mPlayer != 0) {
865 return mPlayer->setLooping(loop);
866 }
867 return OK;
868}
869
870bool MediaPlayer2::isLooping() {
871 ALOGV("isLooping");
872 Mutex::Autolock _l(mLock);
873 if (mPlayer != 0) {
874 return mLoop;
875 }
876 ALOGV("isLooping: no active player");
877 return false;
878}
879
Dichen Zhang7398ca02018-10-15 10:25:12 -0700880status_t MediaPlayer2::setVolume(float volume) {
881 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800882 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700883 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800884 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700885 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800886 }
887 return OK;
888}
889
Dichen Zhang23658642018-11-15 10:26:16 -0800890status_t MediaPlayer2::setAudioSessionId(int32_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800891 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
892 Mutex::Autolock _l(mLock);
893 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
894 ALOGE("setAudioSessionId called in state %d", mCurrentState);
895 return INVALID_OPERATION;
896 }
897 if (sessionId < 0) {
898 return BAD_VALUE;
899 }
Dichen Zhang23658642018-11-15 10:26:16 -0800900 if (mAudioOutput != NULL && sessionId != mAudioOutput->getSessionId()) {
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000901 mAudioOutput->setSessionId(sessionId);
902 }
Wei Jia53692fa2017-12-11 10:33:46 -0800903 return NO_ERROR;
904}
905
Dichen Zhang23658642018-11-15 10:26:16 -0800906int32_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800907 Mutex::Autolock _l(mLock);
Dichen Zhang23658642018-11-15 10:26:16 -0800908 if (mAudioOutput != NULL) {
909 return mAudioOutput->getSessionId();
910 }
911 return 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800912}
913
Wei Jiaec044b02018-02-19 12:41:23 -0800914status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800915 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
916 Mutex::Autolock _l(mLock);
917 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800918 if (mAudioOutput != 0) {
919 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -0800920 }
921 return OK;
922}
923
Wei Jiaec044b02018-02-19 12:41:23 -0800924status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800925 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
926 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800927 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -0800928 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
929 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
930 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
931 return INVALID_OPERATION;
932 }
933
Wei Jiaec044b02018-02-19 12:41:23 -0800934 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -0800935}
936
937// always call with lock held
Dichen Zhangc2465c52018-11-12 11:56:05 -0800938status_t MediaPlayer2::checkState_l() {
939 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
940 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
941 // Can't change the audio attributes after prepare
942 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
943 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800944 }
945 return OK;
946}
947
Dichen Zhangc2465c52018-11-12 11:56:05 -0800948status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
949 ALOGV("MediaPlayer2::setAudioAttributes");
Wei Jia53692fa2017-12-11 10:33:46 -0800950 status_t status = INVALID_OPERATION;
951 Mutex::Autolock _l(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800952 if (checkState_l() != OK) {
Wei Jia53692fa2017-12-11 10:33:46 -0800953 return status;
954 }
Dichen Zhangc2465c52018-11-12 11:56:05 -0800955 mAudioAttributes = new JObjectHolder(attributes);
956 status = setAudioAttributes_l(attributes);
Wei Jia53692fa2017-12-11 10:33:46 -0800957 return status;
958}
959
Dichen Zhangc2465c52018-11-12 11:56:05 -0800960jobject MediaPlayer2::getAudioAttributes() {
961 ALOGV("MediaPlayer2::getAudioAttributes)");
962 Mutex::Autolock _l(mLock);
963 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
964}
965
Wei Jiaec044b02018-02-19 12:41:23 -0800966status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800967 ALOGV("MediaPlayer2::getParameter(%d)", key);
968 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800969 if (mPlayer == NULL) {
970 ALOGV("getParameter: no active player");
971 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800972 }
Wei Jiaec044b02018-02-19 12:41:23 -0800973
974 status_t status = mPlayer->getParameter(key, reply);
975 if (status != OK) {
976 ALOGD("getParameter returns %d", status);
977 }
978 return status;
Wei Jia53692fa2017-12-11 10:33:46 -0800979}
980
Dongwon Kang41929fb2018-09-09 08:29:56 -0700981void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800982 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
983 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -0800984
Wei Jia53692fa2017-12-11 10:33:46 -0800985 bool send = true;
986 bool locked = false;
987
988 // TODO: In the future, we might be on the same thread if the app is
989 // running in the same process as the media server. In that case,
990 // this will deadlock.
991 //
992 // The threadId hack below works around this for the care of prepare,
993 // seekTo, start, and reset within the same process.
994 // FIXME: Remember, this is a hack, it's not even a hack that is applied
995 // consistently for all use-cases, this needs to be revisited.
996 if (mLockThreadId != getThreadId()) {
997 mLock.lock();
998 locked = true;
999 }
1000
1001 // Allows calls from JNI in idle state to notify errors
1002 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001003 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1004 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001005 if (locked) mLock.unlock(); // release the lock when done.
1006 return;
1007 }
1008
1009 switch (msg) {
1010 case MEDIA2_NOP: // interface test message
1011 break;
1012 case MEDIA2_PREPARED:
1013 ALOGV("MediaPlayer2::notify() prepared");
1014 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001015 break;
1016 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001017 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1018 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001019 break;
1020 case MEDIA2_PLAYBACK_COMPLETE:
1021 ALOGV("playback complete");
1022 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1023 ALOGE("playback complete in idle state");
1024 }
1025 if (!mLoop) {
1026 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1027 }
1028 break;
1029 case MEDIA2_ERROR:
1030 // Always log errors.
1031 // ext1: Media framework error code.
1032 // ext2: Implementation dependant error code.
1033 ALOGE("error (%d, %d)", ext1, ext2);
1034 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001035 break;
1036 case MEDIA2_INFO:
1037 // ext1: Media framework error code.
1038 // ext2: Implementation dependant error code.
1039 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1040 ALOGW("info/warning (%d, %d)", ext1, ext2);
1041 }
1042 break;
1043 case MEDIA2_SEEK_COMPLETE:
1044 ALOGV("Received seek complete");
1045 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001046 ALOGV("Executing queued seekTo(%lld, %d)",
1047 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001048 mSeekPosition = -1;
1049 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1050 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1051 }
1052 else {
1053 ALOGV("All seeks complete - return to regularly scheduled program");
1054 mCurrentPosition = mSeekPosition = -1;
1055 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1056 }
1057 break;
1058 case MEDIA2_BUFFERING_UPDATE:
1059 ALOGV("buffering %d", ext1);
1060 break;
1061 case MEDIA2_SET_VIDEO_SIZE:
1062 ALOGV("New video size %d x %d", ext1, ext2);
1063 mVideoWidth = ext1;
1064 mVideoHeight = ext2;
1065 break;
1066 case MEDIA2_NOTIFY_TIME:
1067 ALOGV("Received notify time message");
1068 break;
1069 case MEDIA2_TIMED_TEXT:
1070 ALOGV("Received timed text message");
1071 break;
1072 case MEDIA2_SUBTITLE_DATA:
1073 ALOGV("Received subtitle data message");
1074 break;
1075 case MEDIA2_META_DATA:
1076 ALOGV("Received timed metadata message");
1077 break;
1078 default:
1079 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1080 break;
1081 }
1082
1083 sp<MediaPlayer2Listener> listener = mListener;
1084 if (locked) mLock.unlock();
1085
1086 // this prevents re-entrant calls into client code
1087 if ((listener != 0) && send) {
1088 Mutex::Autolock _l(mNotifyLock);
1089 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001090 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001091 ALOGV("back from callback");
1092 }
1093}
1094
Wei Jia53692fa2017-12-11 10:33:46 -08001095// Modular DRM
Robert Shih3c3728d2018-12-04 17:06:36 -08001096status_t MediaPlayer2::prepareDrm(
1097 int64_t srcId, 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
Robert Shih3c3728d2018-12-04 17:06:36 -08001121 status_t status = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
Wei Jia53692fa2017-12-11 10:33:46 -08001122 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
Robert Shih3c3728d2018-12-04 17:06:36 -08001130status_t MediaPlayer2::releaseDrm(int64_t srcId) {
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
Robert Shih3c3728d2018-12-04 17:06:36 -08001145 status_t status = mPlayer->releaseDrm(srcId);
Wei Jia53692fa2017-12-11 10:33:46 -08001146 // 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