blob: 4960694997b5d093d074f465f9b263a89eff6c38 [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 -080056// marshalling tag indicating flattened utf16 tags
57// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
58const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
59
60// Audio attributes format in a parcel:
61//
62// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
63// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64// | usage |
65// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66// | content_type |
67// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68// | source |
69// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70// | flags |
71// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72// | kAudioAttributesMarshallTagFlattenTags | // ignore tags if not found
73// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74// | flattened tags in UTF16 |
75// | ... |
76// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77//
78// @param p Parcel that contains audio attributes.
79// @param[out] attributes On exit points to an initialized audio_attributes_t structure
80// @param[out] status On exit contains the status code to be returned.
81void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes) {
82 attributes->usage = (audio_usage_t) parcel.readInt32();
83 attributes->content_type = (audio_content_type_t) parcel.readInt32();
84 attributes->source = (audio_source_t) parcel.readInt32();
85 attributes->flags = (audio_flags_mask_t) parcel.readInt32();
86 const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
87 if (hasFlattenedTag) {
88 // the tags are UTF16, convert to UTF8
89 String16 tags = parcel.readString16();
90 ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
91 if (realTagSize <= 0) {
92 strcpy(attributes->tags, "");
93 } else {
94 // copy the flattened string into the attributes as the destination for the conversion:
95 // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
96 size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
97 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
98 utf16_to_utf8(tags.string(), tagSize, attributes->tags,
99 sizeof(attributes->tags) / sizeof(attributes->tags[0]));
100 }
101 } else {
102 ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
103 strcpy(attributes->tags, "");
104 }
105}
106
Wei Jiaec044b02018-02-19 12:41:23 -0800107class proxyListener : public MediaPlayer2InterfaceListener {
108public:
109 proxyListener(const wp<MediaPlayer2> &player)
110 : mPlayer(player) { }
111
112 ~proxyListener() { };
113
Dongwon Kang41929fb2018-09-09 08:29:56 -0700114 virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
115 const PlayerMessage *obj) override {
Wei Jiaec044b02018-02-19 12:41:23 -0800116 sp<MediaPlayer2> player = mPlayer.promote();
117 if (player != NULL) {
118 player->notify(srcId, msg, ext1, ext2, obj);
119 }
120 }
121
122private:
123 wp<MediaPlayer2> mPlayer;
124};
125
126Mutex sRecordLock;
127SortedVector<wp<MediaPlayer2> > *sPlayers;
128
129void ensureInit_l() {
130 if (sPlayers == NULL) {
131 sPlayers = new SortedVector<wp<MediaPlayer2> >();
132 }
133}
134
135void addPlayer(const wp<MediaPlayer2>& player) {
136 Mutex::Autolock lock(sRecordLock);
137 ensureInit_l();
138 sPlayers->add(player);
139}
140
141void removePlayer(const wp<MediaPlayer2>& player) {
142 Mutex::Autolock lock(sRecordLock);
143 ensureInit_l();
144 sPlayers->remove(player);
145}
146
147/**
148 * The only arguments this understands right now are -c, -von and -voff,
149 * which are parsed by ALooperRoster::dump()
150 */
151status_t dumpPlayers(int fd, const Vector<String16>& args) {
152 const size_t SIZE = 256;
153 char buffer[SIZE];
154 String8 result;
155 SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
156
157 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
158 snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
159 result.append(buffer);
160 } else {
161 {
162 Mutex::Autolock lock(sRecordLock);
163 ensureInit_l();
164 for (int i = 0, n = sPlayers->size(); i < n; ++i) {
165 sp<MediaPlayer2> p = (*sPlayers)[i].promote();
166 if (p != 0) {
167 p->dump(fd, args);
168 }
169 players.add(p);
170 }
171 }
172
173 result.append(" Files opened and/or mapped:\n");
174 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
175 FILE *f = fopen(buffer, "r");
176 if (f) {
177 while (!feof(f)) {
178 fgets(buffer, SIZE, f);
179 if (strstr(buffer, " /storage/") ||
180 strstr(buffer, " /system/sounds/") ||
181 strstr(buffer, " /data/") ||
182 strstr(buffer, " /system/media/")) {
183 result.append(" ");
184 result.append(buffer);
185 }
186 }
187 fclose(f);
188 } else {
189 result.append("couldn't open ");
190 result.append(buffer);
191 result.append("\n");
192 }
193
194 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
195 DIR *d = opendir(buffer);
196 if (d) {
197 struct dirent *ent;
198 while((ent = readdir(d)) != NULL) {
199 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
200 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
201 struct stat s;
202 if (lstat(buffer, &s) == 0) {
203 if ((s.st_mode & S_IFMT) == S_IFLNK) {
204 char linkto[256];
205 int len = readlink(buffer, linkto, sizeof(linkto));
206 if(len > 0) {
207 if(len > 255) {
208 linkto[252] = '.';
209 linkto[253] = '.';
210 linkto[254] = '.';
211 linkto[255] = 0;
212 } else {
213 linkto[len] = 0;
214 }
215 if (strstr(linkto, "/storage/") == linkto ||
216 strstr(linkto, "/system/sounds/") == linkto ||
217 strstr(linkto, "/data/") == linkto ||
218 strstr(linkto, "/system/media/") == linkto) {
219 result.append(" ");
220 result.append(buffer);
221 result.append(" -> ");
222 result.append(linkto);
223 result.append("\n");
224 }
225 }
226 } else {
227 result.append(" unexpected type for ");
228 result.append(buffer);
229 result.append("\n");
230 }
231 }
232 }
233 }
234 closedir(d);
235 } else {
236 result.append("couldn't open ");
237 result.append(buffer);
238 result.append("\n");
239 }
240
241 gLooperRoster.dump(fd, args);
242
243 bool dumpMem = false;
244 bool unreachableMemory = false;
245 for (size_t i = 0; i < args.size(); i++) {
246 if (args[i] == String16("-m")) {
247 dumpMem = true;
248 } else if (args[i] == String16("--unreachable")) {
249 unreachableMemory = true;
250 }
251 }
252 if (dumpMem) {
253 result.append("\nDumping memory:\n");
254 std::string s = dumpMemoryAddresses(100 /* limit */);
255 result.append(s.c_str(), s.size());
256 }
257 if (unreachableMemory) {
258 result.append("\nDumping unreachable memory:\n");
259 // TODO - should limit be an argument parameter?
260 // TODO: enable GetUnreachableMemoryString if it's part of stable API
261 //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
262 //result.append(s.c_str(), s.size());
263 }
264 }
265 write(fd, result.string(), result.size());
266 return NO_ERROR;
267}
268
269} // anonymous namespace
270
271//static
272sp<MediaPlayer2> MediaPlayer2::Create() {
273 sp<MediaPlayer2> player = new MediaPlayer2();
274
275 if (!player->init()) {
276 return NULL;
277 }
278
279 ALOGV("Create new player(%p)", player.get());
280
281 addPlayer(player);
282 return player;
283}
284
285// static
286status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
287 return dumpPlayers(fd, args);
288}
289
290MediaPlayer2::MediaPlayer2() {
Wei Jia53692fa2017-12-11 10:33:46 -0800291 ALOGV("constructor");
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800292 mSrcId = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800293 mLockThreadId = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800294 mListener = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800295 mStreamType = AUDIO_STREAM_MUSIC;
296 mAudioAttributesParcel = NULL;
297 mCurrentPosition = -1;
298 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
299 mSeekPosition = -1;
300 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
301 mCurrentState = MEDIA_PLAYER2_IDLE;
Wei Jia53692fa2017-12-11 10:33:46 -0800302 mLoop = false;
Dichen Zhang7398ca02018-10-15 10:25:12 -0700303 mVolume = 1.0;
Wei Jia53692fa2017-12-11 10:33:46 -0800304 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800305 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
306 AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
307 mSendLevel = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800308
309 // TODO: get pid and uid from JAVA
310 mPid = IPCThreadState::self()->getCallingPid();
311 mUid = IPCThreadState::self()->getCallingUid();
312
313 mAudioAttributes = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800314}
315
Wei Jiaec044b02018-02-19 12:41:23 -0800316MediaPlayer2::~MediaPlayer2() {
Wei Jia53692fa2017-12-11 10:33:46 -0800317 ALOGV("destructor");
318 if (mAudioAttributesParcel != NULL) {
319 delete mAudioAttributesParcel;
320 mAudioAttributesParcel = NULL;
321 }
322 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
323 disconnect();
Wei Jiaec044b02018-02-19 12:41:23 -0800324 removePlayer(this);
325 if (mAudioAttributes != NULL) {
326 free(mAudioAttributes);
327 }
Wei Jia53692fa2017-12-11 10:33:46 -0800328}
329
Wei Jiaec044b02018-02-19 12:41:23 -0800330bool MediaPlayer2::init() {
331 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
332 // looper for notification.
333 return true;
334}
335
336void MediaPlayer2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800337 ALOGV("disconnect");
Wei Jiaec044b02018-02-19 12:41:23 -0800338 sp<MediaPlayer2Interface> p;
Wei Jia53692fa2017-12-11 10:33:46 -0800339 {
340 Mutex::Autolock _l(mLock);
341 p = mPlayer;
342 mPlayer.clear();
343 }
344
345 if (p != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800346 p->setListener(NULL);
347 p->reset();
348 }
349
350 {
351 Mutex::Autolock _l(mLock);
352 disconnectNativeWindow_l();
Wei Jia53692fa2017-12-11 10:33:46 -0800353 }
354}
355
Wei Jiaec044b02018-02-19 12:41:23 -0800356void MediaPlayer2::clear_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800357 mCurrentPosition = -1;
358 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
359 mSeekPosition = -1;
360 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
361 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800362}
363
Wei Jiaec044b02018-02-19 12:41:23 -0800364status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
Wei Jia53692fa2017-12-11 10:33:46 -0800365 ALOGV("setListener");
366 Mutex::Autolock _l(mLock);
367 mListener = listener;
368 return NO_ERROR;
369}
370
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800371status_t MediaPlayer2::getSrcId(int64_t *srcId) {
372 if (srcId == NULL) {
373 return BAD_VALUE;
374 }
Wei Jia53692fa2017-12-11 10:33:46 -0800375
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800376 Mutex::Autolock _l(mLock);
377 *srcId = mSrcId;
378 return OK;
379}
380
Wei Jiaec044b02018-02-19 12:41:23 -0800381status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jiac2636032018-02-01 09:15:25 -0800382 if (dsd == NULL) {
383 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800384 }
Wei Jiaf01e3122018-10-18 11:49:44 -0700385 // Microsecond is used in NuPlayer2.
Wei Jiae31ac8a2018-10-25 11:06:21 -0700386 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
387 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700388 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
389 }
Wei Jiae31ac8a2018-10-25 11:06:21 -0700390 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
391 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
Wei Jiaf01e3122018-10-18 11:49:44 -0700392 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
393 }
Wei Jiaec044b02018-02-19 12:41:23 -0800394 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
395
396 sp<MediaPlayer2Interface> oldPlayer;
397
398 Mutex::Autolock _l(mLock);
399 {
400 if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
401 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
402 ALOGE("setDataSource called in wrong state %d", mCurrentState);
403 return INVALID_OPERATION;
404 }
405
406 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
407 status_t err = player->initCheck();
408 if (err != NO_ERROR) {
409 ALOGE("Failed to create player object, initCheck failed(%d)", err);
410 return err;
411 }
412
413 clear_l();
414
Dichen Zhangf8726912018-10-17 13:31:26 -0700415 if (mAudioOutput != NULL) {
416 mAudioOutput->copyAudioDeviceCallback(mRoutingDelegates);
417 }
418
Wei Jiaec044b02018-02-19 12:41:23 -0800419 player->setListener(new proxyListener(this));
420 mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid,
Dichen Zhangf8726912018-10-17 13:31:26 -0700421 mPid, mAudioAttributes, mRoutingDelegates);
Wei Jiaec044b02018-02-19 12:41:23 -0800422 player->setAudioSink(mAudioOutput);
423
424 err = player->setDataSource(dsd);
425 if (err != OK) {
426 ALOGE("setDataSource error: %d", err);
427 return err;
428 }
429
430 sp<MediaPlayer2Interface> oldPlayer = mPlayer;
431 mPlayer = player;
432 mSrcId = dsd->mId;
433 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
Wei Jia53692fa2017-12-11 10:33:46 -0800434 }
Wei Jiaec044b02018-02-19 12:41:23 -0800435
436 if (oldPlayer != NULL) {
437 oldPlayer->setListener(NULL);
438 oldPlayer->reset();
439 }
440
441 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800442}
443
Wei Jia57aeffd2018-02-15 16:01:14 -0800444status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
445 if (dsd == NULL) {
446 return BAD_VALUE;
447 }
448 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
449
450 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800451 if (mPlayer == NULL) {
452 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
453 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800454 }
Wei Jiaec044b02018-02-19 12:41:23 -0800455 return mPlayer->prepareNextDataSource(dsd);
Wei Jia57aeffd2018-02-15 16:01:14 -0800456}
457
458status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
459 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
460
461 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800462 if (mPlayer == NULL) {
463 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
464 return INVALID_OPERATION;
Wei Jia57aeffd2018-02-15 16:01:14 -0800465 }
Wei Jiaec044b02018-02-19 12:41:23 -0800466 mSrcId = srcId;
467 return mPlayer->playNextDataSource(srcId);
Wei Jia57aeffd2018-02-15 16:01:14 -0800468}
469
Dongwon Kang9f631982018-07-10 12:34:41 -0700470status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -0800471 Mutex::Autolock _l(mLock);
472 const bool hasBeenInitialized =
473 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
474 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
Wei Jiaec044b02018-02-19 12:41:23 -0800475 if ((mPlayer == NULL) || !hasBeenInitialized) {
Dongwon Kang9f631982018-07-10 12:34:41 -0700476 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
Wei Jiaec044b02018-02-19 12:41:23 -0800477 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800478 }
Wei Jiaec044b02018-02-19 12:41:23 -0800479 return mPlayer->invoke(request, reply);
Wei Jia53692fa2017-12-11 10:33:46 -0800480}
481
Wei Jiaec044b02018-02-19 12:41:23 -0800482void MediaPlayer2::disconnectNativeWindow_l() {
483 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
484 status_t err = native_window_api_disconnect(
485 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
486
487 if (err != OK) {
488 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
489 strerror(-err), err);
490 }
491 }
492 mConnectedWindow.clear();
493}
494
495status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
496 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
497 ALOGV("setVideoSurfaceTexture(%p)", anw);
498 Mutex::Autolock _l(mLock);
499 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800500 return NO_INIT;
501 }
Wei Jiaec044b02018-02-19 12:41:23 -0800502
503 if (anw != NULL) {
504 if (mConnectedWindow != NULL
505 && mConnectedWindow->getANativeWindow() == anw) {
506 return OK;
507 }
508 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
509
510 if (err != OK) {
511 ALOGE("setVideoSurfaceTexture failed: %d", err);
512 // Note that we must do the reset before disconnecting from the ANW.
513 // Otherwise queue/dequeue calls could be made on the disconnected
514 // ANW, which may result in errors.
515 mPlayer->reset();
516 disconnectNativeWindow_l();
517 return err;
518 }
519 }
520
521 // Note that we must set the player's new GraphicBufferProducer before
522 // disconnecting the old one. Otherwise queue/dequeue calls could be made
523 // on the disconnected ANW, which may result in errors.
524 status_t err = mPlayer->setVideoSurfaceTexture(nww);
525
526 disconnectNativeWindow_l();
527
528 if (err == OK) {
529 mConnectedWindow = nww;
530 mLock.unlock();
531 } else if (anw != NULL) {
532 mLock.unlock();
533 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
534
535 if (err != OK) {
536 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
537 strerror(-err), err);
538 }
539 }
540
541 return err;
Wei Jia53692fa2017-12-11 10:33:46 -0800542}
543
Wei Jiaec044b02018-02-19 12:41:23 -0800544status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800545 ALOGV("getBufferingSettings");
546
547 Mutex::Autolock _l(mLock);
548 if (mPlayer == 0) {
549 return NO_INIT;
550 }
Wei Jiaec044b02018-02-19 12:41:23 -0800551
552 status_t ret = mPlayer->getBufferingSettings(buffering);
553 if (ret == NO_ERROR) {
554 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
555 } else {
556 ALOGE("getBufferingSettings returned %d", ret);
557 }
558 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800559}
560
Wei Jiaec044b02018-02-19 12:41:23 -0800561status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
562 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Wei Jia53692fa2017-12-11 10:33:46 -0800563
564 Mutex::Autolock _l(mLock);
565 if (mPlayer == 0) {
566 return NO_INIT;
567 }
568 return mPlayer->setBufferingSettings(buffering);
569}
570
Wei Jiaec044b02018-02-19 12:41:23 -0800571status_t MediaPlayer2::setAudioAttributes_l(const Parcel &parcel) {
572 if (mAudioAttributes != NULL) {
573 free(mAudioAttributes);
574 }
575 mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
576 if (mAudioAttributes == NULL) {
577 return NO_MEMORY;
578 }
579 unmarshallAudioAttributes(parcel, mAudioAttributes);
580
581 ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
582 mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
583 mAudioAttributes->tags);
584
585 if (mAudioOutput != 0) {
586 mAudioOutput->setAudioAttributes(mAudioAttributes);
587 }
588 return NO_ERROR;
589}
590
591status_t MediaPlayer2::prepareAsync() {
592 ALOGV("prepareAsync");
593 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700594 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800595 if (mAudioAttributesParcel != NULL) {
Wei Jiaec044b02018-02-19 12:41:23 -0800596 status_t err = setAudioAttributes_l(*mAudioAttributesParcel);
597 if (err != OK) {
598 return err;
599 }
Wei Jia53692fa2017-12-11 10:33:46 -0800600 }
601 mCurrentState = MEDIA_PLAYER2_PREPARING;
602 return mPlayer->prepareAsync();
603 }
604 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
605 return INVALID_OPERATION;
606}
607
Wei Jiaec044b02018-02-19 12:41:23 -0800608status_t MediaPlayer2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800609 ALOGV("start");
610
611 status_t ret = NO_ERROR;
612 Mutex::Autolock _l(mLock);
613
614 mLockThreadId = getThreadId();
615
616 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
617 ret = NO_ERROR;
618 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
619 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
620 mPlayer->setLooping(mLoop);
Wei Jiaec044b02018-02-19 12:41:23 -0800621
622 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700623 mAudioOutput->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800624 }
625
626 if (mAudioOutput != 0) {
627 mAudioOutput->setAuxEffectSendLevel(mSendLevel);
628 }
Wei Jia53692fa2017-12-11 10:33:46 -0800629 mCurrentState = MEDIA_PLAYER2_STARTED;
630 ret = mPlayer->start();
631 if (ret != NO_ERROR) {
632 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
633 } else {
634 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
635 ALOGV("playback completed immediately following start()");
636 }
637 }
638 } else {
639 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
640 ret = INVALID_OPERATION;
641 }
642
643 mLockThreadId = 0;
644
645 return ret;
646}
647
Wei Jiaec044b02018-02-19 12:41:23 -0800648status_t MediaPlayer2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800649 ALOGV("pause");
650 Mutex::Autolock _l(mLock);
651 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
652 return NO_ERROR;
Wei Jia6376cd52018-09-26 11:42:55 -0700653 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
Wei Jia53692fa2017-12-11 10:33:46 -0800654 status_t ret = mPlayer->pause();
655 if (ret != NO_ERROR) {
656 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
657 } else {
658 mCurrentState = MEDIA_PLAYER2_PAUSED;
659 }
660 return ret;
661 }
662 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
663 return INVALID_OPERATION;
664}
665
Wei Jiaec044b02018-02-19 12:41:23 -0800666bool MediaPlayer2::isPlaying() {
Wei Jia53692fa2017-12-11 10:33:46 -0800667 Mutex::Autolock _l(mLock);
668 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800669 bool temp = mPlayer->isPlaying();
Wei Jia53692fa2017-12-11 10:33:46 -0800670 ALOGV("isPlaying: %d", temp);
671 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
672 ALOGE("internal/external state mismatch corrected");
673 mCurrentState = MEDIA_PLAYER2_PAUSED;
674 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
675 ALOGE("internal/external state mismatch corrected");
676 mCurrentState = MEDIA_PLAYER2_STARTED;
677 }
678 return temp;
679 }
680 ALOGV("isPlaying: no active player");
681 return false;
682}
683
Wei Jia1f043e42018-06-20 16:52:50 -0700684mediaplayer2_states MediaPlayer2::getState() {
Wei Jia98787a72018-03-02 14:33:06 -0800685 Mutex::Autolock _l(mLock);
686 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
687 return MEDIAPLAYER2_STATE_ERROR;
688 }
689 if (mPlayer == 0
690 || (mCurrentState &
691 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
692 return MEDIAPLAYER2_STATE_IDLE;
693 }
694 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
695 return MEDIAPLAYER2_STATE_PLAYING;
696 }
Wei Jia0151ef42018-08-24 16:40:21 -0700697 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
Wei Jia98787a72018-03-02 14:33:06 -0800698 return MEDIAPLAYER2_STATE_PAUSED;
699 }
700 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
701 return MEDIAPLAYER2_STATE_PREPARED;
702}
703
Wei Jiaec044b02018-02-19 12:41:23 -0800704status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
Wei Jia53692fa2017-12-11 10:33:46 -0800705 ALOGV("setPlaybackSettings: %f %f %d %d",
706 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
707 // Negative speed and pitch does not make sense. Further validation will
708 // be done by the respective mediaplayers.
Wei Jiaec044b02018-02-19 12:41:23 -0800709 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
Wei Jia53692fa2017-12-11 10:33:46 -0800710 return BAD_VALUE;
711 }
712 Mutex::Autolock _l(mLock);
Wei Jia0151ef42018-08-24 16:40:21 -0700713 if (mPlayer == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800714 return INVALID_OPERATION;
715 }
716
Wei Jia53692fa2017-12-11 10:33:46 -0800717 status_t err = mPlayer->setPlaybackSettings(rate);
Wei Jia53692fa2017-12-11 10:33:46 -0800718 return err;
719}
720
Wei Jiaec044b02018-02-19 12:41:23 -0800721status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800722 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800723 if (mPlayer == 0) {
724 return INVALID_OPERATION;
725 }
Wei Jiaec044b02018-02-19 12:41:23 -0800726 status_t ret = mPlayer->getPlaybackSettings(rate);
727 if (ret == NO_ERROR) {
728 ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
729 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
730 } else {
731 ALOGV("getPlaybackSettings returned %d", ret);
732 }
733 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800734}
735
Wei Jiaec044b02018-02-19 12:41:23 -0800736status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
Wei Jia53692fa2017-12-11 10:33:46 -0800737 ALOGV("setSyncSettings: %u %u %f %f",
738 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
739 Mutex::Autolock _l(mLock);
740 if (mPlayer == 0) return INVALID_OPERATION;
741 return mPlayer->setSyncSettings(sync, videoFpsHint);
742}
743
744status_t MediaPlayer2::getSyncSettings(
Wei Jiaec044b02018-02-19 12:41:23 -0800745 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800746 Mutex::Autolock _l(mLock);
Wei Jia334adf02018-03-23 14:08:23 -0700747 if (mPlayer == 0) {
748 return INVALID_OPERATION;
749 }
Wei Jiaec044b02018-02-19 12:41:23 -0800750 status_t ret = mPlayer->getSyncSettings(sync, videoFps);
751 if (ret == NO_ERROR) {
752 ALOGV("getSyncSettings(%u, %u, %f, %f)",
753 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
754 } else {
755 ALOGV("getSyncSettings returned %d", ret);
756 }
757 return ret;
758
Wei Jia53692fa2017-12-11 10:33:46 -0800759}
760
Wei Jiaec044b02018-02-19 12:41:23 -0800761status_t MediaPlayer2::getVideoWidth(int *w) {
Wei Jia53692fa2017-12-11 10:33:46 -0800762 ALOGV("getVideoWidth");
763 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800764 if (mPlayer == 0) {
765 return INVALID_OPERATION;
766 }
Wei Jia53692fa2017-12-11 10:33:46 -0800767 *w = mVideoWidth;
768 return NO_ERROR;
769}
770
Wei Jiaec044b02018-02-19 12:41:23 -0800771status_t MediaPlayer2::getVideoHeight(int *h) {
Wei Jia53692fa2017-12-11 10:33:46 -0800772 ALOGV("getVideoHeight");
773 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800774 if (mPlayer == 0) {
775 return INVALID_OPERATION;
776 }
Wei Jia53692fa2017-12-11 10:33:46 -0800777 *h = mVideoHeight;
778 return NO_ERROR;
779}
780
Wei Jia800fe372018-02-20 15:00:45 -0800781status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800782 ALOGV("getCurrentPosition");
783 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -0800784 if (mPlayer == 0) {
785 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800786 }
Wei Jiaec044b02018-02-19 12:41:23 -0800787 if (mCurrentPosition >= 0) {
Wei Jia800fe372018-02-20 15:00:45 -0800788 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
Wei Jiaec044b02018-02-19 12:41:23 -0800789 *msec = mCurrentPosition;
790 return NO_ERROR;
791 }
792 status_t ret = mPlayer->getCurrentPosition(msec);
793 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800794 ALOGV("getCurrentPosition = %lld", (long long)*msec);
Wei Jiaec044b02018-02-19 12:41:23 -0800795 } else {
796 ALOGE("getCurrentPosition returned %d", ret);
797 }
798 return ret;
Wei Jia53692fa2017-12-11 10:33:46 -0800799}
800
Wei Jia800fe372018-02-20 15:00:45 -0800801status_t MediaPlayer2::getDuration(int64_t *msec) {
Wei Jiaec044b02018-02-19 12:41:23 -0800802 Mutex::Autolock _l(mLock);
Wei Jia53692fa2017-12-11 10:33:46 -0800803 ALOGV("getDuration_l");
804 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
Wei Jia0151ef42018-08-24 16:40:21 -0700805 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
Wei Jiaec044b02018-02-19 12:41:23 -0800806 if (mPlayer == 0 || !isValidState) {
807 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
808 mPlayer.get(), mCurrentState);
809 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800810 }
Wei Jia800fe372018-02-20 15:00:45 -0800811 int64_t durationMs;
Wei Jiaec044b02018-02-19 12:41:23 -0800812 status_t ret = mPlayer->getDuration(&durationMs);
813
814 if (ret == NO_ERROR) {
Wei Jia800fe372018-02-20 15:00:45 -0800815 ALOGV("getDuration = %lld", (long long)durationMs);
Wei Jiaec044b02018-02-19 12:41:23 -0800816 } else {
817 ALOGE("getDuration returned %d", ret);
818 // Do not enter error state just because no duration was available.
819 durationMs = -1;
820 }
821
822 if (msec) {
823 *msec = durationMs;
824 }
825 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800826}
827
Wei Jia800fe372018-02-20 15:00:45 -0800828status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
829 ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
830 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
831 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
832 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
833 mPlayer.get(), mCurrentState);
834 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800835 }
Wei Jia800fe372018-02-20 15:00:45 -0800836 if (msec < 0) {
837 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
838 msec = 0;
839 }
840
841 int64_t durationMs;
842 status_t err = mPlayer->getDuration(&durationMs);
843
844 if (err != OK) {
845 ALOGW("Stream has no duration and is therefore not seekable.");
846 return err;
847 }
848
849 if (msec > durationMs) {
850 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
851 (long long)msec, (long long)durationMs);
852
853 msec = durationMs;
854 }
855
856 // cache duration
857 mCurrentPosition = msec;
858 mCurrentSeekMode = mode;
859 if (mSeekPosition < 0) {
860 mSeekPosition = msec;
861 mSeekMode = mode;
862 return mPlayer->seekTo(msec, mode);
863 }
864 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
865 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800866}
867
Wei Jia800fe372018-02-20 15:00:45 -0800868status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -0800869 mLockThreadId = getThreadId();
870 Mutex::Autolock _l(mLock);
871 status_t result = seekTo_l(msec, mode);
872 mLockThreadId = 0;
873
874 return result;
875}
876
Wei Jiaec044b02018-02-19 12:41:23 -0800877status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800878 Mutex::Autolock _l(mLock);
879 if (mPlayer != 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800880 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -0800881 }
Wei Jiaec044b02018-02-19 12:41:23 -0800882
883 return mPlayer->notifyAt(mediaTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800884}
885
Wei Jiaec044b02018-02-19 12:41:23 -0800886status_t MediaPlayer2::reset_l() {
Wei Jia53692fa2017-12-11 10:33:46 -0800887 mLoop = false;
Wei Jiaec044b02018-02-19 12:41:23 -0800888 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
889 return NO_ERROR;
890 }
Wei Jia53692fa2017-12-11 10:33:46 -0800891 if (mPlayer != 0) {
892 status_t ret = mPlayer->reset();
893 if (ret != NO_ERROR) {
894 ALOGE("reset() failed with return code (%d)", ret);
895 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
896 } else {
Wei Jiaec044b02018-02-19 12:41:23 -0800897 mPlayer->setListener(NULL);
Wei Jia53692fa2017-12-11 10:33:46 -0800898 mCurrentState = MEDIA_PLAYER2_IDLE;
899 }
900 // setDataSource has to be called again to create a
901 // new mediaplayer.
902 mPlayer = 0;
903 return ret;
904 }
905 clear_l();
906 return NO_ERROR;
907}
908
Wei Jiaec044b02018-02-19 12:41:23 -0800909status_t MediaPlayer2::reset() {
Wei Jia53692fa2017-12-11 10:33:46 -0800910 ALOGV("reset");
911 mLockThreadId = getThreadId();
912 Mutex::Autolock _l(mLock);
913 status_t result = reset_l();
914 mLockThreadId = 0;
915
916 return result;
917}
918
Wei Jiaec044b02018-02-19 12:41:23 -0800919status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800920 ALOGV("MediaPlayer2::setAudioStreamType");
921 Mutex::Autolock _l(mLock);
922 if (mStreamType == type) return NO_ERROR;
923 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
924 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
925 // Can't change the stream type after prepare
926 ALOGE("setAudioStream called in state %d", mCurrentState);
927 return INVALID_OPERATION;
928 }
929 // cache
930 mStreamType = type;
931 return OK;
932}
933
Wei Jiaec044b02018-02-19 12:41:23 -0800934status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
Wei Jia53692fa2017-12-11 10:33:46 -0800935 ALOGV("getAudioStreamType");
936 Mutex::Autolock _l(mLock);
937 *type = mStreamType;
938 return OK;
939}
940
Wei Jiaec044b02018-02-19 12:41:23 -0800941status_t MediaPlayer2::setLooping(int loop) {
Wei Jia53692fa2017-12-11 10:33:46 -0800942 ALOGV("MediaPlayer2::setLooping");
943 Mutex::Autolock _l(mLock);
944 mLoop = (loop != 0);
945 if (mPlayer != 0) {
946 return mPlayer->setLooping(loop);
947 }
948 return OK;
949}
950
951bool MediaPlayer2::isLooping() {
952 ALOGV("isLooping");
953 Mutex::Autolock _l(mLock);
954 if (mPlayer != 0) {
955 return mLoop;
956 }
957 ALOGV("isLooping: no active player");
958 return false;
959}
960
Dichen Zhang7398ca02018-10-15 10:25:12 -0700961status_t MediaPlayer2::setVolume(float volume) {
962 ALOGV("MediaPlayer2::setVolume(%f)", volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800963 Mutex::Autolock _l(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700964 mVolume = volume;
Wei Jiaec044b02018-02-19 12:41:23 -0800965 if (mAudioOutput != 0) {
Dichen Zhang7398ca02018-10-15 10:25:12 -0700966 mAudioOutput->setVolume(volume);
Wei Jia53692fa2017-12-11 10:33:46 -0800967 }
968 return OK;
969}
970
Wei Jiaec044b02018-02-19 12:41:23 -0800971status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800972 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
973 Mutex::Autolock _l(mLock);
974 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
975 ALOGE("setAudioSessionId called in state %d", mCurrentState);
976 return INVALID_OPERATION;
977 }
978 if (sessionId < 0) {
979 return BAD_VALUE;
980 }
981 if (sessionId != mAudioSessionId) {
982 AudioSystem::acquireAudioSessionId(sessionId, -1);
983 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
984 mAudioSessionId = sessionId;
985 }
986 return NO_ERROR;
987}
988
Wei Jiaec044b02018-02-19 12:41:23 -0800989audio_session_t MediaPlayer2::getAudioSessionId() {
Wei Jia53692fa2017-12-11 10:33:46 -0800990 Mutex::Autolock _l(mLock);
991 return mAudioSessionId;
992}
993
Wei Jiaec044b02018-02-19 12:41:23 -0800994status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
Wei Jia53692fa2017-12-11 10:33:46 -0800995 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
996 Mutex::Autolock _l(mLock);
997 mSendLevel = level;
Wei Jiaec044b02018-02-19 12:41:23 -0800998 if (mAudioOutput != 0) {
999 return mAudioOutput->setAuxEffectSendLevel(level);
Wei Jia53692fa2017-12-11 10:33:46 -08001000 }
1001 return OK;
1002}
1003
Wei Jiaec044b02018-02-19 12:41:23 -08001004status_t MediaPlayer2::attachAuxEffect(int effectId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001005 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
1006 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001007 if (mAudioOutput == 0 ||
Wei Jia53692fa2017-12-11 10:33:46 -08001008 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
1009 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
1010 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
1011 return INVALID_OPERATION;
1012 }
1013
Wei Jiaec044b02018-02-19 12:41:23 -08001014 return mAudioOutput->attachAuxEffect(effectId);
Wei Jia53692fa2017-12-11 10:33:46 -08001015}
1016
1017// always call with lock held
Wei Jiaec044b02018-02-19 12:41:23 -08001018status_t MediaPlayer2::checkStateForKeySet_l(int key) {
Wei Jia53692fa2017-12-11 10:33:46 -08001019 switch(key) {
1020 case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
1021 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
1022 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
1023 // Can't change the audio attributes after prepare
1024 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
1025 return INVALID_OPERATION;
1026 }
1027 break;
1028 default:
1029 // parameter doesn't require player state check
1030 break;
1031 }
1032 return OK;
1033}
1034
Wei Jiaec044b02018-02-19 12:41:23 -08001035status_t MediaPlayer2::setParameter(int key, const Parcel& request) {
Wei Jia53692fa2017-12-11 10:33:46 -08001036 ALOGV("MediaPlayer2::setParameter(%d)", key);
1037 status_t status = INVALID_OPERATION;
1038 Mutex::Autolock _l(mLock);
1039 if (checkStateForKeySet_l(key) != OK) {
1040 return status;
1041 }
1042 switch (key) {
1043 case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
1044 // save the marshalled audio attributes
Wei Jiaec044b02018-02-19 12:41:23 -08001045 if (mAudioAttributesParcel != NULL) {
1046 delete mAudioAttributesParcel;
1047 }
Wei Jia53692fa2017-12-11 10:33:46 -08001048 mAudioAttributesParcel = new Parcel();
1049 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
Wei Jiaec044b02018-02-19 12:41:23 -08001050 status = setAudioAttributes_l(request);
1051 if (status != OK) {
1052 return status;
1053 }
Wei Jia53692fa2017-12-11 10:33:46 -08001054 break;
1055 default:
1056 ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
1057 break;
1058 }
1059
1060 if (mPlayer != NULL) {
1061 status = mPlayer->setParameter(key, request);
1062 }
1063 return status;
1064}
1065
Wei Jiaec044b02018-02-19 12:41:23 -08001066status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
Wei Jia53692fa2017-12-11 10:33:46 -08001067 ALOGV("MediaPlayer2::getParameter(%d)", key);
1068 Mutex::Autolock _l(mLock);
Wei Jia800fe372018-02-20 15:00:45 -08001069 if (key == MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES) {
1070 if (reply == NULL) {
1071 return BAD_VALUE;
1072 }
1073 if (mAudioAttributesParcel != NULL) {
1074 reply->appendFrom(mAudioAttributesParcel, 0, mAudioAttributesParcel->dataSize());
1075 }
1076 return OK;
1077 }
1078
Wei Jiaec044b02018-02-19 12:41:23 -08001079 if (mPlayer == NULL) {
1080 ALOGV("getParameter: no active player");
1081 return INVALID_OPERATION;
Wei Jia53692fa2017-12-11 10:33:46 -08001082 }
Wei Jiaec044b02018-02-19 12:41:23 -08001083
1084 status_t status = mPlayer->getParameter(key, reply);
1085 if (status != OK) {
1086 ALOGD("getParameter returns %d", status);
1087 }
1088 return status;
Wei Jia53692fa2017-12-11 10:33:46 -08001089}
1090
Dongwon Kang41929fb2018-09-09 08:29:56 -07001091void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001092 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
1093 (long long)srcId, msg, ext1, ext2);
Wei Jiaec044b02018-02-19 12:41:23 -08001094
Wei Jia53692fa2017-12-11 10:33:46 -08001095 bool send = true;
1096 bool locked = false;
1097
1098 // TODO: In the future, we might be on the same thread if the app is
1099 // running in the same process as the media server. In that case,
1100 // this will deadlock.
1101 //
1102 // The threadId hack below works around this for the care of prepare,
1103 // seekTo, start, and reset within the same process.
1104 // FIXME: Remember, this is a hack, it's not even a hack that is applied
1105 // consistently for all use-cases, this needs to be revisited.
1106 if (mLockThreadId != getThreadId()) {
1107 mLock.lock();
1108 locked = true;
1109 }
1110
1111 // Allows calls from JNI in idle state to notify errors
1112 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001113 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
1114 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -08001115 if (locked) mLock.unlock(); // release the lock when done.
1116 return;
1117 }
1118
1119 switch (msg) {
1120 case MEDIA2_NOP: // interface test message
1121 break;
1122 case MEDIA2_PREPARED:
1123 ALOGV("MediaPlayer2::notify() prepared");
1124 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -08001125 break;
1126 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001127 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
1128 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001129 break;
1130 case MEDIA2_PLAYBACK_COMPLETE:
1131 ALOGV("playback complete");
1132 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
1133 ALOGE("playback complete in idle state");
1134 }
1135 if (!mLoop) {
1136 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
1137 }
1138 break;
1139 case MEDIA2_ERROR:
1140 // Always log errors.
1141 // ext1: Media framework error code.
1142 // ext2: Implementation dependant error code.
1143 ALOGE("error (%d, %d)", ext1, ext2);
1144 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001145 break;
1146 case MEDIA2_INFO:
1147 // ext1: Media framework error code.
1148 // ext2: Implementation dependant error code.
1149 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
1150 ALOGW("info/warning (%d, %d)", ext1, ext2);
1151 }
1152 break;
1153 case MEDIA2_SEEK_COMPLETE:
1154 ALOGV("Received seek complete");
1155 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
Wei Jia800fe372018-02-20 15:00:45 -08001156 ALOGV("Executing queued seekTo(%lld, %d)",
1157 (long long)mCurrentPosition, mCurrentSeekMode);
Wei Jia53692fa2017-12-11 10:33:46 -08001158 mSeekPosition = -1;
1159 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1160 seekTo_l(mCurrentPosition, mCurrentSeekMode);
1161 }
1162 else {
1163 ALOGV("All seeks complete - return to regularly scheduled program");
1164 mCurrentPosition = mSeekPosition = -1;
1165 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
1166 }
1167 break;
1168 case MEDIA2_BUFFERING_UPDATE:
1169 ALOGV("buffering %d", ext1);
1170 break;
1171 case MEDIA2_SET_VIDEO_SIZE:
1172 ALOGV("New video size %d x %d", ext1, ext2);
1173 mVideoWidth = ext1;
1174 mVideoHeight = ext2;
1175 break;
1176 case MEDIA2_NOTIFY_TIME:
1177 ALOGV("Received notify time message");
1178 break;
1179 case MEDIA2_TIMED_TEXT:
1180 ALOGV("Received timed text message");
1181 break;
1182 case MEDIA2_SUBTITLE_DATA:
1183 ALOGV("Received subtitle data message");
1184 break;
1185 case MEDIA2_META_DATA:
1186 ALOGV("Received timed metadata message");
1187 break;
1188 default:
1189 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
1190 break;
1191 }
1192
1193 sp<MediaPlayer2Listener> listener = mListener;
1194 if (locked) mLock.unlock();
1195
1196 // this prevents re-entrant calls into client code
1197 if ((listener != 0) && send) {
1198 Mutex::Autolock _l(mNotifyLock);
1199 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001200 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -08001201 ALOGV("back from callback");
1202 }
1203}
1204
Wei Jia53692fa2017-12-11 10:33:46 -08001205// Modular DRM
Wei Jiaec044b02018-02-19 12:41:23 -08001206status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001207 // TODO change to ALOGV
1208 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
1209 drmSessionId.array(), drmSessionId.size());
1210 Mutex::Autolock _l(mLock);
1211 if (mPlayer == NULL) {
1212 return NO_INIT;
1213 }
1214
1215 // Only allowed it in player's preparing/prepared state.
1216 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
1217 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
1218 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
1219 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
1220 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
1221 return INVALID_OPERATION;
1222 }
1223
1224 if (drmSessionId.isEmpty()) {
1225 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
1226 return INVALID_OPERATION;
1227 }
1228
1229 // Passing down to mediaserver mainly for creating the crypto
1230 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
1231 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
1232
1233 // TODO change to ALOGV
1234 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
1235
1236 return status;
1237}
1238
Wei Jiaec044b02018-02-19 12:41:23 -08001239status_t MediaPlayer2::releaseDrm() {
Wei Jia53692fa2017-12-11 10:33:46 -08001240 Mutex::Autolock _l(mLock);
1241 if (mPlayer == NULL) {
1242 return NO_INIT;
1243 }
1244
1245 // Not allowing releaseDrm in an active/resumable state
1246 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
1247 MEDIA_PLAYER2_PAUSED |
1248 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
1249 MEDIA_PLAYER2_STATE_ERROR)) {
1250 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
1251 return INVALID_OPERATION;
1252 }
1253
1254 status_t status = mPlayer->releaseDrm();
1255 // TODO change to ALOGV
1256 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
1257 if (status != OK) {
1258 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
1259 // Overriding to OK so the client proceed with its own cleanup
1260 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
1261 status = OK;
1262 }
1263
1264 return status;
1265}
1266
Wei Jiaec044b02018-02-19 12:41:23 -08001267status_t MediaPlayer2::setOutputDevice(audio_port_handle_t deviceId) {
Wei Jia53692fa2017-12-11 10:33:46 -08001268 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001269 if (mAudioOutput == NULL) {
1270 ALOGV("setOutputDevice: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001271 return NO_INIT;
1272 }
Wei Jiaec044b02018-02-19 12:41:23 -08001273 return mAudioOutput->setOutputDevice(deviceId);
Wei Jia53692fa2017-12-11 10:33:46 -08001274}
1275
Wei Jiaec044b02018-02-19 12:41:23 -08001276audio_port_handle_t MediaPlayer2::getRoutedDeviceId() {
Wei Jia53692fa2017-12-11 10:33:46 -08001277 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001278 if (mAudioOutput == NULL) {
1279 ALOGV("getRoutedDeviceId: audio sink not init");
Wei Jia53692fa2017-12-11 10:33:46 -08001280 return AUDIO_PORT_HANDLE_NONE;
1281 }
1282 audio_port_handle_t deviceId;
Wei Jiaec044b02018-02-19 12:41:23 -08001283 status_t status = mAudioOutput->getRoutedDeviceId(&deviceId);
Wei Jia53692fa2017-12-11 10:33:46 -08001284 if (status != NO_ERROR) {
1285 return AUDIO_PORT_HANDLE_NONE;
1286 }
1287 return deviceId;
1288}
1289
Dichen Zhangf8726912018-10-17 13:31:26 -07001290status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
1291 Mutex::Autolock _l(mLock);
1292 if (mAudioOutput == NULL) {
1293 ALOGV("addAudioDeviceCallback: player not init");
1294 mRoutingDelegates.push_back(routingDelegate);
1295 return NO_INIT;
1296 }
1297 return mAudioOutput->addAudioDeviceCallback(routingDelegate);
1298}
1299
1300status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
Wei Jia53692fa2017-12-11 10:33:46 -08001301 Mutex::Autolock _l(mLock);
Wei Jiaec044b02018-02-19 12:41:23 -08001302 if (mAudioOutput == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001303 ALOGV("addAudioDeviceCallback: player not init");
1304 return NO_INIT;
1305 }
Dichen Zhangf8726912018-10-17 13:31:26 -07001306 return mAudioOutput->removeAudioDeviceCallback(listener);
Wei Jiaec044b02018-02-19 12:41:23 -08001307}
1308
1309status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
1310 const size_t SIZE = 256;
1311 char buffer[SIZE];
1312 String8 result;
1313 result.append(" MediaPlayer2\n");
1314 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
1315 result.append(buffer);
1316
1317 sp<MediaPlayer2Interface> player;
1318 sp<MediaPlayer2AudioOutput> audioOutput;
1319 bool locked = false;
1320 for (int i = 0; i < kDumpLockRetries; ++i) {
1321 if (mLock.tryLock() == NO_ERROR) {
1322 locked = true;
1323 break;
1324 }
1325 usleep(kDumpLockSleepUs);
1326 }
1327
1328 if (locked) {
1329 player = mPlayer;
1330 audioOutput = mAudioOutput;
1331 mLock.unlock();
1332 } else {
1333 result.append(" lock is taken, no dump from player and audio output\n");
1334 }
1335 write(fd, result.string(), result.size());
1336
1337 if (player != NULL) {
1338 player->dump(fd, args);
1339 }
1340 if (audioOutput != 0) {
1341 audioOutput->dump(fd, args);
1342 }
1343 write(fd, "\n", 1);
1344 return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -08001345}
1346
1347} // namespace android