blob: cf59717b65796b22068b011c10364819df59ae81 [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18// Proxy for media player implementations
19
20//#define LOG_NDEBUG 0
21#define LOG_TAG "MediaPlayerService"
22#include <utils/Log.h>
23
24#include <sys/types.h>
25#include <sys/stat.h>
Gloria Wang7cf180c2011-02-19 18:37:57 -080026#include <sys/time.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080027#include <dirent.h>
28#include <unistd.h>
29
30#include <string.h>
Mathias Agopian6f74b0c2009-06-03 17:32:49 -070031
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080032#include <cutils/atomic.h>
Nicolas Catania14d27472009-07-13 14:37:49 -070033#include <cutils/properties.h> // for property_get
Mathias Agopian6f74b0c2009-06-03 17:32:49 -070034
35#include <utils/misc.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080036
Mathias Agopian75624082009-05-19 19:08:10 -070037#include <binder/IPCThreadState.h>
38#include <binder/IServiceManager.h>
39#include <binder/MemoryHeapBase.h>
40#include <binder/MemoryBase.h>
Mathias Agopianb1e7cd12013-02-14 17:11:27 -080041#include <gui/Surface.h>
Nicolas Catania1d187f12009-05-12 23:25:55 -070042#include <utils/Errors.h> // for status_t
43#include <utils/String8.h>
Marco Nelissen10dbb8e2009-09-20 10:42:13 -070044#include <utils/SystemClock.h>
Nicolas Catania1d187f12009-05-12 23:25:55 -070045#include <utils/Vector.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080046
Jeff Brown2013a542012-09-04 21:38:42 -070047#include <media/IRemoteDisplay.h>
48#include <media/IRemoteDisplayClient.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080049#include <media/MediaPlayerInterface.h>
50#include <media/mediarecorder.h>
51#include <media/MediaMetadataRetrieverInterface.h>
nikoa64c8c72009-07-20 15:07:26 -070052#include <media/Metadata.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080053#include <media/AudioTrack.h>
James Dong8635b7b2011-03-14 17:01:38 -070054#include <media/MemoryLeakTrackUtil.h>
Eric Laurent9cb839a2011-09-27 09:48:56 -070055#include <media/stagefright/MediaErrors.h>
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +010056#include <media/stagefright/AudioPlayer.h>
57#include <media/stagefright/foundation/ADebug.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080058
Dima Zavin64760242011-05-11 14:15:23 -070059#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070060
Gloria Wang7cf180c2011-02-19 18:37:57 -080061#include <private/android_filesystem_config.h>
62
James Dong559bf282012-03-28 10:29:14 -070063#include "ActivityManager.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080064#include "MediaRecorderClient.h"
65#include "MediaPlayerService.h"
66#include "MetadataRetrieverClient.h"
John Grossman44a7e422012-06-21 17:29:24 -070067#include "MediaPlayerFactory.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080068
69#include "MidiFile.h"
Nicolas Catania14d27472009-07-13 14:37:49 -070070#include "TestPlayerStub.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070071#include "StagefrightPlayer.h"
Andreas Huberf9334412010-12-15 15:17:42 -080072#include "nuplayer/NuPlayerDriver.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070073
Andreas Huber20111aa2009-07-14 16:56:47 -070074#include <OMX.h>
Nicolas Catania14d27472009-07-13 14:37:49 -070075
Andreas Hubered3e3e02012-03-26 11:13:27 -070076#include "Crypto.h"
Jeff Tinkercc82dc62013-02-08 10:18:35 -080077#include "Drm.h"
Andreas Huber59451f82012-09-18 10:36:32 -070078#include "HDCP.h"
Andreas Huberb7319a72013-05-29 14:20:52 -070079#include "HTTPBase.h"
Andreas Huber35213f12012-08-29 11:41:50 -070080#include "RemoteDisplay.h"
Andreas Hubered3e3e02012-03-26 11:13:27 -070081
Wei Jia502c2f42017-07-13 17:47:56 -070082static const int kDumpLockRetries = 50;
83static const int kDumpLockSleepUs = 20000;
84
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070085namespace {
nikoa64c8c72009-07-20 15:07:26 -070086using android::media::Metadata;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070087using android::status_t;
88using android::OK;
89using android::BAD_VALUE;
90using android::NOT_ENOUGH_DATA;
91using android::Parcel;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070092
93// Max number of entries in the filter.
94const int kMaxFilterSize = 64; // I pulled that out of thin air.
95
nikoa64c8c72009-07-20 15:07:26 -070096// FIXME: Move all the metadata related function in the Metadata.cpp
nikod608a812009-07-16 16:39:53 -070097
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070098
99// Unmarshall a filter from a Parcel.
100// Filter format in a parcel:
101//
102// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
103// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104// | number of entries (n) |
105// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106// | metadata type 1 |
107// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108// | metadata type 2 |
109// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110// ....
111// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112// | metadata type n |
113// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114//
115// @param p Parcel that should start with a filter.
116// @param[out] filter On exit contains the list of metadata type to be
117// filtered.
118// @param[out] status On exit contains the status code to be returned.
119// @return true if the parcel starts with a valid filter.
120bool unmarshallFilter(const Parcel& p,
nikoa64c8c72009-07-20 15:07:26 -0700121 Metadata::Filter *filter,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700122 status_t *status)
123{
Nicolas Catania48290382009-07-10 13:53:06 -0700124 int32_t val;
125 if (p.readInt32(&val) != OK)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700126 {
Steve Block29357bc2012-01-06 19:20:56 +0000127 ALOGE("Failed to read filter's length");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700128 *status = NOT_ENOUGH_DATA;
129 return false;
130 }
131
Nicolas Catania48290382009-07-10 13:53:06 -0700132 if( val > kMaxFilterSize || val < 0)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700133 {
Steve Block29357bc2012-01-06 19:20:56 +0000134 ALOGE("Invalid filter len %d", val);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700135 *status = BAD_VALUE;
136 return false;
137 }
138
Nicolas Catania48290382009-07-10 13:53:06 -0700139 const size_t num = val;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700140
141 filter->clear();
Nicolas Catania48290382009-07-10 13:53:06 -0700142 filter->setCapacity(num);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700143
nikoa64c8c72009-07-20 15:07:26 -0700144 size_t size = num * sizeof(Metadata::Type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700145
Nicolas Catania48290382009-07-10 13:53:06 -0700146
147 if (p.dataAvail() < size)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700148 {
Steve Block29357bc2012-01-06 19:20:56 +0000149 ALOGE("Filter too short expected %d but got %d", size, p.dataAvail());
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700150 *status = NOT_ENOUGH_DATA;
151 return false;
152 }
153
nikoa64c8c72009-07-20 15:07:26 -0700154 const Metadata::Type *data =
155 static_cast<const Metadata::Type*>(p.readInplace(size));
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700156
Nicolas Catania48290382009-07-10 13:53:06 -0700157 if (NULL == data)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700158 {
Steve Block29357bc2012-01-06 19:20:56 +0000159 ALOGE("Filter had no data");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700160 *status = BAD_VALUE;
161 return false;
162 }
163
164 // TODO: The stl impl of vector would be more efficient here
165 // because it degenerates into a memcpy on pod types. Try to
166 // replace later or use stl::set.
Nicolas Catania48290382009-07-10 13:53:06 -0700167 for (size_t i = 0; i < num; ++i)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700168 {
Nicolas Catania48290382009-07-10 13:53:06 -0700169 filter->add(*data);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700170 ++data;
171 }
172 *status = OK;
173 return true;
174}
175
Nicolas Catania48290382009-07-10 13:53:06 -0700176// @param filter Of metadata type.
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700177// @param val To be searched.
178// @return true if a match was found.
nikoa64c8c72009-07-20 15:07:26 -0700179bool findMetadata(const Metadata::Filter& filter, const int32_t val)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700180{
181 // Deal with empty and ANY right away
182 if (filter.isEmpty()) return false;
nikoa64c8c72009-07-20 15:07:26 -0700183 if (filter[0] == Metadata::kAny) return true;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700184
Nicolas Catania48290382009-07-10 13:53:06 -0700185 return filter.indexOf(val) >= 0;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700186}
187
188} // anonymous namespace
189
190
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800191namespace android {
192
Dave Burked681bbb2011-08-30 14:39:17 +0100193static bool checkPermission(const char* permissionString) {
194#ifndef HAVE_ANDROID_OS
195 return true;
196#endif
197 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
198 bool ok = checkCallingPermission(String16(permissionString));
Steve Block29357bc2012-01-06 19:20:56 +0000199 if (!ok) ALOGE("Request requires %s", permissionString);
Dave Burked681bbb2011-08-30 14:39:17 +0100200 return ok;
201}
202
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800203// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800204/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
205/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
206
207void MediaPlayerService::instantiate() {
208 defaultServiceManager()->addService(
209 String16("media.player"), new MediaPlayerService());
210}
211
212MediaPlayerService::MediaPlayerService()
213{
Steve Block3856b092011-10-20 11:56:00 +0100214 ALOGV("MediaPlayerService created");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800215 mNextConnId = 1;
Gloria Wang9ee159b2011-02-24 14:51:45 -0800216
217 mBatteryAudio.refCount = 0;
218 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
219 mBatteryAudio.deviceOn[i] = 0;
220 mBatteryAudio.lastTime[i] = 0;
221 mBatteryAudio.totalTime[i] = 0;
222 }
223 // speaker is on by default
224 mBatteryAudio.deviceOn[SPEAKER] = 1;
John Grossman44a7e422012-06-21 17:29:24 -0700225
226 MediaPlayerFactory::registerBuiltinFactories();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800227}
228
229MediaPlayerService::~MediaPlayerService()
230{
Steve Block3856b092011-10-20 11:56:00 +0100231 ALOGV("MediaPlayerService destroyed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800232}
233
Glenn Kastenf37971f2012-02-03 11:06:53 -0800234sp<IMediaRecorder> MediaPlayerService::createMediaRecorder()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800235{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800236 pid_t pid = IPCThreadState::self()->getCallingPid();
Gloria Wangdac6a312009-10-29 15:46:37 -0700237 sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
238 wp<MediaRecorderClient> w = recorder;
239 Mutex::Autolock lock(mLock);
240 mMediaRecorderClients.add(w);
Steve Block3856b092011-10-20 11:56:00 +0100241 ALOGV("Create new media recorder client from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800242 return recorder;
243}
244
Gloria Wangdac6a312009-10-29 15:46:37 -0700245void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
246{
247 Mutex::Autolock lock(mLock);
248 mMediaRecorderClients.remove(client);
Steve Block3856b092011-10-20 11:56:00 +0100249 ALOGV("Delete media recorder client");
Gloria Wangdac6a312009-10-29 15:46:37 -0700250}
251
Glenn Kastenf37971f2012-02-03 11:06:53 -0800252sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800253{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800254 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800255 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
Steve Block3856b092011-10-20 11:56:00 +0100256 ALOGV("Create new media retriever from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800257 return retriever;
258}
259
Glenn Kastenf37971f2012-02-03 11:06:53 -0800260sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
Dave Burked681bbb2011-08-30 14:39:17 +0100261 int audioSessionId)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800262{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800263 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800264 int32_t connId = android_atomic_inc(&mNextConnId);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700265
266 sp<Client> c = new Client(
267 this, pid, connId, client, audioSessionId,
268 IPCThreadState::self()->getCallingUid());
269
Steve Block3856b092011-10-20 11:56:00 +0100270 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
Dave Burked681bbb2011-08-30 14:39:17 +0100271 IPCThreadState::self()->getCallingUid());
272
273 wp<Client> w = c;
274 {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800275 Mutex::Autolock lock(mLock);
276 mClients.add(w);
277 }
Andreas Hubere2b10282010-11-23 11:41:34 -0800278 return c;
279}
280
Andreas Huber318ad9c2009-10-15 13:46:54 -0700281sp<IOMX> MediaPlayerService::getOMX() {
282 Mutex::Autolock autoLock(mLock);
283
284 if (mOMX.get() == NULL) {
285 mOMX = new OMX;
286 }
287
288 return mOMX;
Andreas Huber20111aa2009-07-14 16:56:47 -0700289}
290
Andreas Hubered3e3e02012-03-26 11:13:27 -0700291sp<ICrypto> MediaPlayerService::makeCrypto() {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700292 return new Crypto;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700293}
294
Jeff Tinkercc82dc62013-02-08 10:18:35 -0800295sp<IDrm> MediaPlayerService::makeDrm() {
296 return new Drm;
297}
298
Andreas Huber279dcd82013-01-30 10:41:25 -0800299sp<IHDCP> MediaPlayerService::makeHDCP(bool createEncryptionModule) {
300 return new HDCP(createEncryptionModule);
Andreas Huber59451f82012-09-18 10:36:32 -0700301}
302
Jeff Brown2013a542012-09-04 21:38:42 -0700303sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
304 const sp<IRemoteDisplayClient>& client, const String8& iface) {
Jeff Brownaba33d52012-09-07 17:38:58 -0700305 if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
306 return NULL;
307 }
308
Jeff Brownced24b32012-09-05 17:48:03 -0700309 return new RemoteDisplay(client, iface.string());
Jeff Brown2013a542012-09-04 21:38:42 -0700310}
311
Andreas Huberb7319a72013-05-29 14:20:52 -0700312status_t MediaPlayerService::updateProxyConfig(
313 const char *host, int32_t port, const char *exclusionList) {
314 return HTTPBase::UpdateProxyConfig(host, port, exclusionList);
315}
316
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800317status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
318{
319 const size_t SIZE = 256;
320 char buffer[SIZE];
321 String8 result;
322
323 result.append(" AudioCache\n");
324 if (mHeap != 0) {
Eric Laurent3d00aa62013-09-24 09:53:27 -0700325 snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d)\n",
326 mHeap->getBase(), mHeap->getSize(), mHeap->getFlags());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800327 result.append(buffer);
328 }
Scott Fan7d409692013-04-28 10:13:54 +0800329 snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800330 mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
331 result.append(buffer);
332 snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
333 mSampleRate, mSize, mError, mCommandComplete?"true":"false");
334 result.append(buffer);
335 ::write(fd, result.string(), result.size());
336 return NO_ERROR;
337}
338
339status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
340{
341 const size_t SIZE = 256;
342 char buffer[SIZE];
343 String8 result;
344
345 result.append(" AudioOutput\n");
346 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
347 mStreamType, mLeftVolume, mRightVolume);
348 result.append(buffer);
349 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Eric Laurentdb354e52012-03-05 17:27:11 -0800350 mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800351 result.append(buffer);
Eric Laurent2beeb502010-07-16 07:43:46 -0700352 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
353 mAuxEffectId, mSendLevel);
354 result.append(buffer);
355
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800356 ::write(fd, result.string(), result.size());
357 if (mTrack != 0) {
358 mTrack->dump(fd, args);
359 }
360 return NO_ERROR;
361}
362
363status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
364{
365 const size_t SIZE = 256;
366 char buffer[SIZE];
367 String8 result;
368 result.append(" Client\n");
369 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
370 mPid, mConnId, mStatus, mLoop?"true": "false");
371 result.append(buffer);
Wei Jia502c2f42017-07-13 17:47:56 -0700372
373 sp<MediaPlayerBase> p;
374 sp<AudioOutput> audioOutput;
375 bool locked = false;
376 for (int i = 0; i < kDumpLockRetries; ++i) {
377 if (mLock.tryLock() == NO_ERROR) {
378 locked = true;
379 break;
380 }
381 usleep(kDumpLockSleepUs);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700382 }
Wei Jia502c2f42017-07-13 17:47:56 -0700383
384 if (locked) {
385 p = mPlayer;
386 audioOutput = mAudioOutput;
387 mLock.unlock();
388 } else {
389 result.append(" lock is taken, no dump from player and audio output\n");
390 }
391 write(fd, result.string(), result.size());
392
393 if (p != NULL) {
394 p->dump(fd, args);
395 }
396 if (audioOutput != 0) {
397 audioOutput->dump(fd, args);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800398 }
399 write(fd, "\n", 1);
400 return NO_ERROR;
401}
402
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800403status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
404{
405 const size_t SIZE = 256;
406 char buffer[SIZE];
407 String8 result;
408 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
409 snprintf(buffer, SIZE, "Permission Denial: "
410 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
411 IPCThreadState::self()->getCallingPid(),
412 IPCThreadState::self()->getCallingUid());
413 result.append(buffer);
414 } else {
415 Mutex::Autolock lock(mLock);
416 for (int i = 0, n = mClients.size(); i < n; ++i) {
417 sp<Client> c = mClients[i].promote();
418 if (c != 0) c->dump(fd, args);
419 }
James Dongb9141222010-07-08 11:16:11 -0700420 if (mMediaRecorderClients.size() == 0) {
421 result.append(" No media recorder client\n\n");
422 } else {
423 for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
424 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
James Donge579e282011-10-18 22:29:20 -0700425 if (c != 0) {
426 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
427 result.append(buffer);
428 write(fd, result.string(), result.size());
429 result = "\n";
430 c->dump(fd, args);
431 }
James Dongb9141222010-07-08 11:16:11 -0700432 }
Gloria Wangdac6a312009-10-29 15:46:37 -0700433 }
434
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800435 result.append(" Files opened and/or mapped:\n");
Glenn Kasten0512ab52011-05-04 17:58:57 -0700436 snprintf(buffer, SIZE, "/proc/%d/maps", gettid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800437 FILE *f = fopen(buffer, "r");
438 if (f) {
439 while (!feof(f)) {
440 fgets(buffer, SIZE, f);
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700441 if (strstr(buffer, " /storage/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800442 strstr(buffer, " /system/sounds/") ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700443 strstr(buffer, " /data/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800444 strstr(buffer, " /system/media/")) {
445 result.append(" ");
446 result.append(buffer);
447 }
448 }
449 fclose(f);
450 } else {
451 result.append("couldn't open ");
452 result.append(buffer);
453 result.append("\n");
454 }
455
Glenn Kasten0512ab52011-05-04 17:58:57 -0700456 snprintf(buffer, SIZE, "/proc/%d/fd", gettid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800457 DIR *d = opendir(buffer);
458 if (d) {
459 struct dirent *ent;
460 while((ent = readdir(d)) != NULL) {
461 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
Glenn Kasten0512ab52011-05-04 17:58:57 -0700462 snprintf(buffer, SIZE, "/proc/%d/fd/%s", gettid(), ent->d_name);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800463 struct stat s;
464 if (lstat(buffer, &s) == 0) {
465 if ((s.st_mode & S_IFMT) == S_IFLNK) {
466 char linkto[256];
467 int len = readlink(buffer, linkto, sizeof(linkto));
468 if(len > 0) {
469 if(len > 255) {
470 linkto[252] = '.';
471 linkto[253] = '.';
472 linkto[254] = '.';
473 linkto[255] = 0;
474 } else {
475 linkto[len] = 0;
476 }
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700477 if (strstr(linkto, "/storage/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800478 strstr(linkto, "/system/sounds/") == linkto ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700479 strstr(linkto, "/data/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800480 strstr(linkto, "/system/media/") == linkto) {
481 result.append(" ");
482 result.append(buffer);
483 result.append(" -> ");
484 result.append(linkto);
485 result.append("\n");
486 }
487 }
488 } else {
489 result.append(" unexpected type for ");
490 result.append(buffer);
491 result.append("\n");
492 }
493 }
494 }
495 }
496 closedir(d);
497 } else {
498 result.append("couldn't open ");
499 result.append(buffer);
500 result.append("\n");
501 }
502
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800503 bool dumpMem = false;
504 for (size_t i = 0; i < args.size(); i++) {
505 if (args[i] == String16("-m")) {
506 dumpMem = true;
507 }
508 }
509 if (dumpMem) {
James Dong8635b7b2011-03-14 17:01:38 -0700510 dumpMemoryAddresses(fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800511 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800512 }
513 write(fd, result.string(), result.size());
514 return NO_ERROR;
515}
516
517void MediaPlayerService::removeClient(wp<Client> client)
518{
519 Mutex::Autolock lock(mLock);
520 mClients.remove(client);
521}
522
Robert Shihc159a5a2016-08-16 16:50:54 -0700523bool MediaPlayerService::hasClient(wp<Client> client)
524{
525 Mutex::Autolock lock(mLock);
526 return mClients.indexOf(client) != NAME_NOT_FOUND;
527}
528
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700529MediaPlayerService::Client::Client(
530 const sp<MediaPlayerService>& service, pid_t pid,
531 int32_t connId, const sp<IMediaPlayerClient>& client,
532 int audioSessionId, uid_t uid)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800533{
Steve Block3856b092011-10-20 11:56:00 +0100534 ALOGV("Client(%d) constructor", connId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800535 mPid = pid;
536 mConnId = connId;
537 mService = service;
538 mClient = client;
539 mLoop = false;
540 mStatus = NO_INIT;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700541 mAudioSessionId = audioSessionId;
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700542 mUID = uid;
John Grossmanc795b642012-02-22 15:38:35 -0800543 mRetransmitEndpointValid = false;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700544
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800545#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000546 ALOGD("create Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800547 mAntagonizer = new Antagonizer(notify, this);
548#endif
549}
550
551MediaPlayerService::Client::~Client()
552{
Steve Block3856b092011-10-20 11:56:00 +0100553 ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
Wei Jia502c2f42017-07-13 17:47:56 -0700554 {
555 Mutex::Autolock l(mLock);
556 mAudioOutput.clear();
557 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800558 wp<Client> client(this);
559 disconnect();
560 mService->removeClient(client);
561}
562
563void MediaPlayerService::Client::disconnect()
564{
Steve Block3856b092011-10-20 11:56:00 +0100565 ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800566 // grab local reference and clear main reference to prevent future
567 // access to object
568 sp<MediaPlayerBase> p;
569 {
570 Mutex::Autolock l(mLock);
571 p = mPlayer;
beanzdcfefde2012-11-05 09:51:43 +0800572 mClient.clear();
Wei Jia502c2f42017-07-13 17:47:56 -0700573 mPlayer.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800574 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700575
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800576 // clear the notification to prevent callbacks to dead client
577 // and reset the player. We assume the player will serialize
578 // access to itself if necessary.
579 if (p != 0) {
580 p->setNotifyCallback(0, 0);
581#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000582 ALOGD("kill Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800583 mAntagonizer->kill();
584#endif
585 p->reset();
586 }
587
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700588 disconnectNativeWindow();
589
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800590 IPCThreadState::self()->flushCommands();
591}
592
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800593sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
594{
595 // determine if we have the right player type
Wei Jia502c2f42017-07-13 17:47:56 -0700596 sp<MediaPlayerBase> p = getPlayer();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800597 if ((p != NULL) && (p->playerType() != playerType)) {
Steve Block3856b092011-10-20 11:56:00 +0100598 ALOGV("delete player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800599 p.clear();
600 }
601 if (p == NULL) {
John Grossman44a7e422012-06-21 17:29:24 -0700602 p = MediaPlayerFactory::createPlayer(playerType, this, notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800603 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700604
Jason Simmonsdb29e522011-08-12 13:46:55 -0700605 if (p != NULL) {
606 p->setUID(mUID);
607 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700608
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800609 return p;
610}
611
John Grossmanc795b642012-02-22 15:38:35 -0800612sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
613 player_type playerType)
614{
615 ALOGV("player type = %d", playerType);
616
617 // create the right type of player
618 sp<MediaPlayerBase> p = createPlayer(playerType);
619 if (p == NULL) {
620 return p;
621 }
622
623 if (!p->hardwareOutput()) {
Marco Nelissen9cae2172013-01-14 14:12:05 -0800624 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid());
John Grossmanc795b642012-02-22 15:38:35 -0800625 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
626 }
627
628 return p;
629}
630
631void MediaPlayerService::Client::setDataSource_post(
632 const sp<MediaPlayerBase>& p,
633 status_t status)
634{
635 ALOGV(" setDataSource");
636 mStatus = status;
637 if (mStatus != OK) {
638 ALOGE(" error: %d", mStatus);
639 return;
640 }
641
642 // Set the re-transmission endpoint if one was chosen.
643 if (mRetransmitEndpointValid) {
644 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
645 if (mStatus != NO_ERROR) {
646 ALOGE("setRetransmitEndpoint error: %d", mStatus);
647 }
648 }
649
650 if (mStatus == OK) {
Wei Jia502c2f42017-07-13 17:47:56 -0700651 Mutex::Autolock l(mLock);
John Grossmanc795b642012-02-22 15:38:35 -0800652 mPlayer = p;
653 }
654}
655
Andreas Huber2db84552010-01-28 11:19:57 -0800656status_t MediaPlayerService::Client::setDataSource(
657 const char *url, const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800658{
Steve Block3856b092011-10-20 11:56:00 +0100659 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800660 if (url == NULL)
661 return UNKNOWN_ERROR;
662
Dave Burked681bbb2011-08-30 14:39:17 +0100663 if ((strncmp(url, "http://", 7) == 0) ||
664 (strncmp(url, "https://", 8) == 0) ||
665 (strncmp(url, "rtsp://", 7) == 0)) {
666 if (!checkPermission("android.permission.INTERNET")) {
667 return PERMISSION_DENIED;
668 }
669 }
670
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800671 if (strncmp(url, "content://", 10) == 0) {
672 // get a filedescriptor for the content Uri and
673 // pass it to the setDataSource(fd) method
674
675 String16 url16(url);
676 int fd = android::openContentProviderFile(url16);
677 if (fd < 0)
678 {
Steve Block29357bc2012-01-06 19:20:56 +0000679 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800680 return UNKNOWN_ERROR;
681 }
682 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
683 close(fd);
684 return mStatus;
685 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700686 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800687 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
688 if (p == NULL) {
689 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800690 }
691
John Grossmanc795b642012-02-22 15:38:35 -0800692 setDataSource_post(p, p->setDataSource(url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800693 return mStatus;
694 }
695}
696
697status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
698{
Steve Block3856b092011-10-20 11:56:00 +0100699 ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800700 struct stat sb;
701 int ret = fstat(fd, &sb);
702 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000703 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800704 return UNKNOWN_ERROR;
705 }
706
Steve Block3856b092011-10-20 11:56:00 +0100707 ALOGV("st_dev = %llu", sb.st_dev);
708 ALOGV("st_mode = %u", sb.st_mode);
709 ALOGV("st_uid = %lu", sb.st_uid);
710 ALOGV("st_gid = %lu", sb.st_gid);
711 ALOGV("st_size = %llu", sb.st_size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800712
713 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000714 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800715 ::close(fd);
716 return UNKNOWN_ERROR;
717 }
718 if (offset + length > sb.st_size) {
719 length = sb.st_size - offset;
Steve Block3856b092011-10-20 11:56:00 +0100720 ALOGV("calculated length = %lld", length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800721 }
722
John Grossman44a7e422012-06-21 17:29:24 -0700723 player_type playerType = MediaPlayerFactory::getPlayerType(this,
724 fd,
725 offset,
726 length);
John Grossmanc795b642012-02-22 15:38:35 -0800727 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
728 if (p == NULL) {
729 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800730 }
731
732 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800733 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800734 return mStatus;
735}
736
Andreas Hubere2b10282010-11-23 11:41:34 -0800737status_t MediaPlayerService::Client::setDataSource(
738 const sp<IStreamSource> &source) {
739 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700740 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800741 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800742 if (p == NULL) {
743 return NO_INIT;
744 }
745
Andreas Hubere2b10282010-11-23 11:41:34 -0800746 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800747 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800748 return mStatus;
749}
750
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700751void MediaPlayerService::Client::disconnectNativeWindow() {
752 if (mConnectedWindow != NULL) {
753 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
754 NATIVE_WINDOW_API_MEDIA);
755
756 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000757 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700758 strerror(-err), err);
759 }
760 }
761 mConnectedWindow.clear();
762}
763
Glenn Kasten11731182011-02-08 17:26:17 -0800764status_t MediaPlayerService::Client::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800765 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800766{
Andy McFadden484566c2012-12-18 09:46:54 -0800767 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800768 sp<MediaPlayerBase> p = getPlayer();
769 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700770
Andy McFadden484566c2012-12-18 09:46:54 -0800771 sp<IBinder> binder(bufferProducer == NULL ? NULL :
772 bufferProducer->asBinder());
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700773 if (mConnectedWindowBinder == binder) {
774 return OK;
775 }
776
777 sp<ANativeWindow> anw;
Andy McFadden484566c2012-12-18 09:46:54 -0800778 if (bufferProducer != NULL) {
Marco Nelissenee08f7e2013-09-16 13:30:01 -0700779 anw = new Surface(bufferProducer, true /* controlledByApp */);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700780 status_t err = native_window_api_connect(anw.get(),
781 NATIVE_WINDOW_API_MEDIA);
782
783 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000784 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700785 // Note that we must do the reset before disconnecting from the ANW.
786 // Otherwise queue/dequeue calls could be made on the disconnected
787 // ANW, which may result in errors.
788 reset();
789
790 disconnectNativeWindow();
791
792 return err;
793 }
794 }
795
Andy McFadden484566c2012-12-18 09:46:54 -0800796 // Note that we must set the player's new GraphicBufferProducer before
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700797 // disconnecting the old one. Otherwise queue/dequeue calls could be made
798 // on the disconnected ANW, which may result in errors.
Andy McFadden484566c2012-12-18 09:46:54 -0800799 status_t err = p->setVideoSurfaceTexture(bufferProducer);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700800
801 disconnectNativeWindow();
802
803 mConnectedWindow = anw;
804
805 if (err == OK) {
806 mConnectedWindowBinder = binder;
807 } else {
808 disconnectNativeWindow();
809 }
810
811 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800812}
813
Nicolas Catania1d187f12009-05-12 23:25:55 -0700814status_t MediaPlayerService::Client::invoke(const Parcel& request,
815 Parcel *reply)
816{
817 sp<MediaPlayerBase> p = getPlayer();
818 if (p == NULL) return UNKNOWN_ERROR;
819 return p->invoke(request, reply);
820}
821
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700822// This call doesn't need to access the native player.
823status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
824{
825 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700826 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700827
Nicolas Catania48290382009-07-10 13:53:06 -0700828 if (unmarshallFilter(filter, &allow, &status) &&
829 unmarshallFilter(filter, &drop, &status)) {
830 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700831
832 mMetadataAllow = allow;
833 mMetadataDrop = drop;
834 }
835 return status;
836}
837
Nicolas Catania48290382009-07-10 13:53:06 -0700838status_t MediaPlayerService::Client::getMetadata(
839 bool update_only, bool apply_filter, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700840{
nikoa64c8c72009-07-20 15:07:26 -0700841 sp<MediaPlayerBase> player = getPlayer();
842 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700843
nikod608a812009-07-16 16:39:53 -0700844 status_t status;
845 // Placeholder for the return code, updated by the caller.
846 reply->writeInt32(-1);
847
nikoa64c8c72009-07-20 15:07:26 -0700848 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700849
850 // We don't block notifications while we fetch the data. We clear
851 // mMetadataUpdated first so we don't lose notifications happening
852 // during the rest of this call.
853 {
854 Mutex::Autolock lock(mLock);
855 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700856 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700857 }
858 mMetadataUpdated.clear();
859 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700860
nikoa64c8c72009-07-20 15:07:26 -0700861 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700862
nikoa64c8c72009-07-20 15:07:26 -0700863 metadata.appendHeader();
864 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700865
866 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700867 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000868 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700869 return status;
870 }
871
872 // FIXME: Implement filtering on the result. Not critical since
873 // filtering takes place on the update notifications already. This
874 // would be when all the metadata are fetch and a filter is set.
875
nikod608a812009-07-16 16:39:53 -0700876 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700877 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700878 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700879}
880
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800881status_t MediaPlayerService::Client::prepareAsync()
882{
Steve Block3856b092011-10-20 11:56:00 +0100883 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800884 sp<MediaPlayerBase> p = getPlayer();
885 if (p == 0) return UNKNOWN_ERROR;
886 status_t ret = p->prepareAsync();
887#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000888 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800889 if (ret == NO_ERROR) mAntagonizer->start();
890#endif
891 return ret;
892}
893
894status_t MediaPlayerService::Client::start()
895{
Steve Block3856b092011-10-20 11:56:00 +0100896 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800897 sp<MediaPlayerBase> p = getPlayer();
898 if (p == 0) return UNKNOWN_ERROR;
899 p->setLooping(mLoop);
900 return p->start();
901}
902
903status_t MediaPlayerService::Client::stop()
904{
Steve Block3856b092011-10-20 11:56:00 +0100905 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800906 sp<MediaPlayerBase> p = getPlayer();
907 if (p == 0) return UNKNOWN_ERROR;
908 return p->stop();
909}
910
911status_t MediaPlayerService::Client::pause()
912{
Steve Block3856b092011-10-20 11:56:00 +0100913 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800914 sp<MediaPlayerBase> p = getPlayer();
915 if (p == 0) return UNKNOWN_ERROR;
916 return p->pause();
917}
918
919status_t MediaPlayerService::Client::isPlaying(bool* state)
920{
921 *state = false;
922 sp<MediaPlayerBase> p = getPlayer();
923 if (p == 0) return UNKNOWN_ERROR;
924 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +0100925 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800926 return NO_ERROR;
927}
928
929status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
930{
Steve Block3856b092011-10-20 11:56:00 +0100931 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800932 sp<MediaPlayerBase> p = getPlayer();
933 if (p == 0) return UNKNOWN_ERROR;
934 status_t ret = p->getCurrentPosition(msec);
935 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +0100936 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800937 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000938 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800939 }
940 return ret;
941}
942
943status_t MediaPlayerService::Client::getDuration(int *msec)
944{
Steve Block3856b092011-10-20 11:56:00 +0100945 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800946 sp<MediaPlayerBase> p = getPlayer();
947 if (p == 0) return UNKNOWN_ERROR;
948 status_t ret = p->getDuration(msec);
949 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +0100950 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800951 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000952 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800953 }
954 return ret;
955}
956
Marco Nelissen6b74d672012-02-28 16:07:44 -0800957status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
958 ALOGV("setNextPlayer");
959 Mutex::Autolock l(mLock);
960 sp<Client> c = static_cast<Client*>(player.get());
Wei Jia28284122016-08-30 13:49:06 -0700961 if (c != NULL && !mService->hasClient(c)) {
Robert Shihc159a5a2016-08-16 16:50:54 -0700962 return BAD_VALUE;
963 }
964
Marco Nelissen6b74d672012-02-28 16:07:44 -0800965 mNextClient = c;
John Grossman5f7e55e2012-08-24 14:47:25 -0700966
967 if (c != NULL) {
968 if (mAudioOutput != NULL) {
969 mAudioOutput->setNextOutput(c->mAudioOutput);
970 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
971 ALOGE("no current audio output");
972 }
973
974 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
975 mPlayer->setNextPlayer(mNextClient->getPlayer());
976 }
Marco Nelissen6b74d672012-02-28 16:07:44 -0800977 }
John Grossman5f7e55e2012-08-24 14:47:25 -0700978
Marco Nelissen6b74d672012-02-28 16:07:44 -0800979 return OK;
980}
981
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800982status_t MediaPlayerService::Client::seekTo(int msec)
983{
Steve Block3856b092011-10-20 11:56:00 +0100984 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800985 sp<MediaPlayerBase> p = getPlayer();
986 if (p == 0) return UNKNOWN_ERROR;
987 return p->seekTo(msec);
988}
989
990status_t MediaPlayerService::Client::reset()
991{
Steve Block3856b092011-10-20 11:56:00 +0100992 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -0800993 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800994 sp<MediaPlayerBase> p = getPlayer();
995 if (p == 0) return UNKNOWN_ERROR;
996 return p->reset();
997}
998
Glenn Kastenfff6d712012-01-12 16:38:12 -0800999status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001000{
Steve Block3856b092011-10-20 11:56:00 +01001001 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001002 // TODO: for hardware output, call player instead
1003 Mutex::Autolock l(mLock);
1004 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1005 return NO_ERROR;
1006}
1007
1008status_t MediaPlayerService::Client::setLooping(int loop)
1009{
Steve Block3856b092011-10-20 11:56:00 +01001010 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001011 mLoop = loop;
1012 sp<MediaPlayerBase> p = getPlayer();
1013 if (p != 0) return p->setLooping(loop);
1014 return NO_ERROR;
1015}
1016
1017status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1018{
Steve Block3856b092011-10-20 11:56:00 +01001019 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -08001020
1021 // for hardware output, call player instead
1022 sp<MediaPlayerBase> p = getPlayer();
1023 {
1024 Mutex::Autolock l(mLock);
1025 if (p != 0 && p->hardwareOutput()) {
1026 MediaPlayerHWInterface* hwp =
1027 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1028 return hwp->setVolume(leftVolume, rightVolume);
1029 } else {
1030 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1031 return NO_ERROR;
1032 }
1033 }
1034
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001035 return NO_ERROR;
1036}
1037
Eric Laurent2beeb502010-07-16 07:43:46 -07001038status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1039{
Steve Block3856b092011-10-20 11:56:00 +01001040 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001041 Mutex::Autolock l(mLock);
1042 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1043 return NO_ERROR;
1044}
1045
1046status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1047{
Steve Block3856b092011-10-20 11:56:00 +01001048 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001049 Mutex::Autolock l(mLock);
1050 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1051 return NO_ERROR;
1052}
Nicolas Catania48290382009-07-10 13:53:06 -07001053
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001054status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001055 ALOGV("[%d] setParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001056 sp<MediaPlayerBase> p = getPlayer();
1057 if (p == 0) return UNKNOWN_ERROR;
1058 return p->setParameter(key, request);
1059}
1060
1061status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001062 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001063 sp<MediaPlayerBase> p = getPlayer();
1064 if (p == 0) return UNKNOWN_ERROR;
1065 return p->getParameter(key, reply);
1066}
1067
John Grossmanc795b642012-02-22 15:38:35 -08001068status_t MediaPlayerService::Client::setRetransmitEndpoint(
1069 const struct sockaddr_in* endpoint) {
1070
1071 if (NULL != endpoint) {
1072 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1073 uint16_t p = ntohs(endpoint->sin_port);
1074 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1075 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1076 } else {
1077 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1078 }
1079
1080 sp<MediaPlayerBase> p = getPlayer();
1081
1082 // Right now, the only valid time to set a retransmit endpoint is before
1083 // player selection has been made (since the presence or absence of a
1084 // retransmit endpoint is going to determine which player is selected during
1085 // setDataSource).
1086 if (p != 0) return INVALID_OPERATION;
1087
1088 if (NULL != endpoint) {
1089 mRetransmitEndpoint = *endpoint;
1090 mRetransmitEndpointValid = true;
1091 } else {
1092 mRetransmitEndpointValid = false;
1093 }
1094
1095 return NO_ERROR;
1096}
1097
John Grossman44a7e422012-06-21 17:29:24 -07001098status_t MediaPlayerService::Client::getRetransmitEndpoint(
1099 struct sockaddr_in* endpoint)
1100{
1101 if (NULL == endpoint)
1102 return BAD_VALUE;
1103
1104 sp<MediaPlayerBase> p = getPlayer();
1105
1106 if (p != NULL)
1107 return p->getRetransmitEndpoint(endpoint);
1108
1109 if (!mRetransmitEndpointValid)
1110 return NO_INIT;
1111
1112 *endpoint = mRetransmitEndpoint;
1113
1114 return NO_ERROR;
1115}
1116
Gloria Wangb483c472011-04-11 17:23:27 -07001117void MediaPlayerService::Client::notify(
1118 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001119{
1120 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001121 if (client == NULL) {
1122 return;
1123 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001124
James Dongb8a98252012-08-26 16:13:03 -07001125 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001126 {
1127 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001128 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001129 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001130 if (client->mAudioOutput != NULL)
1131 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001132 client->mNextClient->start();
1133 client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1134 }
1135 }
1136
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001137 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001138 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001139 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001140
1141 if(client->shouldDropMetadata(metadata_type)) {
1142 return;
1143 }
1144
1145 // Update the list of metadata that have changed. getMetadata
1146 // also access mMetadataUpdated and clears it.
1147 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001148 }
James Dongb8a98252012-08-26 16:13:03 -07001149
1150 if (c != NULL) {
1151 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1152 c->notify(msg, ext1, ext2, obj);
1153 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001154}
1155
Nicolas Catania48290382009-07-10 13:53:06 -07001156
nikoa64c8c72009-07-20 15:07:26 -07001157bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001158{
Nicolas Catania48290382009-07-10 13:53:06 -07001159 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001160
Nicolas Catania48290382009-07-10 13:53:06 -07001161 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001162 return true;
1163 }
1164
Nicolas Catania48290382009-07-10 13:53:06 -07001165 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001166 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001167 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001168 return true;
1169 }
1170}
1171
Nicolas Catania48290382009-07-10 13:53:06 -07001172
nikoa64c8c72009-07-20 15:07:26 -07001173void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001174 Mutex::Autolock lock(mLock);
1175 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1176 mMetadataUpdated.add(metadata_type);
1177 }
1178}
1179
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001180#if CALLBACK_ANTAGONIZER
1181const int Antagonizer::interval = 10000; // 10 msecs
1182
1183Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1184 mExit(false), mActive(false), mClient(client), mCb(cb)
1185{
1186 createThread(callbackThread, this);
1187}
1188
1189void Antagonizer::kill()
1190{
1191 Mutex::Autolock _l(mLock);
1192 mActive = false;
1193 mExit = true;
1194 mCondition.wait(mLock);
1195}
1196
1197int Antagonizer::callbackThread(void* user)
1198{
Steve Blockb8a80522011-12-20 16:23:08 +00001199 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001200 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1201 while (!p->mExit) {
1202 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001203 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001204 p->mCb(p->mClient, 0, 0, 0);
1205 }
1206 usleep(interval);
1207 }
1208 Mutex::Autolock _l(p->mLock);
1209 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001210 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001211 return 0;
1212}
1213#endif
1214
Eric Laurent3d00aa62013-09-24 09:53:27 -07001215status_t MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels,
1216 audio_format_t* pFormat,
1217 const sp<IMemoryHeap>& heap, size_t *pSize)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001218{
Steve Block3856b092011-10-20 11:56:00 +01001219 ALOGV("decode(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001220 sp<MediaPlayerBase> player;
Eric Laurent3d00aa62013-09-24 09:53:27 -07001221 status_t status = BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001222
1223 // Protect our precious, precious DRMd ringtones by only allowing
1224 // decoding of http, but not filesystem paths or content Uris.
1225 // If the application wants to decode those, it should open a
1226 // filedescriptor for them and use that.
1227 if (url != NULL && strncmp(url, "http://", 7) != 0) {
Steve Blockb8a80522011-12-20 16:23:08 +00001228 ALOGD("Can't decode %s by path, use filedescriptor instead", url);
Eric Laurent3d00aa62013-09-24 09:53:27 -07001229 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001230 }
1231
John Grossman44a7e422012-06-21 17:29:24 -07001232 player_type playerType =
1233 MediaPlayerFactory::getPlayerType(NULL /* client */, url);
Steve Block3856b092011-10-20 11:56:00 +01001234 ALOGV("player type = %d", playerType);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001235
1236 // create the right type of player
Eric Laurent3d00aa62013-09-24 09:53:27 -07001237 sp<AudioCache> cache = new AudioCache(heap);
John Grossman44a7e422012-06-21 17:29:24 -07001238 player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001239 if (player == NULL) goto Exit;
1240 if (player->hardwareOutput()) goto Exit;
1241
1242 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1243
1244 // set data source
1245 if (player->setDataSource(url) != NO_ERROR) goto Exit;
1246
Steve Block3856b092011-10-20 11:56:00 +01001247 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001248 player->prepareAsync();
1249
Steve Block3856b092011-10-20 11:56:00 +01001250 ALOGV("wait for prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001251 if (cache->wait() != NO_ERROR) goto Exit;
1252
Steve Block3856b092011-10-20 11:56:00 +01001253 ALOGV("start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001254 player->start();
1255
Steve Block3856b092011-10-20 11:56:00 +01001256 ALOGV("wait for playback complete");
Eric Laurent9cb839a2011-09-27 09:48:56 -07001257 cache->wait();
1258 // in case of error, return what was successfully decoded.
1259 if (cache->size() == 0) {
1260 goto Exit;
1261 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001262
Eric Laurent3d00aa62013-09-24 09:53:27 -07001263 *pSize = cache->size();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001264 *pSampleRate = cache->sampleRate();
1265 *pNumChannels = cache->channelCount();
Glenn Kastene1c39622012-01-04 09:36:37 -08001266 *pFormat = cache->format();
Eric Laurent3d00aa62013-09-24 09:53:27 -07001267 ALOGV("return size %d sampleRate=%u, channelCount = %d, format = %d",
1268 *pSize, *pSampleRate, *pNumChannels, *pFormat);
1269 status = NO_ERROR;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001270
1271Exit:
1272 if (player != 0) player->reset();
Eric Laurent3d00aa62013-09-24 09:53:27 -07001273 return status;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001274}
1275
Eric Laurent3d00aa62013-09-24 09:53:27 -07001276status_t MediaPlayerService::decode(int fd, int64_t offset, int64_t length,
1277 uint32_t *pSampleRate, int* pNumChannels,
1278 audio_format_t* pFormat,
1279 const sp<IMemoryHeap>& heap, size_t *pSize)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001280{
Steve Block3856b092011-10-20 11:56:00 +01001281 ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001282 sp<MediaPlayerBase> player;
Eric Laurent3d00aa62013-09-24 09:53:27 -07001283 status_t status = BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001284
John Grossman44a7e422012-06-21 17:29:24 -07001285 player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
1286 fd,
1287 offset,
1288 length);
Steve Block3856b092011-10-20 11:56:00 +01001289 ALOGV("player type = %d", playerType);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001290
1291 // create the right type of player
Eric Laurent3d00aa62013-09-24 09:53:27 -07001292 sp<AudioCache> cache = new AudioCache(heap);
John Grossman44a7e422012-06-21 17:29:24 -07001293 player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001294 if (player == NULL) goto Exit;
1295 if (player->hardwareOutput()) goto Exit;
1296
1297 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1298
1299 // set data source
1300 if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
1301
Steve Block3856b092011-10-20 11:56:00 +01001302 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001303 player->prepareAsync();
1304
Steve Block3856b092011-10-20 11:56:00 +01001305 ALOGV("wait for prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001306 if (cache->wait() != NO_ERROR) goto Exit;
1307
Steve Block3856b092011-10-20 11:56:00 +01001308 ALOGV("start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001309 player->start();
1310
Steve Block3856b092011-10-20 11:56:00 +01001311 ALOGV("wait for playback complete");
Eric Laurent9cb839a2011-09-27 09:48:56 -07001312 cache->wait();
1313 // in case of error, return what was successfully decoded.
1314 if (cache->size() == 0) {
1315 goto Exit;
1316 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001317
Eric Laurent3d00aa62013-09-24 09:53:27 -07001318 *pSize = cache->size();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001319 *pSampleRate = cache->sampleRate();
1320 *pNumChannels = cache->channelCount();
1321 *pFormat = cache->format();
Eric Laurent3d00aa62013-09-24 09:53:27 -07001322 ALOGV("return size %d, sampleRate=%u, channelCount = %d, format = %d",
1323 *pSize, *pSampleRate, *pNumChannels, *pFormat);
1324 status = NO_ERROR;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001325
1326Exit:
1327 if (player != 0) player->reset();
1328 ::close(fd);
Eric Laurent3d00aa62013-09-24 09:53:27 -07001329 return status;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001330}
1331
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001332
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001333#undef LOG_TAG
1334#define LOG_TAG "AudioSink"
Marco Nelissen9cae2172013-01-14 14:12:05 -08001335MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid)
Andreas Huber20111aa2009-07-14 16:56:47 -07001336 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001337 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001338 mCallbackData(NULL),
Marco Nelissen4110c102012-03-29 09:31:28 -07001339 mBytesWritten(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001340 mSessionId(sessionId),
Marco Nelissen9cae2172013-01-14 14:12:05 -08001341 mUid(uid),
Eric Laurent1948eb32012-04-13 16:50:19 -07001342 mFlags(AUDIO_OUTPUT_FLAG_NONE) {
Steve Block3856b092011-10-20 11:56:00 +01001343 ALOGV("AudioOutput(%d)", sessionId);
Dima Zavinfce7a472011-04-19 22:30:36 -07001344 mStreamType = AUDIO_STREAM_MUSIC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001345 mLeftVolume = 1.0;
1346 mRightVolume = 1.0;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001347 mPlaybackRatePermille = 1000;
1348 mSampleRateHz = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001349 mMsecsPerFrame = 0;
Eric Laurent2beeb502010-07-16 07:43:46 -07001350 mAuxEffectId = 0;
1351 mSendLevel = 0.0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001352 setMinBufferCount();
1353}
1354
1355MediaPlayerService::AudioOutput::~AudioOutput()
1356{
1357 close();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001358 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001359}
1360
1361void MediaPlayerService::AudioOutput::setMinBufferCount()
1362{
1363 char value[PROPERTY_VALUE_MAX];
1364 if (property_get("ro.kernel.qemu", value, 0)) {
1365 mIsOnEmulator = true;
1366 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1367 }
1368}
1369
1370bool MediaPlayerService::AudioOutput::isOnEmulator()
1371{
1372 setMinBufferCount();
1373 return mIsOnEmulator;
1374}
1375
1376int MediaPlayerService::AudioOutput::getMinBufferCount()
1377{
1378 setMinBufferCount();
1379 return mMinBufferCount;
1380}
1381
1382ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1383{
1384 if (mTrack == 0) return NO_INIT;
1385 return mTrack->frameCount() * frameSize();
1386}
1387
1388ssize_t MediaPlayerService::AudioOutput::frameCount() const
1389{
1390 if (mTrack == 0) return NO_INIT;
1391 return mTrack->frameCount();
1392}
1393
1394ssize_t MediaPlayerService::AudioOutput::channelCount() const
1395{
1396 if (mTrack == 0) return NO_INIT;
1397 return mTrack->channelCount();
1398}
1399
1400ssize_t MediaPlayerService::AudioOutput::frameSize() const
1401{
1402 if (mTrack == 0) return NO_INIT;
1403 return mTrack->frameSize();
1404}
1405
1406uint32_t MediaPlayerService::AudioOutput::latency () const
1407{
Eric Laurentdb354e52012-03-05 17:27:11 -08001408 if (mTrack == 0) return 0;
1409 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001410}
1411
1412float MediaPlayerService::AudioOutput::msecsPerFrame() const
1413{
1414 return mMsecsPerFrame;
1415}
1416
Marco Nelissen4110c102012-03-29 09:31:28 -07001417status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001418{
1419 if (mTrack == 0) return NO_INIT;
1420 return mTrack->getPosition(position);
1421}
1422
Marco Nelissen4110c102012-03-29 09:31:28 -07001423status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1424{
1425 if (mTrack == 0) return NO_INIT;
1426 *frameswritten = mBytesWritten / frameSize();
1427 return OK;
1428}
1429
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001430status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
1431{
1432 if (mTrack == 0) return NO_INIT;
1433 return mTrack->setParameters(keyValuePairs);
1434}
1435
1436String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
1437{
1438 if (mTrack == 0) return String8::empty();
1439 return mTrack->getParameters(keys);
1440}
1441
1442void MediaPlayerService::AudioOutput::deleteRecycledTrack()
1443{
1444 ALOGV("deleteRecycledTrack");
1445
1446 if (mRecycledTrack != 0) {
1447
1448 if (mCallbackData != NULL) {
1449 mCallbackData->setOutput(NULL);
1450 mCallbackData->endTrackSwitch();
1451 }
1452
1453 if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
1454 mRecycledTrack->flush();
1455 }
1456 // An offloaded track isn't flushed because the STREAM_END is reported
1457 // slightly prematurely to allow time for the gapless track switch
1458 // but this means that if we decide not to recycle the track there
1459 // could be a small amount of residual data still playing. We leave
1460 // AudioFlinger to drain the track.
1461
1462 mRecycledTrack.clear();
1463 delete mCallbackData;
1464 mCallbackData = NULL;
1465 close();
1466 }
1467}
1468
Andreas Huber20111aa2009-07-14 16:56:47 -07001469status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001470 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1471 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001472 AudioCallback cb, void *cookie,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001473 audio_output_flags_t flags,
1474 const audio_offload_info_t *offloadInfo)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001475{
Andreas Huber20111aa2009-07-14 16:56:47 -07001476 mCallback = cb;
1477 mCallbackCookie = cookie;
1478
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001479 // Check argument "bufferCount" against the mininum buffer count
1480 if (bufferCount < mMinBufferCount) {
Steve Blockb8a80522011-12-20 16:23:08 +00001481 ALOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001482 bufferCount = mMinBufferCount;
1483
1484 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001485 ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
1486 format, bufferCount, mSessionId, flags);
Glenn Kasten1127d652012-11-14 08:44:39 -08001487 uint32_t afSampleRate;
Glenn Kasten7da35f22012-11-14 12:54:39 -08001488 size_t afFrameCount;
Eric Laurent1948eb32012-04-13 16:50:19 -07001489 uint32_t frameCount;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001490
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001491 // offloading is only supported in callback mode for now.
1492 // offloadInfo must be present if offload flag is set
1493 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
1494 ((cb == NULL) || (offloadInfo == NULL))) {
1495 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001496 }
1497
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001498 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1499 frameCount = 0; // AudioTrack will get frame count from AudioFlinger
1500 } else {
1501 uint32_t afSampleRate;
1502 size_t afFrameCount;
1503
1504 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1505 return NO_INIT;
1506 }
1507 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1508 return NO_INIT;
1509 }
1510
1511 frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
1512 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001513
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001514 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001515 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001516 if (0 == channelMask) {
1517 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1518 return NO_INIT;
1519 }
1520 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001521
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001522 // Check whether we can recycle the track
1523 bool reuse = false;
1524 bool bothOffloaded = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001525
Glenn Kasten2799d742013-05-30 14:33:29 -07001526 if (mRecycledTrack != 0) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001527 // check whether we are switching between two offloaded tracks
1528 bothOffloaded = (flags & mRecycledTrack->getFlags()
1529 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
Marco Nelissen67295b52012-06-11 14:52:53 -07001530
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001531 // check if the existing track can be reused as-is, or if a new track needs to be created.
1532 reuse = true;
1533
Marco Nelissen67295b52012-06-11 14:52:53 -07001534 if ((mCallbackData == NULL && mCallback != NULL) ||
1535 (mCallbackData != NULL && mCallback == NULL)) {
1536 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1537 ALOGV("can't chain callback and write");
1538 reuse = false;
1539 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001540 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
1541 ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
Marco Nelissen67295b52012-06-11 14:52:53 -07001542 mRecycledTrack->getSampleRate(), sampleRate,
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001543 mRecycledTrack->channelCount(), channelCount);
Marco Nelissen67295b52012-06-11 14:52:53 -07001544 reuse = false;
1545 } else if (flags != mFlags) {
1546 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1547 reuse = false;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001548 } else if (mRecycledTrack->format() != format) {
1549 reuse = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001550 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001551 } else {
1552 ALOGV("no track available to recycle");
1553 }
1554
1555 ALOGV_IF(bothOffloaded, "both tracks offloaded");
1556
1557 // If we can't recycle and both tracks are offloaded
1558 // we must close the previous output before opening a new one
1559 if (bothOffloaded && !reuse) {
1560 ALOGV("both offloaded and not recycling");
1561 deleteRecycledTrack();
1562 }
1563
1564 sp<AudioTrack> t;
1565 CallbackData *newcbd = NULL;
1566
1567 // We don't attempt to create a new track if we are recycling an
1568 // offloaded track. But, if we are recycling a non-offloaded or we
1569 // are switching where one is offloaded and one isn't then we create
1570 // the new track in advance so that we can read additional stream info
1571
1572 if (!(reuse && bothOffloaded)) {
1573 ALOGV("creating new AudioTrack");
1574
1575 if (mCallback != NULL) {
1576 newcbd = new CallbackData(this);
1577 t = new AudioTrack(
1578 mStreamType,
1579 sampleRate,
1580 format,
1581 channelMask,
1582 frameCount,
1583 flags,
1584 CallbackWrapper,
1585 newcbd,
1586 0, // notification frames
1587 mSessionId,
1588 AudioTrack::TRANSFER_CALLBACK,
Marco Nelissen9cae2172013-01-14 14:12:05 -08001589 offloadInfo,
1590 mUid);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001591 } else {
1592 t = new AudioTrack(
1593 mStreamType,
1594 sampleRate,
1595 format,
1596 channelMask,
1597 frameCount,
1598 flags,
Marco Nelissen9cae2172013-01-14 14:12:05 -08001599 NULL, // callback
1600 NULL, // user data
1601 0, // notification frames
1602 mSessionId,
1603 AudioTrack::TRANSFER_DEFAULT,
1604 NULL, // offload info
1605 mUid);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001606 }
1607
1608 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1609 ALOGE("Unable to create audio track");
1610 delete newcbd;
1611 return NO_INIT;
1612 }
1613 }
1614
1615 if (reuse) {
1616 CHECK(mRecycledTrack != NULL);
1617
1618 if (!bothOffloaded) {
1619 if (mRecycledTrack->frameCount() != t->frameCount()) {
1620 ALOGV("framecount differs: %u/%u frames",
1621 mRecycledTrack->frameCount(), t->frameCount());
1622 reuse = false;
1623 }
1624 }
1625
Marco Nelissen67295b52012-06-11 14:52:53 -07001626 if (reuse) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001627 ALOGV("chaining to next output and recycling track");
Marco Nelissen67295b52012-06-11 14:52:53 -07001628 close();
1629 mTrack = mRecycledTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001630 mRecycledTrack.clear();
Marco Nelissen67295b52012-06-11 14:52:53 -07001631 if (mCallbackData != NULL) {
1632 mCallbackData->setOutput(this);
1633 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001634 delete newcbd;
1635 return OK;
1636 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001637 }
1638
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001639 // we're not going to reuse the track, unblock and flush it
1640 // this was done earlier if both tracks are offloaded
1641 if (!bothOffloaded) {
1642 deleteRecycledTrack();
1643 }
1644
1645 CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
1646
Marco Nelissen67295b52012-06-11 14:52:53 -07001647 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001648 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001649 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001650
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001651 mSampleRateHz = sampleRate;
Eric Laurent1948eb32012-04-13 16:50:19 -07001652 mFlags = flags;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001653 mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
Marco Nelissen99448602012-04-02 12:16:49 -07001654 uint32_t pos;
1655 if (t->getPosition(&pos) == OK) {
1656 mBytesWritten = uint64_t(pos) * t->frameSize();
1657 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001658 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001659
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001660 status_t res = NO_ERROR;
1661 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
1662 res = t->setSampleRate(mPlaybackRatePermille * mSampleRateHz / 1000);
1663 if (res == NO_ERROR) {
1664 t->setAuxEffectSendLevel(mSendLevel);
1665 res = t->attachAuxEffect(mAuxEffectId);
1666 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001667 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001668 ALOGV("open() DONE status %d", res);
1669 return res;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001670}
1671
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001672status_t MediaPlayerService::AudioOutput::start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001673{
Steve Block3856b092011-10-20 11:56:00 +01001674 ALOGV("start");
Marco Nelissen6b74d672012-02-28 16:07:44 -08001675 if (mCallbackData != NULL) {
1676 mCallbackData->endTrackSwitch();
1677 }
Glenn Kasten2799d742013-05-30 14:33:29 -07001678 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001679 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001680 mTrack->setAuxEffectSendLevel(mSendLevel);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001681 return mTrack->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001682 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001683 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001684}
1685
Marco Nelissen6b74d672012-02-28 16:07:44 -08001686void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
1687 mNextOutput = nextOutput;
1688}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001689
1690
Marco Nelissen6b74d672012-02-28 16:07:44 -08001691void MediaPlayerService::AudioOutput::switchToNextOutput() {
1692 ALOGV("switchToNextOutput");
1693 if (mNextOutput != NULL) {
1694 if (mCallbackData != NULL) {
1695 mCallbackData->beginTrackSwitch();
1696 }
1697 delete mNextOutput->mCallbackData;
1698 mNextOutput->mCallbackData = mCallbackData;
1699 mCallbackData = NULL;
1700 mNextOutput->mRecycledTrack = mTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001701 mTrack.clear();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001702 mNextOutput->mSampleRateHz = mSampleRateHz;
1703 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
Marco Nelissen4110c102012-03-29 09:31:28 -07001704 mNextOutput->mBytesWritten = mBytesWritten;
Marco Nelissend791e092012-06-11 17:00:59 -07001705 mNextOutput->mFlags = mFlags;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001706 }
1707}
1708
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001709ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
1710{
Andreas Huber20111aa2009-07-14 16:56:47 -07001711 LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
1712
Steve Block3856b092011-10-20 11:56:00 +01001713 //ALOGV("write(%p, %u)", buffer, size);
Glenn Kasten2799d742013-05-30 14:33:29 -07001714 if (mTrack != 0) {
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001715 ssize_t ret = mTrack->write(buffer, size);
Marco Nelissen4110c102012-03-29 09:31:28 -07001716 mBytesWritten += ret;
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001717 return ret;
1718 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001719 return NO_INIT;
1720}
1721
1722void MediaPlayerService::AudioOutput::stop()
1723{
Steve Block3856b092011-10-20 11:56:00 +01001724 ALOGV("stop");
Glenn Kasten2799d742013-05-30 14:33:29 -07001725 if (mTrack != 0) mTrack->stop();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001726}
1727
1728void MediaPlayerService::AudioOutput::flush()
1729{
Steve Block3856b092011-10-20 11:56:00 +01001730 ALOGV("flush");
Glenn Kasten2799d742013-05-30 14:33:29 -07001731 if (mTrack != 0) mTrack->flush();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001732}
1733
1734void MediaPlayerService::AudioOutput::pause()
1735{
Steve Block3856b092011-10-20 11:56:00 +01001736 ALOGV("pause");
Glenn Kasten2799d742013-05-30 14:33:29 -07001737 if (mTrack != 0) mTrack->pause();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001738}
1739
1740void MediaPlayerService::AudioOutput::close()
1741{
Steve Block3856b092011-10-20 11:56:00 +01001742 ALOGV("close");
Glenn Kasten2799d742013-05-30 14:33:29 -07001743 mTrack.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001744}
1745
1746void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1747{
Steve Block3856b092011-10-20 11:56:00 +01001748 ALOGV("setVolume(%f, %f)", left, right);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001749 mLeftVolume = left;
1750 mRightVolume = right;
Glenn Kasten2799d742013-05-30 14:33:29 -07001751 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001752 mTrack->setVolume(left, right);
1753 }
1754}
1755
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001756status_t MediaPlayerService::AudioOutput::setPlaybackRatePermille(int32_t ratePermille)
1757{
1758 ALOGV("setPlaybackRatePermille(%d)", ratePermille);
1759 status_t res = NO_ERROR;
Glenn Kasten2799d742013-05-30 14:33:29 -07001760 if (mTrack != 0) {
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001761 res = mTrack->setSampleRate(ratePermille * mSampleRateHz / 1000);
1762 } else {
1763 res = NO_INIT;
1764 }
1765 mPlaybackRatePermille = ratePermille;
1766 if (mSampleRateHz != 0) {
1767 mMsecsPerFrame = mPlaybackRatePermille / (float) mSampleRateHz;
1768 }
1769 return res;
1770}
1771
Eric Laurent2beeb502010-07-16 07:43:46 -07001772status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
1773{
Steve Block3856b092011-10-20 11:56:00 +01001774 ALOGV("setAuxEffectSendLevel(%f)", level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001775 mSendLevel = level;
Glenn Kasten2799d742013-05-30 14:33:29 -07001776 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07001777 return mTrack->setAuxEffectSendLevel(level);
1778 }
1779 return NO_ERROR;
1780}
1781
1782status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
1783{
Steve Block3856b092011-10-20 11:56:00 +01001784 ALOGV("attachAuxEffect(%d)", effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001785 mAuxEffectId = effectId;
Glenn Kasten2799d742013-05-30 14:33:29 -07001786 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07001787 return mTrack->attachAuxEffect(effectId);
1788 }
1789 return NO_ERROR;
1790}
1791
Andreas Huber20111aa2009-07-14 16:56:47 -07001792// static
1793void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07001794 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01001795 //ALOGV("callbackwrapper");
Marco Nelissen6b74d672012-02-28 16:07:44 -08001796 CallbackData *data = (CallbackData*)cookie;
1797 data->lock();
1798 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07001799 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001800 if (me == NULL) {
1801 // no output set, likely because the track was scheduled to be reused
1802 // by another player, but the format turned out to be incompatible.
1803 data->unlock();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001804 if (buffer != NULL) {
1805 buffer->size = 0;
1806 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001807 return;
1808 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001809
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001810 switch(event) {
1811 case AudioTrack::EVENT_MORE_DATA: {
1812 size_t actualSize = (*me->mCallback)(
1813 me, buffer->raw, buffer->size, me->mCallbackCookie,
1814 CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001815
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001816 if (actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) {
1817 // We've reached EOS but the audio track is not stopped yet,
1818 // keep playing silence.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08001819
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001820 memset(buffer->raw, 0, buffer->size);
1821 actualSize = buffer->size;
1822 }
1823
1824 buffer->size = actualSize;
1825 } break;
1826
1827
1828 case AudioTrack::EVENT_STREAM_END:
1829 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
1830 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
1831 me->mCallbackCookie, CB_EVENT_STREAM_END);
1832 break;
1833
1834 case AudioTrack::EVENT_NEW_IAUDIOTRACK :
1835 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
1836 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
1837 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
1838 break;
1839
1840 default:
1841 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
Andreas Huber51c1e0e2011-04-04 11:43:40 -07001842 }
1843
Marco Nelissen6b74d672012-02-28 16:07:44 -08001844 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07001845}
1846
Marco Nelissen4110c102012-03-29 09:31:28 -07001847int MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07001848{
1849 return mSessionId;
1850}
1851
Eric Laurentd0115d82013-07-26 17:16:50 -07001852uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
1853{
1854 if (mTrack == 0) return 0;
1855 return mTrack->getSampleRate();
1856}
1857
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001858#undef LOG_TAG
1859#define LOG_TAG "AudioCache"
Eric Laurent3d00aa62013-09-24 09:53:27 -07001860MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) :
1861 mHeap(heap), mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
1862 mError(NO_ERROR), mCommandComplete(false)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001863{
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001864}
1865
1866uint32_t MediaPlayerService::AudioCache::latency () const
1867{
1868 return 0;
1869}
1870
1871float MediaPlayerService::AudioCache::msecsPerFrame() const
1872{
1873 return mMsecsPerFrame;
1874}
1875
Marco Nelissen4110c102012-03-29 09:31:28 -07001876status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001877{
1878 if (position == 0) return BAD_VALUE;
1879 *position = mSize;
1880 return NO_ERROR;
1881}
1882
Marco Nelissen4110c102012-03-29 09:31:28 -07001883status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
1884{
1885 if (written == 0) return BAD_VALUE;
1886 *written = mSize;
1887 return NO_ERROR;
1888}
1889
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001890////////////////////////////////////////////////////////////////////////////////
1891
1892struct CallbackThread : public Thread {
1893 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
1894 MediaPlayerBase::AudioSink::AudioCallback cb,
1895 void *cookie);
1896
1897protected:
1898 virtual ~CallbackThread();
1899
1900 virtual bool threadLoop();
1901
1902private:
1903 wp<MediaPlayerBase::AudioSink> mSink;
1904 MediaPlayerBase::AudioSink::AudioCallback mCallback;
1905 void *mCookie;
1906 void *mBuffer;
1907 size_t mBufferSize;
1908
1909 CallbackThread(const CallbackThread &);
1910 CallbackThread &operator=(const CallbackThread &);
1911};
1912
1913CallbackThread::CallbackThread(
1914 const wp<MediaPlayerBase::AudioSink> &sink,
1915 MediaPlayerBase::AudioSink::AudioCallback cb,
1916 void *cookie)
1917 : mSink(sink),
1918 mCallback(cb),
1919 mCookie(cookie),
1920 mBuffer(NULL),
1921 mBufferSize(0) {
1922}
1923
1924CallbackThread::~CallbackThread() {
1925 if (mBuffer) {
1926 free(mBuffer);
1927 mBuffer = NULL;
1928 }
1929}
1930
1931bool CallbackThread::threadLoop() {
1932 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
1933 if (sink == NULL) {
1934 return false;
1935 }
1936
1937 if (mBuffer == NULL) {
1938 mBufferSize = sink->bufferSize();
1939 mBuffer = malloc(mBufferSize);
1940 }
1941
1942 size_t actualSize =
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001943 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
1944 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001945
1946 if (actualSize > 0) {
1947 sink->write(mBuffer, actualSize);
1948 }
1949
1950 return true;
1951}
1952
1953////////////////////////////////////////////////////////////////////////////////
1954
Andreas Huber20111aa2009-07-14 16:56:47 -07001955status_t MediaPlayerService::AudioCache::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001956 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1957 audio_format_t format, int bufferCount,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001958 AudioCallback cb, void *cookie, audio_output_flags_t flags,
1959 const audio_offload_info_t *offloadInfo)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001960{
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001961 ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
Dave Sparks8eb80112009-12-09 20:20:26 -08001962 if (mHeap->getHeapID() < 0) {
1963 return NO_INIT;
1964 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001965
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001966 mSampleRate = sampleRate;
1967 mChannelCount = (uint16_t)channelCount;
Glenn Kastene1c39622012-01-04 09:36:37 -08001968 mFormat = format;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001969 mMsecsPerFrame = 1.e3 / (float) sampleRate;
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001970
1971 if (cb != NULL) {
1972 mCallbackThread = new CallbackThread(this, cb, cookie);
1973 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001974 return NO_ERROR;
1975}
1976
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001977status_t MediaPlayerService::AudioCache::start() {
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001978 if (mCallbackThread != NULL) {
1979 mCallbackThread->run("AudioCache callback");
1980 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001981 return NO_ERROR;
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001982}
1983
1984void MediaPlayerService::AudioCache::stop() {
1985 if (mCallbackThread != NULL) {
1986 mCallbackThread->requestExitAndWait();
1987 }
1988}
1989
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001990ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
1991{
Steve Block3856b092011-10-20 11:56:00 +01001992 ALOGV("write(%p, %u)", buffer, size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001993 if ((buffer == 0) || (size == 0)) return size;
1994
1995 uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
1996 if (p == NULL) return NO_INIT;
1997 p += mSize;
Steve Block3856b092011-10-20 11:56:00 +01001998 ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001999 if (mSize + size > mHeap->getSize()) {
Steve Block29357bc2012-01-06 19:20:56 +00002000 ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002001 size = mHeap->getSize() - mSize;
2002 }
2003 memcpy(p, buffer, size);
2004 mSize += size;
2005 return size;
2006}
2007
2008// call with lock held
2009status_t MediaPlayerService::AudioCache::wait()
2010{
2011 Mutex::Autolock lock(mLock);
Dave Sparks4bbc0ba2010-03-01 19:29:58 -08002012 while (!mCommandComplete) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002013 mSignal.wait(mLock);
2014 }
2015 mCommandComplete = false;
2016
2017 if (mError == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01002018 ALOGV("wait - success");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002019 } else {
Steve Block3856b092011-10-20 11:56:00 +01002020 ALOGV("wait - error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002021 }
2022 return mError;
2023}
2024
Gloria Wangb483c472011-04-11 17:23:27 -07002025void MediaPlayerService::AudioCache::notify(
2026 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002027{
Steve Block3856b092011-10-20 11:56:00 +01002028 ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002029 AudioCache* p = static_cast<AudioCache*>(cookie);
2030
2031 // ignore buffering messages
Dave Sparks8eb80112009-12-09 20:20:26 -08002032 switch (msg)
2033 {
2034 case MEDIA_ERROR:
Steve Block29357bc2012-01-06 19:20:56 +00002035 ALOGE("Error %d, %d occurred", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002036 p->mError = ext1;
Dave Sparks8eb80112009-12-09 20:20:26 -08002037 break;
2038 case MEDIA_PREPARED:
Steve Block3856b092011-10-20 11:56:00 +01002039 ALOGV("prepared");
Dave Sparks8eb80112009-12-09 20:20:26 -08002040 break;
2041 case MEDIA_PLAYBACK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +01002042 ALOGV("playback complete");
Dave Sparks8eb80112009-12-09 20:20:26 -08002043 break;
2044 default:
Steve Block3856b092011-10-20 11:56:00 +01002045 ALOGV("ignored");
Dave Sparks8eb80112009-12-09 20:20:26 -08002046 return;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002047 }
2048
2049 // wake up thread
Dave Sparksfe4c6f02010-03-02 12:56:37 -08002050 Mutex::Autolock lock(p->mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002051 p->mCommandComplete = true;
2052 p->mSignal.signal();
2053}
2054
Marco Nelissen4110c102012-03-29 09:31:28 -07002055int MediaPlayerService::AudioCache::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07002056{
2057 return 0;
2058}
2059
Eric Laurentd0115d82013-07-26 17:16:50 -07002060uint32_t MediaPlayerService::AudioCache::getSampleRate() const
2061{
2062 if (mMsecsPerFrame == 0) {
2063 return 0;
2064 }
2065 return (uint32_t)(1.e3 / mMsecsPerFrame);
2066}
2067
Gloria Wang7cf180c2011-02-19 18:37:57 -08002068void MediaPlayerService::addBatteryData(uint32_t params)
2069{
2070 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002071
2072 int32_t time = systemTime() / 1000000L;
2073
2074 // change audio output devices. This notification comes from AudioFlinger
2075 if ((params & kBatteryDataSpeakerOn)
2076 || (params & kBatteryDataOtherAudioDeviceOn)) {
2077
2078 int deviceOn[NUM_AUDIO_DEVICES];
2079 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2080 deviceOn[i] = 0;
2081 }
2082
2083 if ((params & kBatteryDataSpeakerOn)
2084 && (params & kBatteryDataOtherAudioDeviceOn)) {
2085 deviceOn[SPEAKER_AND_OTHER] = 1;
2086 } else if (params & kBatteryDataSpeakerOn) {
2087 deviceOn[SPEAKER] = 1;
2088 } else {
2089 deviceOn[OTHER_AUDIO_DEVICE] = 1;
2090 }
2091
2092 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2093 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2094
2095 if (mBatteryAudio.refCount > 0) { // if playing audio
2096 if (!deviceOn[i]) {
2097 mBatteryAudio.lastTime[i] += time;
2098 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2099 mBatteryAudio.lastTime[i] = 0;
2100 } else {
2101 mBatteryAudio.lastTime[i] = 0 - time;
2102 }
2103 }
2104
2105 mBatteryAudio.deviceOn[i] = deviceOn[i];
2106 }
2107 }
2108 return;
2109 }
2110
2111 // an sudio stream is started
2112 if (params & kBatteryDataAudioFlingerStart) {
2113 // record the start time only if currently no other audio
2114 // is being played
2115 if (mBatteryAudio.refCount == 0) {
2116 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2117 if (mBatteryAudio.deviceOn[i]) {
2118 mBatteryAudio.lastTime[i] -= time;
2119 }
2120 }
2121 }
2122
2123 mBatteryAudio.refCount ++;
2124 return;
2125
2126 } else if (params & kBatteryDataAudioFlingerStop) {
2127 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002128 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002129 return;
2130 }
2131
2132 // record the stop time only if currently this is the only
2133 // audio being played
2134 if (mBatteryAudio.refCount == 1) {
2135 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2136 if (mBatteryAudio.deviceOn[i]) {
2137 mBatteryAudio.lastTime[i] += time;
2138 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2139 mBatteryAudio.lastTime[i] = 0;
2140 }
2141 }
2142 }
2143
2144 mBatteryAudio.refCount --;
2145 return;
2146 }
2147
Gloria Wang7cf180c2011-02-19 18:37:57 -08002148 int uid = IPCThreadState::self()->getCallingUid();
2149 if (uid == AID_MEDIA) {
2150 return;
2151 }
2152 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08002153
2154 if (index < 0) { // create a new entry for this UID
2155 BatteryUsageInfo info;
2156 info.audioTotalTime = 0;
2157 info.videoTotalTime = 0;
2158 info.audioLastTime = 0;
2159 info.videoLastTime = 0;
2160 info.refCount = 0;
2161
Gloria Wang9ee159b2011-02-24 14:51:45 -08002162 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00002163 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002164 return;
2165 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08002166 }
2167
2168 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2169
2170 if (params & kBatteryDataCodecStarted) {
2171 if (params & kBatteryDataTrackAudio) {
2172 info.audioLastTime -= time;
2173 info.refCount ++;
2174 }
2175 if (params & kBatteryDataTrackVideo) {
2176 info.videoLastTime -= time;
2177 info.refCount ++;
2178 }
2179 } else {
2180 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002181 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002182 return;
2183 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00002184 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002185 mBatteryData.removeItem(uid);
2186 return;
2187 }
2188
2189 if (params & kBatteryDataTrackAudio) {
2190 info.audioLastTime += time;
2191 info.refCount --;
2192 }
2193 if (params & kBatteryDataTrackVideo) {
2194 info.videoLastTime += time;
2195 info.refCount --;
2196 }
2197
2198 // no stream is being played by this UID
2199 if (info.refCount == 0) {
2200 info.audioTotalTime += info.audioLastTime;
2201 info.audioLastTime = 0;
2202 info.videoTotalTime += info.videoLastTime;
2203 info.videoLastTime = 0;
2204 }
2205 }
2206}
2207
2208status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2209 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002210
2211 // audio output devices usage
2212 int32_t time = systemTime() / 1000000L; //in ms
2213 int32_t totalTime;
2214
2215 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2216 totalTime = mBatteryAudio.totalTime[i];
2217
2218 if (mBatteryAudio.deviceOn[i]
2219 && (mBatteryAudio.lastTime[i] != 0)) {
2220 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2221 totalTime += tmpTime;
2222 }
2223
2224 reply->writeInt32(totalTime);
2225 // reset the total time
2226 mBatteryAudio.totalTime[i] = 0;
2227 }
2228
2229 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002230 BatteryUsageInfo info;
2231 int size = mBatteryData.size();
2232
2233 reply->writeInt32(size);
2234 int i = 0;
2235
2236 while (i < size) {
2237 info = mBatteryData.valueAt(i);
2238
2239 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2240 reply->writeInt32(info.audioTotalTime);
2241 reply->writeInt32(info.videoTotalTime);
2242
2243 info.audioTotalTime = 0;
2244 info.videoTotalTime = 0;
2245
2246 // remove the UID entry where no stream is being played
2247 if (info.refCount <= 0) {
2248 mBatteryData.removeItemsAt(i);
2249 size --;
2250 i --;
2251 }
2252 i++;
2253 }
2254 return NO_ERROR;
2255}
nikoa64c8c72009-07-20 15:07:26 -07002256} // namespace android