xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "NuPlayerDriver"
19*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <android-base/macros.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDriver.h"
25*ec779b8eSAndroid Build Coastguard Worker 
26*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayer.h"
27*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerSource.h"
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker #include <audiomanager/AudioManager.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooper.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AUtils.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ByteUtils.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaClock.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
38*ec779b8eSAndroid Build Coastguard Worker 
39*ec779b8eSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_AUDIO
40*ec779b8eSAndroid Build Coastguard Worker #include <utils/Trace.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
42*ec779b8eSAndroid Build Coastguard Worker using ::android::base::StringPrintf;
43*ec779b8eSAndroid Build Coastguard Worker 
44*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockRetries = 50;
45*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockSleepUs = 20000;
46*ec779b8eSAndroid Build Coastguard Worker 
47*ec779b8eSAndroid Build Coastguard Worker namespace android {
48*ec779b8eSAndroid Build Coastguard Worker 
49*ec779b8eSAndroid Build Coastguard Worker // key for media statistics
50*ec779b8eSAndroid Build Coastguard Worker static const char *kKeyPlayer = "nuplayer";
51*ec779b8eSAndroid Build Coastguard Worker // attrs for media statistics
52*ec779b8eSAndroid Build Coastguard Worker     // NB: these are matched with public Java API constants defined
53*ec779b8eSAndroid Build Coastguard Worker     // in frameworks/base/media/java/android/media/MediaPlayer.java
54*ec779b8eSAndroid Build Coastguard Worker     // These must be kept synchronized with the constants there.
55*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
56*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
57*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerWidth = "android.media.mediaplayer.width";
58*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerHeight = "android.media.mediaplayer.height";
59*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFrames = "android.media.mediaplayer.frames";
60*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
61*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFrameRate = "android.media.mediaplayer.fps";
62*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
63*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
64*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
65*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
66*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerError = "android.media.mediaplayer.err";
67*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
68*ec779b8eSAndroid Build Coastguard Worker 
69*ec779b8eSAndroid Build Coastguard Worker     // NB: These are not yet exposed as public Java API constants.
70*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
71*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
72*ec779b8eSAndroid Build Coastguard Worker //
73*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
74*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
75*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
76*ec779b8eSAndroid Build Coastguard Worker 
77*ec779b8eSAndroid Build Coastguard Worker 
NuPlayerDriver(pid_t pid)78*ec779b8eSAndroid Build Coastguard Worker NuPlayerDriver::NuPlayerDriver(pid_t pid)
79*ec779b8eSAndroid Build Coastguard Worker     : mState(STATE_IDLE),
80*ec779b8eSAndroid Build Coastguard Worker       mIsAsyncPrepare(false),
81*ec779b8eSAndroid Build Coastguard Worker       mAsyncResult(UNKNOWN_ERROR),
82*ec779b8eSAndroid Build Coastguard Worker       mSetSurfaceInProgress(false),
83*ec779b8eSAndroid Build Coastguard Worker       mDurationUs(-1),
84*ec779b8eSAndroid Build Coastguard Worker       mPositionUs(-1),
85*ec779b8eSAndroid Build Coastguard Worker       mSeekInProgress(false),
86*ec779b8eSAndroid Build Coastguard Worker       mPlayingTimeUs(0),
87*ec779b8eSAndroid Build Coastguard Worker       mRebufferingTimeUs(0),
88*ec779b8eSAndroid Build Coastguard Worker       mRebufferingEvents(0),
89*ec779b8eSAndroid Build Coastguard Worker       mRebufferingAtExit(false),
90*ec779b8eSAndroid Build Coastguard Worker       mLooper(new ALooper),
91*ec779b8eSAndroid Build Coastguard Worker       mMediaClock(new MediaClock),
92*ec779b8eSAndroid Build Coastguard Worker       mPlayer(new NuPlayer(pid, mMediaClock)),
93*ec779b8eSAndroid Build Coastguard Worker       mPlayerFlags(0),
94*ec779b8eSAndroid Build Coastguard Worker       mCachedPlayerIId(PLAYER_PIID_INVALID),
95*ec779b8eSAndroid Build Coastguard Worker       mMetricsItem(NULL),
96*ec779b8eSAndroid Build Coastguard Worker       mClientUid(-1),
97*ec779b8eSAndroid Build Coastguard Worker       mAtEOS(false),
98*ec779b8eSAndroid Build Coastguard Worker       mLooping(false),
99*ec779b8eSAndroid Build Coastguard Worker       mAutoLoop(false) {
100*ec779b8eSAndroid Build Coastguard Worker     ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
101*ec779b8eSAndroid Build Coastguard Worker     mLooper->setName("NuPlayerDriver Looper");
102*ec779b8eSAndroid Build Coastguard Worker 
103*ec779b8eSAndroid Build Coastguard Worker     mMediaClock->init();
104*ec779b8eSAndroid Build Coastguard Worker 
105*ec779b8eSAndroid Build Coastguard Worker     // set up an analytics record
106*ec779b8eSAndroid Build Coastguard Worker     mMetricsItem = mediametrics::Item::create(kKeyPlayer);
107*ec779b8eSAndroid Build Coastguard Worker 
108*ec779b8eSAndroid Build Coastguard Worker     mLooper->start(
109*ec779b8eSAndroid Build Coastguard Worker             false, /* runOnCallingThread */
110*ec779b8eSAndroid Build Coastguard Worker             true,  /* canCallJava */
111*ec779b8eSAndroid Build Coastguard Worker             PRIORITY_AUDIO);
112*ec779b8eSAndroid Build Coastguard Worker 
113*ec779b8eSAndroid Build Coastguard Worker     mLooper->registerHandler(mPlayer);
114*ec779b8eSAndroid Build Coastguard Worker 
115*ec779b8eSAndroid Build Coastguard Worker     mPlayer->init(this);
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker 
~NuPlayerDriver()118*ec779b8eSAndroid Build Coastguard Worker NuPlayerDriver::~NuPlayerDriver() {
119*ec779b8eSAndroid Build Coastguard Worker     ALOGV("~NuPlayerDriver(%p)", this);
120*ec779b8eSAndroid Build Coastguard Worker     mLooper->stop();
121*ec779b8eSAndroid Build Coastguard Worker 
122*ec779b8eSAndroid Build Coastguard Worker     // finalize any pending metrics, usually a no-op.
123*ec779b8eSAndroid Build Coastguard Worker     updateMetrics("destructor");
124*ec779b8eSAndroid Build Coastguard Worker     logMetrics("destructor");
125*ec779b8eSAndroid Build Coastguard Worker 
126*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mMetricsLock);
127*ec779b8eSAndroid Build Coastguard Worker     if (mMetricsItem != NULL) {
128*ec779b8eSAndroid Build Coastguard Worker         delete mMetricsItem;
129*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem = NULL;
130*ec779b8eSAndroid Build Coastguard Worker     }
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker 
initCheck()133*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::initCheck() {
134*ec779b8eSAndroid Build Coastguard Worker     return OK;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
setUID(uid_t uid)137*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setUID(uid_t uid) {
138*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setUID(uid);
139*ec779b8eSAndroid Build Coastguard Worker     mClientUid = uid;
140*ec779b8eSAndroid Build Coastguard Worker 
141*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mMetricsLock);
142*ec779b8eSAndroid Build Coastguard Worker     if (mMetricsItem) {
143*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem->setUid(mClientUid);
144*ec779b8eSAndroid Build Coastguard Worker     }
145*ec779b8eSAndroid Build Coastguard Worker 
146*ec779b8eSAndroid Build Coastguard Worker     return OK;
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)149*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(
150*ec779b8eSAndroid Build Coastguard Worker         const sp<IMediaHTTPService> &httpService,
151*ec779b8eSAndroid Build Coastguard Worker         const char *url,
152*ec779b8eSAndroid Build Coastguard Worker         const KeyedVector<String8, String8> *headers) {
153*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
154*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("setDataSource(%p)", this).c_str());
155*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
156*ec779b8eSAndroid Build Coastguard Worker 
157*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_IDLE) {
158*ec779b8eSAndroid Build Coastguard Worker         ATRACE_END();
159*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
160*ec779b8eSAndroid Build Coastguard Worker     }
161*ec779b8eSAndroid Build Coastguard Worker 
162*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_SET_DATASOURCE_PENDING;
163*ec779b8eSAndroid Build Coastguard Worker 
164*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setDataSourceAsync(httpService, url, headers);
165*ec779b8eSAndroid Build Coastguard Worker 
166*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_SET_DATASOURCE_PENDING) {
167*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
168*ec779b8eSAndroid Build Coastguard Worker     }
169*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
170*ec779b8eSAndroid Build Coastguard Worker 
171*ec779b8eSAndroid Build Coastguard Worker     return mAsyncResult;
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(int fd,int64_t offset,int64_t length)174*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
175*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%p) file(%d)", this, fd);
176*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("setDataSource(%p) file(%d)", this, fd).c_str());
177*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
178*ec779b8eSAndroid Build Coastguard Worker 
179*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_IDLE) {
180*ec779b8eSAndroid Build Coastguard Worker         ATRACE_END();
181*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
182*ec779b8eSAndroid Build Coastguard Worker     }
183*ec779b8eSAndroid Build Coastguard Worker 
184*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_SET_DATASOURCE_PENDING;
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setDataSourceAsync(fd, offset, length);
187*ec779b8eSAndroid Build Coastguard Worker 
188*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_SET_DATASOURCE_PENDING) {
189*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
190*ec779b8eSAndroid Build Coastguard Worker     }
191*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
192*ec779b8eSAndroid Build Coastguard Worker 
193*ec779b8eSAndroid Build Coastguard Worker     return mAsyncResult;
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IStreamSource> & source)196*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
197*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%p) stream source", this);
198*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("setDataSource(%p) stream source", this).c_str());
199*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
200*ec779b8eSAndroid Build Coastguard Worker 
201*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_IDLE) {
202*ec779b8eSAndroid Build Coastguard Worker         ATRACE_END();
203*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
204*ec779b8eSAndroid Build Coastguard Worker     }
205*ec779b8eSAndroid Build Coastguard Worker 
206*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_SET_DATASOURCE_PENDING;
207*ec779b8eSAndroid Build Coastguard Worker 
208*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setDataSourceAsync(source);
209*ec779b8eSAndroid Build Coastguard Worker 
210*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_SET_DATASOURCE_PENDING) {
211*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
212*ec779b8eSAndroid Build Coastguard Worker     }
213*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
214*ec779b8eSAndroid Build Coastguard Worker 
215*ec779b8eSAndroid Build Coastguard Worker     return mAsyncResult;
216*ec779b8eSAndroid Build Coastguard Worker }
217*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<DataSource> & source)218*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) {
219*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%p) callback source", this);
220*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("setDataSource(%p) callback source", this).c_str());
221*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
222*ec779b8eSAndroid Build Coastguard Worker 
223*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_IDLE) {
224*ec779b8eSAndroid Build Coastguard Worker         ATRACE_END();
225*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
226*ec779b8eSAndroid Build Coastguard Worker     }
227*ec779b8eSAndroid Build Coastguard Worker 
228*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_SET_DATASOURCE_PENDING;
229*ec779b8eSAndroid Build Coastguard Worker 
230*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setDataSourceAsync(source);
231*ec779b8eSAndroid Build Coastguard Worker 
232*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_SET_DATASOURCE_PENDING) {
233*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
234*ec779b8eSAndroid Build Coastguard Worker     }
235*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
236*ec779b8eSAndroid Build Coastguard Worker 
237*ec779b8eSAndroid Build Coastguard Worker     return mAsyncResult;
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const String8 & rtpParams)240*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const String8& rtpParams) {
241*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%p) rtp source", this);
242*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("setDataSource(%p) rtp source", this).c_str());
243*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
244*ec779b8eSAndroid Build Coastguard Worker 
245*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_IDLE) {
246*ec779b8eSAndroid Build Coastguard Worker         ATRACE_END();
247*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
248*ec779b8eSAndroid Build Coastguard Worker     }
249*ec779b8eSAndroid Build Coastguard Worker 
250*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_SET_DATASOURCE_PENDING;
251*ec779b8eSAndroid Build Coastguard Worker 
252*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setDataSourceAsync(rtpParams);
253*ec779b8eSAndroid Build Coastguard Worker 
254*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_SET_DATASOURCE_PENDING) {
255*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
256*ec779b8eSAndroid Build Coastguard Worker     }
257*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker     return mAsyncResult;
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker 
262*ec779b8eSAndroid Build Coastguard Worker 
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)263*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setVideoSurfaceTexture(
264*ec779b8eSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer> &bufferProducer) {
265*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setVideoSurfaceTexture(%p)", this);
266*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
267*ec779b8eSAndroid Build Coastguard Worker 
268*ec779b8eSAndroid Build Coastguard Worker     if (mSetSurfaceInProgress) {
269*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
270*ec779b8eSAndroid Build Coastguard Worker     }
271*ec779b8eSAndroid Build Coastguard Worker 
272*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
273*ec779b8eSAndroid Build Coastguard Worker         case STATE_SET_DATASOURCE_PENDING:
274*ec779b8eSAndroid Build Coastguard Worker         case STATE_RESET_IN_PROGRESS:
275*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker         default:
278*ec779b8eSAndroid Build Coastguard Worker             break;
279*ec779b8eSAndroid Build Coastguard Worker     }
280*ec779b8eSAndroid Build Coastguard Worker 
281*ec779b8eSAndroid Build Coastguard Worker     mSetSurfaceInProgress = true;
282*ec779b8eSAndroid Build Coastguard Worker 
283*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
284*ec779b8eSAndroid Build Coastguard Worker 
285*ec779b8eSAndroid Build Coastguard Worker     while (mSetSurfaceInProgress) {
286*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
287*ec779b8eSAndroid Build Coastguard Worker     }
288*ec779b8eSAndroid Build Coastguard Worker 
289*ec779b8eSAndroid Build Coastguard Worker     return OK;
290*ec779b8eSAndroid Build Coastguard Worker }
291*ec779b8eSAndroid Build Coastguard Worker 
getBufferingSettings(BufferingSettings * buffering)292*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getBufferingSettings(BufferingSettings* buffering) {
293*ec779b8eSAndroid Build Coastguard Worker     ALOGV("getBufferingSettings(%p)", this);
294*ec779b8eSAndroid Build Coastguard Worker     {
295*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mLock);
296*ec779b8eSAndroid Build Coastguard Worker         if (mState == STATE_IDLE) {
297*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
298*ec779b8eSAndroid Build Coastguard Worker         }
299*ec779b8eSAndroid Build Coastguard Worker     }
300*ec779b8eSAndroid Build Coastguard Worker 
301*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->getBufferingSettings(buffering);
302*ec779b8eSAndroid Build Coastguard Worker }
303*ec779b8eSAndroid Build Coastguard Worker 
setBufferingSettings(const BufferingSettings & buffering)304*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setBufferingSettings(const BufferingSettings& buffering) {
305*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setBufferingSettings(%p)", this);
306*ec779b8eSAndroid Build Coastguard Worker     {
307*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mLock);
308*ec779b8eSAndroid Build Coastguard Worker         if (mState == STATE_IDLE) {
309*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
310*ec779b8eSAndroid Build Coastguard Worker         }
311*ec779b8eSAndroid Build Coastguard Worker     }
312*ec779b8eSAndroid Build Coastguard Worker 
313*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->setBufferingSettings(buffering);
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker 
prepare()316*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepare() {
317*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepare(%p)", this);
318*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("prepare(%p)", this).c_str());
319*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
320*ec779b8eSAndroid Build Coastguard Worker     status_t ret = prepare_l();
321*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
322*ec779b8eSAndroid Build Coastguard Worker     return ret;
323*ec779b8eSAndroid Build Coastguard Worker }
324*ec779b8eSAndroid Build Coastguard Worker 
prepare_l()325*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepare_l() {
326*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
327*ec779b8eSAndroid Build Coastguard Worker         case STATE_UNPREPARED:
328*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_PREPARING;
329*ec779b8eSAndroid Build Coastguard Worker 
330*ec779b8eSAndroid Build Coastguard Worker             // Make sure we're not posting any notifications, success or
331*ec779b8eSAndroid Build Coastguard Worker             // failure information is only communicated through our result
332*ec779b8eSAndroid Build Coastguard Worker             // code.
333*ec779b8eSAndroid Build Coastguard Worker             mIsAsyncPrepare = false;
334*ec779b8eSAndroid Build Coastguard Worker             mPlayer->prepareAsync();
335*ec779b8eSAndroid Build Coastguard Worker             while (mState == STATE_PREPARING) {
336*ec779b8eSAndroid Build Coastguard Worker                 mCondition.wait(mLock);
337*ec779b8eSAndroid Build Coastguard Worker             }
338*ec779b8eSAndroid Build Coastguard Worker             return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
339*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED:
340*ec779b8eSAndroid Build Coastguard Worker             // this is really just paused. handle as seek to start
341*ec779b8eSAndroid Build Coastguard Worker             mAtEOS = false;
342*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_STOPPED_AND_PREPARING;
343*ec779b8eSAndroid Build Coastguard Worker             mIsAsyncPrepare = false;
344*ec779b8eSAndroid Build Coastguard Worker             mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
345*ec779b8eSAndroid Build Coastguard Worker                     true /* needNotify */);
346*ec779b8eSAndroid Build Coastguard Worker             while (mState == STATE_STOPPED_AND_PREPARING) {
347*ec779b8eSAndroid Build Coastguard Worker                 mCondition.wait(mLock);
348*ec779b8eSAndroid Build Coastguard Worker             }
349*ec779b8eSAndroid Build Coastguard Worker             return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR;
350*ec779b8eSAndroid Build Coastguard Worker         default:
351*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
352*ec779b8eSAndroid Build Coastguard Worker     };
353*ec779b8eSAndroid Build Coastguard Worker }
354*ec779b8eSAndroid Build Coastguard Worker 
prepareAsync()355*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepareAsync() {
356*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareAsync(%p)", this);
357*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
358*ec779b8eSAndroid Build Coastguard Worker 
359*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
360*ec779b8eSAndroid Build Coastguard Worker         case STATE_UNPREPARED:
361*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_PREPARING;
362*ec779b8eSAndroid Build Coastguard Worker             mIsAsyncPrepare = true;
363*ec779b8eSAndroid Build Coastguard Worker             mPlayer->prepareAsync();
364*ec779b8eSAndroid Build Coastguard Worker             return OK;
365*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED:
366*ec779b8eSAndroid Build Coastguard Worker             // this is really just paused. handle as seek to start
367*ec779b8eSAndroid Build Coastguard Worker             mAtEOS = false;
368*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_STOPPED_AND_PREPARING;
369*ec779b8eSAndroid Build Coastguard Worker             mIsAsyncPrepare = true;
370*ec779b8eSAndroid Build Coastguard Worker             mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
371*ec779b8eSAndroid Build Coastguard Worker                     true /* needNotify */);
372*ec779b8eSAndroid Build Coastguard Worker             return OK;
373*ec779b8eSAndroid Build Coastguard Worker         default:
374*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
375*ec779b8eSAndroid Build Coastguard Worker     };
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker 
start()378*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::start() {
379*ec779b8eSAndroid Build Coastguard Worker     ALOGV("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
380*ec779b8eSAndroid Build Coastguard Worker     ATRACE_BEGIN(StringPrintf("start(%p), state is %d, eos is %d", this, mState, mAtEOS).c_str());
381*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
382*ec779b8eSAndroid Build Coastguard Worker     status_t ret = start_l();
383*ec779b8eSAndroid Build Coastguard Worker     ATRACE_END();
384*ec779b8eSAndroid Build Coastguard Worker     return ret;
385*ec779b8eSAndroid Build Coastguard Worker }
386*ec779b8eSAndroid Build Coastguard Worker 
start_l()387*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::start_l() {
388*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
389*ec779b8eSAndroid Build Coastguard Worker         case STATE_UNPREPARED:
390*ec779b8eSAndroid Build Coastguard Worker         {
391*ec779b8eSAndroid Build Coastguard Worker             status_t err = prepare_l();
392*ec779b8eSAndroid Build Coastguard Worker 
393*ec779b8eSAndroid Build Coastguard Worker             if (err != OK) {
394*ec779b8eSAndroid Build Coastguard Worker                 return err;
395*ec779b8eSAndroid Build Coastguard Worker             }
396*ec779b8eSAndroid Build Coastguard Worker 
397*ec779b8eSAndroid Build Coastguard Worker             CHECK_EQ(mState, STATE_PREPARED);
398*ec779b8eSAndroid Build Coastguard Worker 
399*ec779b8eSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
400*ec779b8eSAndroid Build Coastguard Worker         }
401*ec779b8eSAndroid Build Coastguard Worker 
402*ec779b8eSAndroid Build Coastguard Worker         case STATE_PAUSED:
403*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARED:
404*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARED:
405*ec779b8eSAndroid Build Coastguard Worker         {
406*ec779b8eSAndroid Build Coastguard Worker             mPlayer->start();
407*ec779b8eSAndroid Build Coastguard Worker 
408*ec779b8eSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
409*ec779b8eSAndroid Build Coastguard Worker         }
410*ec779b8eSAndroid Build Coastguard Worker 
411*ec779b8eSAndroid Build Coastguard Worker         case STATE_RUNNING:
412*ec779b8eSAndroid Build Coastguard Worker         {
413*ec779b8eSAndroid Build Coastguard Worker             if (mAtEOS) {
414*ec779b8eSAndroid Build Coastguard Worker                 mPlayer->seekToAsync(0);
415*ec779b8eSAndroid Build Coastguard Worker                 mAtEOS = false;
416*ec779b8eSAndroid Build Coastguard Worker                 mPositionUs = -1;
417*ec779b8eSAndroid Build Coastguard Worker             }
418*ec779b8eSAndroid Build Coastguard Worker             break;
419*ec779b8eSAndroid Build Coastguard Worker         }
420*ec779b8eSAndroid Build Coastguard Worker 
421*ec779b8eSAndroid Build Coastguard Worker         default:
422*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
423*ec779b8eSAndroid Build Coastguard Worker     }
424*ec779b8eSAndroid Build Coastguard Worker 
425*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_RUNNING;
426*ec779b8eSAndroid Build Coastguard Worker 
427*ec779b8eSAndroid Build Coastguard Worker     return OK;
428*ec779b8eSAndroid Build Coastguard Worker }
429*ec779b8eSAndroid Build Coastguard Worker 
stop()430*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::stop() {
431*ec779b8eSAndroid Build Coastguard Worker     ALOGD("stop(%p)", this);
432*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
433*ec779b8eSAndroid Build Coastguard Worker 
434*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
435*ec779b8eSAndroid Build Coastguard Worker         case STATE_RUNNING:
436*ec779b8eSAndroid Build Coastguard Worker             mPlayer->pause();
437*ec779b8eSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
438*ec779b8eSAndroid Build Coastguard Worker 
439*ec779b8eSAndroid Build Coastguard Worker         case STATE_PAUSED:
440*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_STOPPED;
441*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_STOPPED);
442*ec779b8eSAndroid Build Coastguard Worker             break;
443*ec779b8eSAndroid Build Coastguard Worker 
444*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARED:
445*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED:
446*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARING:
447*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARED:
448*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_STOPPED;
449*ec779b8eSAndroid Build Coastguard Worker             break;
450*ec779b8eSAndroid Build Coastguard Worker 
451*ec779b8eSAndroid Build Coastguard Worker         default:
452*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
453*ec779b8eSAndroid Build Coastguard Worker     }
454*ec779b8eSAndroid Build Coastguard Worker 
455*ec779b8eSAndroid Build Coastguard Worker     return OK;
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker 
pause()458*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::pause() {
459*ec779b8eSAndroid Build Coastguard Worker     ALOGD("pause(%p)", this);
460*ec779b8eSAndroid Build Coastguard Worker     // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
461*ec779b8eSAndroid Build Coastguard Worker     // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
462*ec779b8eSAndroid Build Coastguard Worker     // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
463*ec779b8eSAndroid Build Coastguard Worker     // getCurrentPosition here.
464*ec779b8eSAndroid Build Coastguard Worker     int unused;
465*ec779b8eSAndroid Build Coastguard Worker     getCurrentPosition(&unused);
466*ec779b8eSAndroid Build Coastguard Worker 
467*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
468*ec779b8eSAndroid Build Coastguard Worker 
469*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
470*ec779b8eSAndroid Build Coastguard Worker         case STATE_PAUSED:
471*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARED:
472*ec779b8eSAndroid Build Coastguard Worker             return OK;
473*ec779b8eSAndroid Build Coastguard Worker 
474*ec779b8eSAndroid Build Coastguard Worker         case STATE_RUNNING:
475*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_PAUSED;
476*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_PAUSED);
477*ec779b8eSAndroid Build Coastguard Worker             mPlayer->pause();
478*ec779b8eSAndroid Build Coastguard Worker             break;
479*ec779b8eSAndroid Build Coastguard Worker 
480*ec779b8eSAndroid Build Coastguard Worker         default:
481*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
482*ec779b8eSAndroid Build Coastguard Worker     }
483*ec779b8eSAndroid Build Coastguard Worker 
484*ec779b8eSAndroid Build Coastguard Worker     return OK;
485*ec779b8eSAndroid Build Coastguard Worker }
486*ec779b8eSAndroid Build Coastguard Worker 
isPlaying()487*ec779b8eSAndroid Build Coastguard Worker bool NuPlayerDriver::isPlaying() {
488*ec779b8eSAndroid Build Coastguard Worker     return mState == STATE_RUNNING && !mAtEOS;
489*ec779b8eSAndroid Build Coastguard Worker }
490*ec779b8eSAndroid Build Coastguard Worker 
setPlaybackSettings(const AudioPlaybackRate & rate)491*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) {
492*ec779b8eSAndroid Build Coastguard Worker     status_t err = mPlayer->setPlaybackSettings(rate);
493*ec779b8eSAndroid Build Coastguard Worker     if (err == OK) {
494*ec779b8eSAndroid Build Coastguard Worker         // try to update position
495*ec779b8eSAndroid Build Coastguard Worker         int unused;
496*ec779b8eSAndroid Build Coastguard Worker         getCurrentPosition(&unused);
497*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mLock);
498*ec779b8eSAndroid Build Coastguard Worker         if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
499*ec779b8eSAndroid Build Coastguard Worker             mState = STATE_PAUSED;
500*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_PAUSED);
501*ec779b8eSAndroid Build Coastguard Worker         } else if (rate.mSpeed != 0.f
502*ec779b8eSAndroid Build Coastguard Worker                 && (mState == STATE_PAUSED
503*ec779b8eSAndroid Build Coastguard Worker                     || mState == STATE_STOPPED_AND_PREPARED
504*ec779b8eSAndroid Build Coastguard Worker                     || mState == STATE_PREPARED)) {
505*ec779b8eSAndroid Build Coastguard Worker             err = start_l();
506*ec779b8eSAndroid Build Coastguard Worker         }
507*ec779b8eSAndroid Build Coastguard Worker     }
508*ec779b8eSAndroid Build Coastguard Worker     return err;
509*ec779b8eSAndroid Build Coastguard Worker }
510*ec779b8eSAndroid Build Coastguard Worker 
getPlaybackSettings(AudioPlaybackRate * rate)511*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getPlaybackSettings(AudioPlaybackRate *rate) {
512*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->getPlaybackSettings(rate);
513*ec779b8eSAndroid Build Coastguard Worker }
514*ec779b8eSAndroid Build Coastguard Worker 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)515*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
516*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->setSyncSettings(sync, videoFpsHint);
517*ec779b8eSAndroid Build Coastguard Worker }
518*ec779b8eSAndroid Build Coastguard Worker 
getSyncSettings(AVSyncSettings * sync,float * videoFps)519*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
520*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->getSyncSettings(sync, videoFps);
521*ec779b8eSAndroid Build Coastguard Worker }
522*ec779b8eSAndroid Build Coastguard Worker 
seekTo(int msec,MediaPlayerSeekMode mode)523*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::seekTo(int msec, MediaPlayerSeekMode mode) {
524*ec779b8eSAndroid Build Coastguard Worker     ALOGV("seekTo(%p) (%d ms, %d) at state %d", this, msec, mode, mState);
525*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
526*ec779b8eSAndroid Build Coastguard Worker 
527*ec779b8eSAndroid Build Coastguard Worker     int64_t seekTimeUs = msec * 1000LL;
528*ec779b8eSAndroid Build Coastguard Worker 
529*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
530*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARED:
531*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARED:
532*ec779b8eSAndroid Build Coastguard Worker         case STATE_PAUSED:
533*ec779b8eSAndroid Build Coastguard Worker         case STATE_RUNNING:
534*ec779b8eSAndroid Build Coastguard Worker         {
535*ec779b8eSAndroid Build Coastguard Worker             mAtEOS = false;
536*ec779b8eSAndroid Build Coastguard Worker             mSeekInProgress = true;
537*ec779b8eSAndroid Build Coastguard Worker             // seeks can take a while, so we essentially paused
538*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_PAUSED);
539*ec779b8eSAndroid Build Coastguard Worker             mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
540*ec779b8eSAndroid Build Coastguard Worker             break;
541*ec779b8eSAndroid Build Coastguard Worker         }
542*ec779b8eSAndroid Build Coastguard Worker 
543*ec779b8eSAndroid Build Coastguard Worker         default:
544*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
545*ec779b8eSAndroid Build Coastguard Worker     }
546*ec779b8eSAndroid Build Coastguard Worker 
547*ec779b8eSAndroid Build Coastguard Worker     mPositionUs = seekTimeUs;
548*ec779b8eSAndroid Build Coastguard Worker     return OK;
549*ec779b8eSAndroid Build Coastguard Worker }
550*ec779b8eSAndroid Build Coastguard Worker 
getCurrentPosition(int * msec)551*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getCurrentPosition(int *msec) {
552*ec779b8eSAndroid Build Coastguard Worker     int64_t tempUs = 0;
553*ec779b8eSAndroid Build Coastguard Worker     {
554*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mLock);
555*ec779b8eSAndroid Build Coastguard Worker         if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
556*ec779b8eSAndroid Build Coastguard Worker             tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
557*ec779b8eSAndroid Build Coastguard Worker             *msec = (int)divRound(tempUs, (int64_t)(1000));
558*ec779b8eSAndroid Build Coastguard Worker             return OK;
559*ec779b8eSAndroid Build Coastguard Worker         }
560*ec779b8eSAndroid Build Coastguard Worker     }
561*ec779b8eSAndroid Build Coastguard Worker 
562*ec779b8eSAndroid Build Coastguard Worker     status_t ret = mPlayer->getCurrentPosition(&tempUs);
563*ec779b8eSAndroid Build Coastguard Worker 
564*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
565*ec779b8eSAndroid Build Coastguard Worker     // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
566*ec779b8eSAndroid Build Coastguard Worker     // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
567*ec779b8eSAndroid Build Coastguard Worker     // position value that's different the seek to position.
568*ec779b8eSAndroid Build Coastguard Worker     if (ret != OK) {
569*ec779b8eSAndroid Build Coastguard Worker         tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
570*ec779b8eSAndroid Build Coastguard Worker     } else {
571*ec779b8eSAndroid Build Coastguard Worker         mPositionUs = tempUs;
572*ec779b8eSAndroid Build Coastguard Worker     }
573*ec779b8eSAndroid Build Coastguard Worker     *msec = (int)divRound(tempUs, (int64_t)(1000));
574*ec779b8eSAndroid Build Coastguard Worker     return OK;
575*ec779b8eSAndroid Build Coastguard Worker }
576*ec779b8eSAndroid Build Coastguard Worker 
getDuration(int * msec)577*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getDuration(int *msec) {
578*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
579*ec779b8eSAndroid Build Coastguard Worker 
580*ec779b8eSAndroid Build Coastguard Worker     if (mDurationUs < 0) {
581*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
582*ec779b8eSAndroid Build Coastguard Worker     }
583*ec779b8eSAndroid Build Coastguard Worker 
584*ec779b8eSAndroid Build Coastguard Worker     *msec = (mDurationUs + 500LL) / 1000;
585*ec779b8eSAndroid Build Coastguard Worker 
586*ec779b8eSAndroid Build Coastguard Worker     return OK;
587*ec779b8eSAndroid Build Coastguard Worker }
588*ec779b8eSAndroid Build Coastguard Worker 
updateMetrics(const char * where)589*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::updateMetrics(const char *where) {
590*ec779b8eSAndroid Build Coastguard Worker 
591*ec779b8eSAndroid Build Coastguard Worker     if (where == NULL) {
592*ec779b8eSAndroid Build Coastguard Worker         where = "unknown";
593*ec779b8eSAndroid Build Coastguard Worker     }
594*ec779b8eSAndroid Build Coastguard Worker     ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
595*ec779b8eSAndroid Build Coastguard Worker 
596*ec779b8eSAndroid Build Coastguard Worker     // avoid nested locks by gathering our data outside of the metrics lock.
597*ec779b8eSAndroid Build Coastguard Worker 
598*ec779b8eSAndroid Build Coastguard Worker     // final track statistics for this record
599*ec779b8eSAndroid Build Coastguard Worker     Vector<sp<AMessage>> trackStats;
600*ec779b8eSAndroid Build Coastguard Worker     mPlayer->getStats(&trackStats);
601*ec779b8eSAndroid Build Coastguard Worker 
602*ec779b8eSAndroid Build Coastguard Worker     // getDuration() uses mLock
603*ec779b8eSAndroid Build Coastguard Worker     int duration_ms = -1;
604*ec779b8eSAndroid Build Coastguard Worker     getDuration(&duration_ms);
605*ec779b8eSAndroid Build Coastguard Worker 
606*ec779b8eSAndroid Build Coastguard Worker     mPlayer->updateInternalTimers();
607*ec779b8eSAndroid Build Coastguard Worker 
608*ec779b8eSAndroid Build Coastguard Worker     int64_t playingTimeUs;
609*ec779b8eSAndroid Build Coastguard Worker     int64_t rebufferingTimeUs;
610*ec779b8eSAndroid Build Coastguard Worker     int32_t rebufferingEvents;
611*ec779b8eSAndroid Build Coastguard Worker     bool rebufferingAtExit;
612*ec779b8eSAndroid Build Coastguard Worker     {
613*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mLock);
614*ec779b8eSAndroid Build Coastguard Worker 
615*ec779b8eSAndroid Build Coastguard Worker         playingTimeUs = mPlayingTimeUs;
616*ec779b8eSAndroid Build Coastguard Worker         rebufferingTimeUs = mRebufferingTimeUs;
617*ec779b8eSAndroid Build Coastguard Worker         rebufferingEvents = mRebufferingEvents;
618*ec779b8eSAndroid Build Coastguard Worker         rebufferingAtExit = mRebufferingAtExit;
619*ec779b8eSAndroid Build Coastguard Worker     }
620*ec779b8eSAndroid Build Coastguard Worker 
621*ec779b8eSAndroid Build Coastguard Worker     // finish the rest of the gathering under our mutex to avoid metrics races.
622*ec779b8eSAndroid Build Coastguard Worker     // some of the fields we read are updated under mLock.
623*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mMetricsLock);
624*ec779b8eSAndroid Build Coastguard Worker 
625*ec779b8eSAndroid Build Coastguard Worker     if (mMetricsItem == NULL) {
626*ec779b8eSAndroid Build Coastguard Worker         return;
627*ec779b8eSAndroid Build Coastguard Worker     }
628*ec779b8eSAndroid Build Coastguard Worker 
629*ec779b8eSAndroid Build Coastguard Worker     mMetricsItem->setInt64(kPlayerDuration, duration_ms);
630*ec779b8eSAndroid Build Coastguard Worker     mMetricsItem->setInt64(kPlayerPlaying, (playingTimeUs+500)/1000 );
631*ec779b8eSAndroid Build Coastguard Worker 
632*ec779b8eSAndroid Build Coastguard Worker     if (rebufferingEvents != 0) {
633*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem->setInt64(kPlayerRebuffering, (rebufferingTimeUs+500)/1000 );
634*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem->setInt32(kPlayerRebufferingCount, rebufferingEvents);
635*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem->setInt32(kPlayerRebufferingAtExit, rebufferingAtExit);
636*ec779b8eSAndroid Build Coastguard Worker     }
637*ec779b8eSAndroid Build Coastguard Worker 
638*ec779b8eSAndroid Build Coastguard Worker     mMetricsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
639*ec779b8eSAndroid Build Coastguard Worker 
640*ec779b8eSAndroid Build Coastguard Worker     if (trackStats.size() > 0) {
641*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < trackStats.size(); ++i) {
642*ec779b8eSAndroid Build Coastguard Worker             const sp<AMessage> &stats = trackStats.itemAt(i);
643*ec779b8eSAndroid Build Coastguard Worker 
644*ec779b8eSAndroid Build Coastguard Worker             AString mime;
645*ec779b8eSAndroid Build Coastguard Worker             stats->findString("mime", &mime);
646*ec779b8eSAndroid Build Coastguard Worker 
647*ec779b8eSAndroid Build Coastguard Worker             AString name;
648*ec779b8eSAndroid Build Coastguard Worker             stats->findString("component-name", &name);
649*ec779b8eSAndroid Build Coastguard Worker 
650*ec779b8eSAndroid Build Coastguard Worker             if (mime.startsWith("video/")) {
651*ec779b8eSAndroid Build Coastguard Worker                 int32_t width, height;
652*ec779b8eSAndroid Build Coastguard Worker                 mMetricsItem->setCString(kPlayerVMime, mime.c_str());
653*ec779b8eSAndroid Build Coastguard Worker                 if (!name.empty()) {
654*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setCString(kPlayerVCodec, name.c_str());
655*ec779b8eSAndroid Build Coastguard Worker                 }
656*ec779b8eSAndroid Build Coastguard Worker 
657*ec779b8eSAndroid Build Coastguard Worker                 if (stats->findInt32("width", &width)
658*ec779b8eSAndroid Build Coastguard Worker                         && stats->findInt32("height", &height)) {
659*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setInt32(kPlayerWidth, width);
660*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setInt32(kPlayerHeight, height);
661*ec779b8eSAndroid Build Coastguard Worker                 }
662*ec779b8eSAndroid Build Coastguard Worker 
663*ec779b8eSAndroid Build Coastguard Worker                 int64_t numFramesTotal = 0;
664*ec779b8eSAndroid Build Coastguard Worker                 int64_t numFramesDropped = 0;
665*ec779b8eSAndroid Build Coastguard Worker                 stats->findInt64("frames-total", &numFramesTotal);
666*ec779b8eSAndroid Build Coastguard Worker                 stats->findInt64("frames-dropped-output", &numFramesDropped);
667*ec779b8eSAndroid Build Coastguard Worker 
668*ec779b8eSAndroid Build Coastguard Worker                 mMetricsItem->setInt64(kPlayerFrames, numFramesTotal);
669*ec779b8eSAndroid Build Coastguard Worker                 mMetricsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
670*ec779b8eSAndroid Build Coastguard Worker 
671*ec779b8eSAndroid Build Coastguard Worker                 float frameRate = 0;
672*ec779b8eSAndroid Build Coastguard Worker                 if (stats->findFloat("frame-rate-total", &frameRate)) {
673*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setDouble(kPlayerFrameRate, (double) frameRate);
674*ec779b8eSAndroid Build Coastguard Worker                 }
675*ec779b8eSAndroid Build Coastguard Worker 
676*ec779b8eSAndroid Build Coastguard Worker             } else if (mime.startsWith("audio/")) {
677*ec779b8eSAndroid Build Coastguard Worker                 mMetricsItem->setCString(kPlayerAMime, mime.c_str());
678*ec779b8eSAndroid Build Coastguard Worker                 if (!name.empty()) {
679*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setCString(kPlayerACodec, name.c_str());
680*ec779b8eSAndroid Build Coastguard Worker                 }
681*ec779b8eSAndroid Build Coastguard Worker             }
682*ec779b8eSAndroid Build Coastguard Worker         }
683*ec779b8eSAndroid Build Coastguard Worker     }
684*ec779b8eSAndroid Build Coastguard Worker }
685*ec779b8eSAndroid Build Coastguard Worker 
686*ec779b8eSAndroid Build Coastguard Worker 
logMetrics(const char * where)687*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::logMetrics(const char *where) {
688*ec779b8eSAndroid Build Coastguard Worker     if (where == NULL) {
689*ec779b8eSAndroid Build Coastguard Worker         where = "unknown";
690*ec779b8eSAndroid Build Coastguard Worker     }
691*ec779b8eSAndroid Build Coastguard Worker     ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
692*ec779b8eSAndroid Build Coastguard Worker 
693*ec779b8eSAndroid Build Coastguard Worker     // ensure mMetricsItem stability while we write it out
694*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mMetricsLock);
695*ec779b8eSAndroid Build Coastguard Worker 
696*ec779b8eSAndroid Build Coastguard Worker     if (mMetricsItem == NULL || mMetricsItem->isEnabled() == false) {
697*ec779b8eSAndroid Build Coastguard Worker         return;
698*ec779b8eSAndroid Build Coastguard Worker     }
699*ec779b8eSAndroid Build Coastguard Worker 
700*ec779b8eSAndroid Build Coastguard Worker     // log only non-empty records
701*ec779b8eSAndroid Build Coastguard Worker     // we always updateMetrics() before we get here
702*ec779b8eSAndroid Build Coastguard Worker     // and that always injects 3 fields (duration, playing time, and
703*ec779b8eSAndroid Build Coastguard Worker     // datasource) into the record.
704*ec779b8eSAndroid Build Coastguard Worker     // So the canonical "empty" record has 3 elements in it.
705*ec779b8eSAndroid Build Coastguard Worker     if (mMetricsItem->count() > 3) {
706*ec779b8eSAndroid Build Coastguard Worker 
707*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem->selfrecord();
708*ec779b8eSAndroid Build Coastguard Worker 
709*ec779b8eSAndroid Build Coastguard Worker         // re-init in case we prepare() and start() again.
710*ec779b8eSAndroid Build Coastguard Worker         delete mMetricsItem ;
711*ec779b8eSAndroid Build Coastguard Worker         mMetricsItem = mediametrics::Item::create(kKeyPlayer);
712*ec779b8eSAndroid Build Coastguard Worker         if (mMetricsItem) {
713*ec779b8eSAndroid Build Coastguard Worker             mMetricsItem->setUid(mClientUid);
714*ec779b8eSAndroid Build Coastguard Worker         }
715*ec779b8eSAndroid Build Coastguard Worker     } else {
716*ec779b8eSAndroid Build Coastguard Worker         ALOGV("nothing to record (only %zu fields)", mMetricsItem->count());
717*ec779b8eSAndroid Build Coastguard Worker     }
718*ec779b8eSAndroid Build Coastguard Worker }
719*ec779b8eSAndroid Build Coastguard Worker 
reset()720*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::reset() {
721*ec779b8eSAndroid Build Coastguard Worker     ALOGD("reset(%p) at state %d", this, mState);
722*ec779b8eSAndroid Build Coastguard Worker 
723*ec779b8eSAndroid Build Coastguard Worker     updateMetrics("reset");
724*ec779b8eSAndroid Build Coastguard Worker     logMetrics("reset");
725*ec779b8eSAndroid Build Coastguard Worker 
726*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
727*ec779b8eSAndroid Build Coastguard Worker 
728*ec779b8eSAndroid Build Coastguard Worker     switch (mState) {
729*ec779b8eSAndroid Build Coastguard Worker         case STATE_IDLE:
730*ec779b8eSAndroid Build Coastguard Worker             return OK;
731*ec779b8eSAndroid Build Coastguard Worker 
732*ec779b8eSAndroid Build Coastguard Worker         case STATE_SET_DATASOURCE_PENDING:
733*ec779b8eSAndroid Build Coastguard Worker         case STATE_RESET_IN_PROGRESS:
734*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
735*ec779b8eSAndroid Build Coastguard Worker 
736*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARING:
737*ec779b8eSAndroid Build Coastguard Worker         {
738*ec779b8eSAndroid Build Coastguard Worker             CHECK(mIsAsyncPrepare);
739*ec779b8eSAndroid Build Coastguard Worker 
740*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_PREPARED);
741*ec779b8eSAndroid Build Coastguard Worker             break;
742*ec779b8eSAndroid Build Coastguard Worker         }
743*ec779b8eSAndroid Build Coastguard Worker 
744*ec779b8eSAndroid Build Coastguard Worker         default:
745*ec779b8eSAndroid Build Coastguard Worker             break;
746*ec779b8eSAndroid Build Coastguard Worker     }
747*ec779b8eSAndroid Build Coastguard Worker 
748*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_STOPPED) {
749*ec779b8eSAndroid Build Coastguard Worker         notifyListener_l(MEDIA_STOPPED);
750*ec779b8eSAndroid Build Coastguard Worker     }
751*ec779b8eSAndroid Build Coastguard Worker 
752*ec779b8eSAndroid Build Coastguard Worker     if (property_get_bool("persist.debug.sf.stats", false)) {
753*ec779b8eSAndroid Build Coastguard Worker         Vector<String16> args;
754*ec779b8eSAndroid Build Coastguard Worker         dump(-1, args);
755*ec779b8eSAndroid Build Coastguard Worker     }
756*ec779b8eSAndroid Build Coastguard Worker 
757*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_RESET_IN_PROGRESS;
758*ec779b8eSAndroid Build Coastguard Worker     mPlayer->resetAsync();
759*ec779b8eSAndroid Build Coastguard Worker 
760*ec779b8eSAndroid Build Coastguard Worker     while (mState == STATE_RESET_IN_PROGRESS) {
761*ec779b8eSAndroid Build Coastguard Worker         mCondition.wait(mLock);
762*ec779b8eSAndroid Build Coastguard Worker     }
763*ec779b8eSAndroid Build Coastguard Worker 
764*ec779b8eSAndroid Build Coastguard Worker     mDurationUs = -1;
765*ec779b8eSAndroid Build Coastguard Worker     mPositionUs = -1;
766*ec779b8eSAndroid Build Coastguard Worker     mLooping = false;
767*ec779b8eSAndroid Build Coastguard Worker     mPlayingTimeUs = 0;
768*ec779b8eSAndroid Build Coastguard Worker     mRebufferingTimeUs = 0;
769*ec779b8eSAndroid Build Coastguard Worker     mRebufferingEvents = 0;
770*ec779b8eSAndroid Build Coastguard Worker     mRebufferingAtExit = false;
771*ec779b8eSAndroid Build Coastguard Worker 
772*ec779b8eSAndroid Build Coastguard Worker     return OK;
773*ec779b8eSAndroid Build Coastguard Worker }
774*ec779b8eSAndroid Build Coastguard Worker 
notifyAt(int64_t mediaTimeUs)775*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::notifyAt(int64_t mediaTimeUs) {
776*ec779b8eSAndroid Build Coastguard Worker     ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
777*ec779b8eSAndroid Build Coastguard Worker     return mPlayer->notifyAt(mediaTimeUs);
778*ec779b8eSAndroid Build Coastguard Worker }
779*ec779b8eSAndroid Build Coastguard Worker 
setLooping(int loop)780*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setLooping(int loop) {
781*ec779b8eSAndroid Build Coastguard Worker     mLooping = loop != 0;
782*ec779b8eSAndroid Build Coastguard Worker     return OK;
783*ec779b8eSAndroid Build Coastguard Worker }
784*ec779b8eSAndroid Build Coastguard Worker 
playerType()785*ec779b8eSAndroid Build Coastguard Worker player_type NuPlayerDriver::playerType() {
786*ec779b8eSAndroid Build Coastguard Worker     return NU_PLAYER;
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker 
invoke(const Parcel & request,Parcel * reply)789*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
790*ec779b8eSAndroid Build Coastguard Worker     if (reply == NULL) {
791*ec779b8eSAndroid Build Coastguard Worker         ALOGE("reply is a NULL pointer");
792*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
793*ec779b8eSAndroid Build Coastguard Worker     }
794*ec779b8eSAndroid Build Coastguard Worker 
795*ec779b8eSAndroid Build Coastguard Worker     int32_t methodId;
796*ec779b8eSAndroid Build Coastguard Worker     status_t ret = request.readInt32(&methodId);
797*ec779b8eSAndroid Build Coastguard Worker     if (ret != OK) {
798*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to retrieve the requested method to invoke");
799*ec779b8eSAndroid Build Coastguard Worker         return ret;
800*ec779b8eSAndroid Build Coastguard Worker     }
801*ec779b8eSAndroid Build Coastguard Worker 
802*ec779b8eSAndroid Build Coastguard Worker     switch (methodId) {
803*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_SET_VIDEO_SCALING_MODE:
804*ec779b8eSAndroid Build Coastguard Worker         {
805*ec779b8eSAndroid Build Coastguard Worker             int mode = request.readInt32();
806*ec779b8eSAndroid Build Coastguard Worker             return mPlayer->setVideoScalingMode(mode);
807*ec779b8eSAndroid Build Coastguard Worker         }
808*ec779b8eSAndroid Build Coastguard Worker 
809*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_GET_TRACK_INFO:
810*ec779b8eSAndroid Build Coastguard Worker         {
811*ec779b8eSAndroid Build Coastguard Worker             return mPlayer->getTrackInfo(reply);
812*ec779b8eSAndroid Build Coastguard Worker         }
813*ec779b8eSAndroid Build Coastguard Worker 
814*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_SELECT_TRACK:
815*ec779b8eSAndroid Build Coastguard Worker         {
816*ec779b8eSAndroid Build Coastguard Worker             int trackIndex = request.readInt32();
817*ec779b8eSAndroid Build Coastguard Worker             int msec = 0;
818*ec779b8eSAndroid Build Coastguard Worker             // getCurrentPosition should always return OK
819*ec779b8eSAndroid Build Coastguard Worker             getCurrentPosition(&msec);
820*ec779b8eSAndroid Build Coastguard Worker             return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000LL);
821*ec779b8eSAndroid Build Coastguard Worker         }
822*ec779b8eSAndroid Build Coastguard Worker 
823*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_UNSELECT_TRACK:
824*ec779b8eSAndroid Build Coastguard Worker         {
825*ec779b8eSAndroid Build Coastguard Worker             int trackIndex = request.readInt32();
826*ec779b8eSAndroid Build Coastguard Worker             return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
827*ec779b8eSAndroid Build Coastguard Worker         }
828*ec779b8eSAndroid Build Coastguard Worker 
829*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_GET_SELECTED_TRACK:
830*ec779b8eSAndroid Build Coastguard Worker         {
831*ec779b8eSAndroid Build Coastguard Worker             int32_t type = request.readInt32();
832*ec779b8eSAndroid Build Coastguard Worker             return mPlayer->getSelectedTrack(type, reply);
833*ec779b8eSAndroid Build Coastguard Worker         }
834*ec779b8eSAndroid Build Coastguard Worker 
835*ec779b8eSAndroid Build Coastguard Worker         case INVOKE_ID_SET_PLAYER_IID:
836*ec779b8eSAndroid Build Coastguard Worker         {
837*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock autoLock(mAudioSinkLock);
838*ec779b8eSAndroid Build Coastguard Worker             mCachedPlayerIId = request.readInt32();
839*ec779b8eSAndroid Build Coastguard Worker             if (mAudioSink != nullptr) {
840*ec779b8eSAndroid Build Coastguard Worker                 mAudioSink->setPlayerIId(mCachedPlayerIId);
841*ec779b8eSAndroid Build Coastguard Worker             }
842*ec779b8eSAndroid Build Coastguard Worker             return OK;
843*ec779b8eSAndroid Build Coastguard Worker         }
844*ec779b8eSAndroid Build Coastguard Worker 
845*ec779b8eSAndroid Build Coastguard Worker         default:
846*ec779b8eSAndroid Build Coastguard Worker         {
847*ec779b8eSAndroid Build Coastguard Worker             return INVALID_OPERATION;
848*ec779b8eSAndroid Build Coastguard Worker         }
849*ec779b8eSAndroid Build Coastguard Worker     }
850*ec779b8eSAndroid Build Coastguard Worker }
851*ec779b8eSAndroid Build Coastguard Worker 
setAudioSink(const sp<AudioSink> & audioSink)852*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
853*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mAudioSinkLock);
854*ec779b8eSAndroid Build Coastguard Worker     mPlayer->setAudioSink(audioSink);
855*ec779b8eSAndroid Build Coastguard Worker     mAudioSink = audioSink;
856*ec779b8eSAndroid Build Coastguard Worker     if (mCachedPlayerIId != PLAYER_PIID_INVALID) {
857*ec779b8eSAndroid Build Coastguard Worker         mAudioSink->setPlayerIId(mCachedPlayerIId);
858*ec779b8eSAndroid Build Coastguard Worker     }
859*ec779b8eSAndroid Build Coastguard Worker }
860*ec779b8eSAndroid Build Coastguard Worker 
setParameter(int key,const Parcel & request)861*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setParameter(
862*ec779b8eSAndroid Build Coastguard Worker         int key, const Parcel &request ) {
863*ec779b8eSAndroid Build Coastguard Worker     if (key == KEY_PARAMETER_RTP_ATTRIBUTES) {
864*ec779b8eSAndroid Build Coastguard Worker         mPlayer->setTargetBitrate(request.readInt32());
865*ec779b8eSAndroid Build Coastguard Worker         return OK;
866*ec779b8eSAndroid Build Coastguard Worker     }
867*ec779b8eSAndroid Build Coastguard Worker     return INVALID_OPERATION;
868*ec779b8eSAndroid Build Coastguard Worker }
869*ec779b8eSAndroid Build Coastguard Worker 
getParameter(int key,Parcel * reply)870*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
871*ec779b8eSAndroid Build Coastguard Worker 
872*ec779b8eSAndroid Build Coastguard Worker     if (key == FOURCC('m','t','r','X')) {
873*ec779b8eSAndroid Build Coastguard Worker         // mtrX -- a play on 'metrics' (not matrix)
874*ec779b8eSAndroid Build Coastguard Worker         // gather current info all together, parcel it, and send it back
875*ec779b8eSAndroid Build Coastguard Worker         updateMetrics("api");
876*ec779b8eSAndroid Build Coastguard Worker 
877*ec779b8eSAndroid Build Coastguard Worker         // ensure mMetricsItem stability while writing to parcel
878*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mMetricsLock);
879*ec779b8eSAndroid Build Coastguard Worker         if (mMetricsItem != NULL) {
880*ec779b8eSAndroid Build Coastguard Worker             mMetricsItem->writeToParcel(reply);
881*ec779b8eSAndroid Build Coastguard Worker         }
882*ec779b8eSAndroid Build Coastguard Worker         return OK;
883*ec779b8eSAndroid Build Coastguard Worker     }
884*ec779b8eSAndroid Build Coastguard Worker 
885*ec779b8eSAndroid Build Coastguard Worker     return INVALID_OPERATION;
886*ec779b8eSAndroid Build Coastguard Worker }
887*ec779b8eSAndroid Build Coastguard Worker 
getMetadata(const media::Metadata::Filter &,Parcel * records)888*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getMetadata(
889*ec779b8eSAndroid Build Coastguard Worker         const media::Metadata::Filter& /* ids */, Parcel *records) {
890*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
891*ec779b8eSAndroid Build Coastguard Worker 
892*ec779b8eSAndroid Build Coastguard Worker     using media::Metadata;
893*ec779b8eSAndroid Build Coastguard Worker 
894*ec779b8eSAndroid Build Coastguard Worker     Metadata meta(records);
895*ec779b8eSAndroid Build Coastguard Worker 
896*ec779b8eSAndroid Build Coastguard Worker     meta.appendBool(
897*ec779b8eSAndroid Build Coastguard Worker             Metadata::kPauseAvailable,
898*ec779b8eSAndroid Build Coastguard Worker             mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
899*ec779b8eSAndroid Build Coastguard Worker 
900*ec779b8eSAndroid Build Coastguard Worker     meta.appendBool(
901*ec779b8eSAndroid Build Coastguard Worker             Metadata::kSeekBackwardAvailable,
902*ec779b8eSAndroid Build Coastguard Worker             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
903*ec779b8eSAndroid Build Coastguard Worker 
904*ec779b8eSAndroid Build Coastguard Worker     meta.appendBool(
905*ec779b8eSAndroid Build Coastguard Worker             Metadata::kSeekForwardAvailable,
906*ec779b8eSAndroid Build Coastguard Worker             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
907*ec779b8eSAndroid Build Coastguard Worker 
908*ec779b8eSAndroid Build Coastguard Worker     meta.appendBool(
909*ec779b8eSAndroid Build Coastguard Worker             Metadata::kSeekAvailable,
910*ec779b8eSAndroid Build Coastguard Worker             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
911*ec779b8eSAndroid Build Coastguard Worker 
912*ec779b8eSAndroid Build Coastguard Worker     return OK;
913*ec779b8eSAndroid Build Coastguard Worker }
914*ec779b8eSAndroid Build Coastguard Worker 
notifyResetComplete()915*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyResetComplete() {
916*ec779b8eSAndroid Build Coastguard Worker     ALOGD("notifyResetComplete(%p)", this);
917*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
918*ec779b8eSAndroid Build Coastguard Worker 
919*ec779b8eSAndroid Build Coastguard Worker     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
920*ec779b8eSAndroid Build Coastguard Worker     mState = STATE_IDLE;
921*ec779b8eSAndroid Build Coastguard Worker     mCondition.broadcast();
922*ec779b8eSAndroid Build Coastguard Worker }
923*ec779b8eSAndroid Build Coastguard Worker 
notifySetSurfaceComplete()924*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySetSurfaceComplete() {
925*ec779b8eSAndroid Build Coastguard Worker     ALOGV("notifySetSurfaceComplete(%p)", this);
926*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
927*ec779b8eSAndroid Build Coastguard Worker 
928*ec779b8eSAndroid Build Coastguard Worker     CHECK(mSetSurfaceInProgress);
929*ec779b8eSAndroid Build Coastguard Worker     mSetSurfaceInProgress = false;
930*ec779b8eSAndroid Build Coastguard Worker 
931*ec779b8eSAndroid Build Coastguard Worker     mCondition.broadcast();
932*ec779b8eSAndroid Build Coastguard Worker }
933*ec779b8eSAndroid Build Coastguard Worker 
notifyDuration(int64_t durationUs)934*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyDuration(int64_t durationUs) {
935*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
936*ec779b8eSAndroid Build Coastguard Worker     mDurationUs = durationUs;
937*ec779b8eSAndroid Build Coastguard Worker }
938*ec779b8eSAndroid Build Coastguard Worker 
notifyMorePlayingTimeUs(int64_t playingUs)939*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyMorePlayingTimeUs(int64_t playingUs) {
940*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
941*ec779b8eSAndroid Build Coastguard Worker     mPlayingTimeUs += playingUs;
942*ec779b8eSAndroid Build Coastguard Worker }
943*ec779b8eSAndroid Build Coastguard Worker 
notifyMoreRebufferingTimeUs(int64_t rebufferingUs)944*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyMoreRebufferingTimeUs(int64_t rebufferingUs) {
945*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
946*ec779b8eSAndroid Build Coastguard Worker     mRebufferingTimeUs += rebufferingUs;
947*ec779b8eSAndroid Build Coastguard Worker     mRebufferingEvents++;
948*ec779b8eSAndroid Build Coastguard Worker }
949*ec779b8eSAndroid Build Coastguard Worker 
notifyRebufferingWhenExit(bool status)950*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyRebufferingWhenExit(bool status) {
951*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
952*ec779b8eSAndroid Build Coastguard Worker     mRebufferingAtExit = status;
953*ec779b8eSAndroid Build Coastguard Worker }
954*ec779b8eSAndroid Build Coastguard Worker 
notifySeekComplete()955*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySeekComplete() {
956*ec779b8eSAndroid Build Coastguard Worker     ALOGV("notifySeekComplete(%p)", this);
957*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
958*ec779b8eSAndroid Build Coastguard Worker     mSeekInProgress = false;
959*ec779b8eSAndroid Build Coastguard Worker     notifySeekComplete_l();
960*ec779b8eSAndroid Build Coastguard Worker }
961*ec779b8eSAndroid Build Coastguard Worker 
notifySeekComplete_l()962*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySeekComplete_l() {
963*ec779b8eSAndroid Build Coastguard Worker     bool wasSeeking = true;
964*ec779b8eSAndroid Build Coastguard Worker     if (mState == STATE_STOPPED_AND_PREPARING) {
965*ec779b8eSAndroid Build Coastguard Worker         wasSeeking = false;
966*ec779b8eSAndroid Build Coastguard Worker         mState = STATE_STOPPED_AND_PREPARED;
967*ec779b8eSAndroid Build Coastguard Worker         mCondition.broadcast();
968*ec779b8eSAndroid Build Coastguard Worker         if (!mIsAsyncPrepare) {
969*ec779b8eSAndroid Build Coastguard Worker             // if we are preparing synchronously, no need to notify listener
970*ec779b8eSAndroid Build Coastguard Worker             return;
971*ec779b8eSAndroid Build Coastguard Worker         }
972*ec779b8eSAndroid Build Coastguard Worker     } else if (mState == STATE_STOPPED) {
973*ec779b8eSAndroid Build Coastguard Worker         // no need to notify listener
974*ec779b8eSAndroid Build Coastguard Worker         return;
975*ec779b8eSAndroid Build Coastguard Worker     }
976*ec779b8eSAndroid Build Coastguard Worker     notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
977*ec779b8eSAndroid Build Coastguard Worker }
978*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd,const Vector<String16> &) const979*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::dump(
980*ec779b8eSAndroid Build Coastguard Worker         int fd, const Vector<String16> & /* args */) const {
981*ec779b8eSAndroid Build Coastguard Worker 
982*ec779b8eSAndroid Build Coastguard Worker     Vector<sp<AMessage> > trackStats;
983*ec779b8eSAndroid Build Coastguard Worker     mPlayer->getStats(&trackStats);
984*ec779b8eSAndroid Build Coastguard Worker 
985*ec779b8eSAndroid Build Coastguard Worker     AString logString(" NuPlayer\n");
986*ec779b8eSAndroid Build Coastguard Worker     char buf[256] = {0};
987*ec779b8eSAndroid Build Coastguard Worker 
988*ec779b8eSAndroid Build Coastguard Worker     bool locked = false;
989*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < kDumpLockRetries; ++i) {
990*ec779b8eSAndroid Build Coastguard Worker         if (mLock.tryLock() == NO_ERROR) {
991*ec779b8eSAndroid Build Coastguard Worker             locked = true;
992*ec779b8eSAndroid Build Coastguard Worker             break;
993*ec779b8eSAndroid Build Coastguard Worker         }
994*ec779b8eSAndroid Build Coastguard Worker         usleep(kDumpLockSleepUs);
995*ec779b8eSAndroid Build Coastguard Worker     }
996*ec779b8eSAndroid Build Coastguard Worker 
997*ec779b8eSAndroid Build Coastguard Worker     if (locked) {
998*ec779b8eSAndroid Build Coastguard Worker         snprintf(buf, sizeof(buf), "  state(%d), atEOS(%d), looping(%d), autoLoop(%d), ",
999*ec779b8eSAndroid Build Coastguard Worker                 mState, mAtEOS, mLooping, mAutoLoop);
1000*ec779b8eSAndroid Build Coastguard Worker         logString.append(buf);
1001*ec779b8eSAndroid Build Coastguard Worker         mPlayer->dump(logString);
1002*ec779b8eSAndroid Build Coastguard Worker         logString.append("\n");
1003*ec779b8eSAndroid Build Coastguard Worker         mLock.unlock();
1004*ec779b8eSAndroid Build Coastguard Worker     } else {
1005*ec779b8eSAndroid Build Coastguard Worker         snprintf(buf, sizeof(buf), "  NPD(%p) lock is taken\n", this);
1006*ec779b8eSAndroid Build Coastguard Worker         logString.append(buf);
1007*ec779b8eSAndroid Build Coastguard Worker     }
1008*ec779b8eSAndroid Build Coastguard Worker 
1009*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < trackStats.size(); ++i) {
1010*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &stats = trackStats.itemAt(i);
1011*ec779b8eSAndroid Build Coastguard Worker 
1012*ec779b8eSAndroid Build Coastguard Worker         AString mime;
1013*ec779b8eSAndroid Build Coastguard Worker         if (stats->findString("mime", &mime)) {
1014*ec779b8eSAndroid Build Coastguard Worker             snprintf(buf, sizeof(buf), "  mime(%s)\n", mime.c_str());
1015*ec779b8eSAndroid Build Coastguard Worker             logString.append(buf);
1016*ec779b8eSAndroid Build Coastguard Worker         }
1017*ec779b8eSAndroid Build Coastguard Worker 
1018*ec779b8eSAndroid Build Coastguard Worker         AString name;
1019*ec779b8eSAndroid Build Coastguard Worker         if (stats->findString("component-name", &name)) {
1020*ec779b8eSAndroid Build Coastguard Worker             snprintf(buf, sizeof(buf), "    decoder(%s)\n", name.c_str());
1021*ec779b8eSAndroid Build Coastguard Worker             logString.append(buf);
1022*ec779b8eSAndroid Build Coastguard Worker         }
1023*ec779b8eSAndroid Build Coastguard Worker 
1024*ec779b8eSAndroid Build Coastguard Worker         if (mime.startsWith("video/")) {
1025*ec779b8eSAndroid Build Coastguard Worker             int32_t width, height;
1026*ec779b8eSAndroid Build Coastguard Worker             if (stats->findInt32("width", &width)
1027*ec779b8eSAndroid Build Coastguard Worker                     && stats->findInt32("height", &height)) {
1028*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buf, sizeof(buf), "    resolution(%d x %d)\n", width, height);
1029*ec779b8eSAndroid Build Coastguard Worker                 logString.append(buf);
1030*ec779b8eSAndroid Build Coastguard Worker             }
1031*ec779b8eSAndroid Build Coastguard Worker 
1032*ec779b8eSAndroid Build Coastguard Worker             int64_t numFramesTotal = 0;
1033*ec779b8eSAndroid Build Coastguard Worker             int64_t numFramesDropped = 0;
1034*ec779b8eSAndroid Build Coastguard Worker 
1035*ec779b8eSAndroid Build Coastguard Worker             stats->findInt64("frames-total", &numFramesTotal);
1036*ec779b8eSAndroid Build Coastguard Worker             stats->findInt64("frames-dropped-output", &numFramesDropped);
1037*ec779b8eSAndroid Build Coastguard Worker             snprintf(buf, sizeof(buf), "    numFramesTotal(%lld), numFramesDropped(%lld), "
1038*ec779b8eSAndroid Build Coastguard Worker                      "percentageDropped(%.2f%%)\n",
1039*ec779b8eSAndroid Build Coastguard Worker                      (long long)numFramesTotal,
1040*ec779b8eSAndroid Build Coastguard Worker                      (long long)numFramesDropped,
1041*ec779b8eSAndroid Build Coastguard Worker                      numFramesTotal == 0
1042*ec779b8eSAndroid Build Coastguard Worker                             ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
1043*ec779b8eSAndroid Build Coastguard Worker             logString.append(buf);
1044*ec779b8eSAndroid Build Coastguard Worker         }
1045*ec779b8eSAndroid Build Coastguard Worker     }
1046*ec779b8eSAndroid Build Coastguard Worker 
1047*ec779b8eSAndroid Build Coastguard Worker     ALOGI("%s", logString.c_str());
1048*ec779b8eSAndroid Build Coastguard Worker 
1049*ec779b8eSAndroid Build Coastguard Worker     if (fd >= 0) {
1050*ec779b8eSAndroid Build Coastguard Worker         FILE *out = fdopen(dup(fd), "w");
1051*ec779b8eSAndroid Build Coastguard Worker         fprintf(out, "%s", logString.c_str());
1052*ec779b8eSAndroid Build Coastguard Worker         fclose(out);
1053*ec779b8eSAndroid Build Coastguard Worker         out = NULL;
1054*ec779b8eSAndroid Build Coastguard Worker     }
1055*ec779b8eSAndroid Build Coastguard Worker 
1056*ec779b8eSAndroid Build Coastguard Worker     return OK;
1057*ec779b8eSAndroid Build Coastguard Worker }
1058*ec779b8eSAndroid Build Coastguard Worker 
notifyListener(int msg,int ext1,int ext2,const Parcel * in)1059*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyListener(
1060*ec779b8eSAndroid Build Coastguard Worker         int msg, int ext1, int ext2, const Parcel *in) {
1061*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
1062*ec779b8eSAndroid Build Coastguard Worker     notifyListener_l(msg, ext1, ext2, in);
1063*ec779b8eSAndroid Build Coastguard Worker }
1064*ec779b8eSAndroid Build Coastguard Worker 
notifyListener_l(int msg,int ext1,int ext2,const Parcel * in)1065*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyListener_l(
1066*ec779b8eSAndroid Build Coastguard Worker         int msg, int ext1, int ext2, const Parcel *in) {
1067*ec779b8eSAndroid Build Coastguard Worker     ALOGV("notifyListener_l(%p), (%d, %d, %d, %d), loop setting(%d, %d)",
1068*ec779b8eSAndroid Build Coastguard Worker             this, msg, ext1, ext2, (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
1069*ec779b8eSAndroid Build Coastguard Worker     switch (msg) {
1070*ec779b8eSAndroid Build Coastguard Worker         case MEDIA_PLAYBACK_COMPLETE:
1071*ec779b8eSAndroid Build Coastguard Worker         {
1072*ec779b8eSAndroid Build Coastguard Worker             if (mState != STATE_RESET_IN_PROGRESS) {
1073*ec779b8eSAndroid Build Coastguard Worker                 if (mAutoLoop) {
1074*ec779b8eSAndroid Build Coastguard Worker                     audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
1075*ec779b8eSAndroid Build Coastguard Worker                     Mutex::Autolock autoLock(mAudioSinkLock);
1076*ec779b8eSAndroid Build Coastguard Worker                     if (mAudioSink != NULL) {
1077*ec779b8eSAndroid Build Coastguard Worker                         streamType = mAudioSink->getAudioStreamType();
1078*ec779b8eSAndroid Build Coastguard Worker                     }
1079*ec779b8eSAndroid Build Coastguard Worker                     if (streamType == AUDIO_STREAM_NOTIFICATION) {
1080*ec779b8eSAndroid Build Coastguard Worker                         ALOGW("disabling auto-loop for notification");
1081*ec779b8eSAndroid Build Coastguard Worker                         mAutoLoop = false;
1082*ec779b8eSAndroid Build Coastguard Worker                     }
1083*ec779b8eSAndroid Build Coastguard Worker                 }
1084*ec779b8eSAndroid Build Coastguard Worker                 if (mLooping || mAutoLoop) {
1085*ec779b8eSAndroid Build Coastguard Worker                     mPlayer->seekToAsync(0);
1086*ec779b8eSAndroid Build Coastguard Worker                     Mutex::Autolock autoLock(mAudioSinkLock);
1087*ec779b8eSAndroid Build Coastguard Worker                     if (mAudioSink != NULL) {
1088*ec779b8eSAndroid Build Coastguard Worker                         // The renderer has stopped the sink at the end in order to play out
1089*ec779b8eSAndroid Build Coastguard Worker                         // the last little bit of audio. If we're looping, we need to restart it.
1090*ec779b8eSAndroid Build Coastguard Worker                         mAudioSink->start();
1091*ec779b8eSAndroid Build Coastguard Worker                     }
1092*ec779b8eSAndroid Build Coastguard Worker                     // don't send completion event when looping
1093*ec779b8eSAndroid Build Coastguard Worker                     return;
1094*ec779b8eSAndroid Build Coastguard Worker                 }
1095*ec779b8eSAndroid Build Coastguard Worker                 if (property_get_bool("persist.debug.sf.stats", false)) {
1096*ec779b8eSAndroid Build Coastguard Worker                     Vector<String16> args;
1097*ec779b8eSAndroid Build Coastguard Worker                     dump(-1, args);
1098*ec779b8eSAndroid Build Coastguard Worker                 }
1099*ec779b8eSAndroid Build Coastguard Worker                 mPlayer->pause();
1100*ec779b8eSAndroid Build Coastguard Worker                 mState = STATE_PAUSED;
1101*ec779b8eSAndroid Build Coastguard Worker             }
1102*ec779b8eSAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
1103*ec779b8eSAndroid Build Coastguard Worker         }
1104*ec779b8eSAndroid Build Coastguard Worker 
1105*ec779b8eSAndroid Build Coastguard Worker         case MEDIA_ERROR:
1106*ec779b8eSAndroid Build Coastguard Worker         {
1107*ec779b8eSAndroid Build Coastguard Worker             // when we have an error, add it to the analytics for this playback.
1108*ec779b8eSAndroid Build Coastguard Worker             // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
1109*ec779b8eSAndroid Build Coastguard Worker             // [test against msg is due to fall through from previous switch value]
1110*ec779b8eSAndroid Build Coastguard Worker             if (msg == MEDIA_ERROR) {
1111*ec779b8eSAndroid Build Coastguard Worker                 Mutex::Autolock autoLock(mMetricsLock);
1112*ec779b8eSAndroid Build Coastguard Worker                 if (mMetricsItem != NULL) {
1113*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setInt32(kPlayerError, ext1);
1114*ec779b8eSAndroid Build Coastguard Worker                     if (ext2 != 0) {
1115*ec779b8eSAndroid Build Coastguard Worker                         mMetricsItem->setInt32(kPlayerErrorCode, ext2);
1116*ec779b8eSAndroid Build Coastguard Worker                     }
1117*ec779b8eSAndroid Build Coastguard Worker                     mMetricsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
1118*ec779b8eSAndroid Build Coastguard Worker                 }
1119*ec779b8eSAndroid Build Coastguard Worker             }
1120*ec779b8eSAndroid Build Coastguard Worker             mAtEOS = true;
1121*ec779b8eSAndroid Build Coastguard Worker             break;
1122*ec779b8eSAndroid Build Coastguard Worker         }
1123*ec779b8eSAndroid Build Coastguard Worker 
1124*ec779b8eSAndroid Build Coastguard Worker         default:
1125*ec779b8eSAndroid Build Coastguard Worker             break;
1126*ec779b8eSAndroid Build Coastguard Worker     }
1127*ec779b8eSAndroid Build Coastguard Worker 
1128*ec779b8eSAndroid Build Coastguard Worker     mLock.unlock();
1129*ec779b8eSAndroid Build Coastguard Worker     sendEvent(msg, ext1, ext2, in);
1130*ec779b8eSAndroid Build Coastguard Worker     mLock.lock();
1131*ec779b8eSAndroid Build Coastguard Worker }
1132*ec779b8eSAndroid Build Coastguard Worker 
notifySetDataSourceCompleted(status_t err)1133*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
1134*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
1135*ec779b8eSAndroid Build Coastguard Worker 
1136*ec779b8eSAndroid Build Coastguard Worker     CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
1137*ec779b8eSAndroid Build Coastguard Worker 
1138*ec779b8eSAndroid Build Coastguard Worker     mAsyncResult = err;
1139*ec779b8eSAndroid Build Coastguard Worker     mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
1140*ec779b8eSAndroid Build Coastguard Worker     mCondition.broadcast();
1141*ec779b8eSAndroid Build Coastguard Worker }
1142*ec779b8eSAndroid Build Coastguard Worker 
notifyPrepareCompleted(status_t err)1143*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
1144*ec779b8eSAndroid Build Coastguard Worker     ALOGV("notifyPrepareCompleted %d", err);
1145*ec779b8eSAndroid Build Coastguard Worker 
1146*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
1147*ec779b8eSAndroid Build Coastguard Worker 
1148*ec779b8eSAndroid Build Coastguard Worker     if (mState != STATE_PREPARING) {
1149*ec779b8eSAndroid Build Coastguard Worker         // We were preparing asynchronously when the client called
1150*ec779b8eSAndroid Build Coastguard Worker         // reset(), we sent a premature "prepared" notification and
1151*ec779b8eSAndroid Build Coastguard Worker         // then initiated the reset. This notification is stale.
1152*ec779b8eSAndroid Build Coastguard Worker         CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
1153*ec779b8eSAndroid Build Coastguard Worker         return;
1154*ec779b8eSAndroid Build Coastguard Worker     }
1155*ec779b8eSAndroid Build Coastguard Worker 
1156*ec779b8eSAndroid Build Coastguard Worker     CHECK_EQ(mState, STATE_PREPARING);
1157*ec779b8eSAndroid Build Coastguard Worker 
1158*ec779b8eSAndroid Build Coastguard Worker     mAsyncResult = err;
1159*ec779b8eSAndroid Build Coastguard Worker 
1160*ec779b8eSAndroid Build Coastguard Worker     if (err == OK) {
1161*ec779b8eSAndroid Build Coastguard Worker         // update state before notifying client, so that if client calls back into NuPlayerDriver
1162*ec779b8eSAndroid Build Coastguard Worker         // in response, NuPlayerDriver has the right state
1163*ec779b8eSAndroid Build Coastguard Worker         mState = STATE_PREPARED;
1164*ec779b8eSAndroid Build Coastguard Worker         if (mIsAsyncPrepare) {
1165*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_PREPARED);
1166*ec779b8eSAndroid Build Coastguard Worker         }
1167*ec779b8eSAndroid Build Coastguard Worker     } else {
1168*ec779b8eSAndroid Build Coastguard Worker         mState = STATE_UNPREPARED;
1169*ec779b8eSAndroid Build Coastguard Worker         if (mIsAsyncPrepare) {
1170*ec779b8eSAndroid Build Coastguard Worker             notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1171*ec779b8eSAndroid Build Coastguard Worker         }
1172*ec779b8eSAndroid Build Coastguard Worker     }
1173*ec779b8eSAndroid Build Coastguard Worker 
1174*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> meta = mPlayer->getFileMeta();
1175*ec779b8eSAndroid Build Coastguard Worker     int32_t loop;
1176*ec779b8eSAndroid Build Coastguard Worker     if (meta != NULL
1177*ec779b8eSAndroid Build Coastguard Worker             && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
1178*ec779b8eSAndroid Build Coastguard Worker         mAutoLoop = true;
1179*ec779b8eSAndroid Build Coastguard Worker     }
1180*ec779b8eSAndroid Build Coastguard Worker 
1181*ec779b8eSAndroid Build Coastguard Worker     mCondition.broadcast();
1182*ec779b8eSAndroid Build Coastguard Worker }
1183*ec779b8eSAndroid Build Coastguard Worker 
notifyFlagsChanged(uint32_t flags)1184*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
1185*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mLock);
1186*ec779b8eSAndroid Build Coastguard Worker 
1187*ec779b8eSAndroid Build Coastguard Worker     mPlayerFlags = flags;
1188*ec779b8eSAndroid Build Coastguard Worker }
1189*ec779b8eSAndroid Build Coastguard Worker 
1190*ec779b8eSAndroid Build Coastguard Worker // Modular DRM
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)1191*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
1192*ec779b8eSAndroid Build Coastguard Worker {
1193*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareDrm(%p) state: %d", this, mState);
1194*ec779b8eSAndroid Build Coastguard Worker 
1195*ec779b8eSAndroid Build Coastguard Worker     // leaving the state verification for mediaplayer.cpp
1196*ec779b8eSAndroid Build Coastguard Worker     status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
1197*ec779b8eSAndroid Build Coastguard Worker 
1198*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareDrm ret: %d", ret);
1199*ec779b8eSAndroid Build Coastguard Worker 
1200*ec779b8eSAndroid Build Coastguard Worker     return ret;
1201*ec779b8eSAndroid Build Coastguard Worker }
1202*ec779b8eSAndroid Build Coastguard Worker 
releaseDrm()1203*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::releaseDrm()
1204*ec779b8eSAndroid Build Coastguard Worker {
1205*ec779b8eSAndroid Build Coastguard Worker     ALOGV("releaseDrm(%p) state: %d", this, mState);
1206*ec779b8eSAndroid Build Coastguard Worker 
1207*ec779b8eSAndroid Build Coastguard Worker     // leaving the state verification for mediaplayer.cpp
1208*ec779b8eSAndroid Build Coastguard Worker     status_t ret = mPlayer->releaseDrm();
1209*ec779b8eSAndroid Build Coastguard Worker 
1210*ec779b8eSAndroid Build Coastguard Worker     ALOGV("releaseDrm ret: %d", ret);
1211*ec779b8eSAndroid Build Coastguard Worker 
1212*ec779b8eSAndroid Build Coastguard Worker     return ret;
1213*ec779b8eSAndroid Build Coastguard Worker }
1214*ec779b8eSAndroid Build Coastguard Worker 
stateString(State state)1215*ec779b8eSAndroid Build Coastguard Worker std::string NuPlayerDriver::stateString(State state) {
1216*ec779b8eSAndroid Build Coastguard Worker     const char *rval = NULL;
1217*ec779b8eSAndroid Build Coastguard Worker     char rawbuffer[16];  // allows "%d"
1218*ec779b8eSAndroid Build Coastguard Worker 
1219*ec779b8eSAndroid Build Coastguard Worker     switch (state) {
1220*ec779b8eSAndroid Build Coastguard Worker         case STATE_IDLE: rval = "IDLE"; break;
1221*ec779b8eSAndroid Build Coastguard Worker         case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1222*ec779b8eSAndroid Build Coastguard Worker         case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1223*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARING: rval = "PREPARING"; break;
1224*ec779b8eSAndroid Build Coastguard Worker         case STATE_PREPARED: rval = "PREPARED"; break;
1225*ec779b8eSAndroid Build Coastguard Worker         case STATE_RUNNING: rval = "RUNNING"; break;
1226*ec779b8eSAndroid Build Coastguard Worker         case STATE_PAUSED: rval = "PAUSED"; break;
1227*ec779b8eSAndroid Build Coastguard Worker         case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
1228*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED: rval = "STOPPED"; break;
1229*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
1230*ec779b8eSAndroid Build Coastguard Worker         case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
1231*ec779b8eSAndroid Build Coastguard Worker         default:
1232*ec779b8eSAndroid Build Coastguard Worker             // yes, this buffer is shared and vulnerable to races
1233*ec779b8eSAndroid Build Coastguard Worker             snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1234*ec779b8eSAndroid Build Coastguard Worker             rval = rawbuffer;
1235*ec779b8eSAndroid Build Coastguard Worker             break;
1236*ec779b8eSAndroid Build Coastguard Worker     }
1237*ec779b8eSAndroid Build Coastguard Worker 
1238*ec779b8eSAndroid Build Coastguard Worker     return rval;
1239*ec779b8eSAndroid Build Coastguard Worker }
1240*ec779b8eSAndroid Build Coastguard Worker 
1241*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
1242