blob: 193b02ce56584bdd9e5fb6aeef6899aa89bd054a [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>
Jamie Gennis7dae00b2011-10-26 18:36:31 -070041#include <gui/SurfaceTextureClient.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 Browne1045962012-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>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080056
Dima Zavin64760242011-05-11 14:15:23 -070057#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070058
Gloria Wang7cf180c2011-02-19 18:37:57 -080059#include <private/android_filesystem_config.h>
60
James Dong559bf282012-03-28 10:29:14 -070061#include "ActivityManager.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080062#include "MediaRecorderClient.h"
63#include "MediaPlayerService.h"
64#include "MetadataRetrieverClient.h"
John Grossman44a7e422012-06-21 17:29:24 -070065#include "MediaPlayerFactory.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080066
67#include "MidiFile.h"
Nicolas Catania14d27472009-07-13 14:37:49 -070068#include "TestPlayerStub.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070069#include "StagefrightPlayer.h"
Andreas Huberf9334412010-12-15 15:17:42 -080070#include "nuplayer/NuPlayerDriver.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070071
Andreas Huber20111aa2009-07-14 16:56:47 -070072#include <OMX.h>
Nicolas Catania14d27472009-07-13 14:37:49 -070073
Andreas Hubered3e3e02012-03-26 11:13:27 -070074#include "Crypto.h"
Andreas Huberefbb7812012-09-18 10:36:32 -070075#include "HDCP.h"
Andreas Huberd7bee3a2012-08-29 11:41:50 -070076#include "RemoteDisplay.h"
Andreas Hubered3e3e02012-03-26 11:13:27 -070077
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070078namespace {
nikoa64c8c72009-07-20 15:07:26 -070079using android::media::Metadata;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070080using android::status_t;
81using android::OK;
82using android::BAD_VALUE;
83using android::NOT_ENOUGH_DATA;
84using android::Parcel;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070085
86// Max number of entries in the filter.
87const int kMaxFilterSize = 64; // I pulled that out of thin air.
88
nikoa64c8c72009-07-20 15:07:26 -070089// FIXME: Move all the metadata related function in the Metadata.cpp
nikod608a812009-07-16 16:39:53 -070090
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070091
92// Unmarshall a filter from a Parcel.
93// Filter format in a parcel:
94//
95// 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
96// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97// | number of entries (n) |
98// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99// | metadata type 1 |
100// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101// | metadata type 2 |
102// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103// ....
104// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105// | metadata type n |
106// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107//
108// @param p Parcel that should start with a filter.
109// @param[out] filter On exit contains the list of metadata type to be
110// filtered.
111// @param[out] status On exit contains the status code to be returned.
112// @return true if the parcel starts with a valid filter.
113bool unmarshallFilter(const Parcel& p,
nikoa64c8c72009-07-20 15:07:26 -0700114 Metadata::Filter *filter,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700115 status_t *status)
116{
Nicolas Catania48290382009-07-10 13:53:06 -0700117 int32_t val;
118 if (p.readInt32(&val) != OK)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700119 {
Steve Block29357bc2012-01-06 19:20:56 +0000120 ALOGE("Failed to read filter's length");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700121 *status = NOT_ENOUGH_DATA;
122 return false;
123 }
124
Nicolas Catania48290382009-07-10 13:53:06 -0700125 if( val > kMaxFilterSize || val < 0)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700126 {
Steve Block29357bc2012-01-06 19:20:56 +0000127 ALOGE("Invalid filter len %d", val);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700128 *status = BAD_VALUE;
129 return false;
130 }
131
Nicolas Catania48290382009-07-10 13:53:06 -0700132 const size_t num = val;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700133
134 filter->clear();
Nicolas Catania48290382009-07-10 13:53:06 -0700135 filter->setCapacity(num);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700136
nikoa64c8c72009-07-20 15:07:26 -0700137 size_t size = num * sizeof(Metadata::Type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700138
Nicolas Catania48290382009-07-10 13:53:06 -0700139
140 if (p.dataAvail() < size)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700141 {
Steve Block29357bc2012-01-06 19:20:56 +0000142 ALOGE("Filter too short expected %d but got %d", size, p.dataAvail());
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700143 *status = NOT_ENOUGH_DATA;
144 return false;
145 }
146
nikoa64c8c72009-07-20 15:07:26 -0700147 const Metadata::Type *data =
148 static_cast<const Metadata::Type*>(p.readInplace(size));
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700149
Nicolas Catania48290382009-07-10 13:53:06 -0700150 if (NULL == data)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700151 {
Steve Block29357bc2012-01-06 19:20:56 +0000152 ALOGE("Filter had no data");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700153 *status = BAD_VALUE;
154 return false;
155 }
156
157 // TODO: The stl impl of vector would be more efficient here
158 // because it degenerates into a memcpy on pod types. Try to
159 // replace later or use stl::set.
Nicolas Catania48290382009-07-10 13:53:06 -0700160 for (size_t i = 0; i < num; ++i)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700161 {
Nicolas Catania48290382009-07-10 13:53:06 -0700162 filter->add(*data);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700163 ++data;
164 }
165 *status = OK;
166 return true;
167}
168
Nicolas Catania48290382009-07-10 13:53:06 -0700169// @param filter Of metadata type.
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700170// @param val To be searched.
171// @return true if a match was found.
nikoa64c8c72009-07-20 15:07:26 -0700172bool findMetadata(const Metadata::Filter& filter, const int32_t val)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700173{
174 // Deal with empty and ANY right away
175 if (filter.isEmpty()) return false;
nikoa64c8c72009-07-20 15:07:26 -0700176 if (filter[0] == Metadata::kAny) return true;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700177
Nicolas Catania48290382009-07-10 13:53:06 -0700178 return filter.indexOf(val) >= 0;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700179}
180
181} // anonymous namespace
182
183
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800184namespace android {
185
Dave Burked681bbb2011-08-30 14:39:17 +0100186static bool checkPermission(const char* permissionString) {
187#ifndef HAVE_ANDROID_OS
188 return true;
189#endif
190 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
191 bool ok = checkCallingPermission(String16(permissionString));
Steve Block29357bc2012-01-06 19:20:56 +0000192 if (!ok) ALOGE("Request requires %s", permissionString);
Dave Burked681bbb2011-08-30 14:39:17 +0100193 return ok;
194}
195
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800196// 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 -0800197/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
198/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
199
200void MediaPlayerService::instantiate() {
201 defaultServiceManager()->addService(
202 String16("media.player"), new MediaPlayerService());
203}
204
205MediaPlayerService::MediaPlayerService()
206{
Steve Block3856b092011-10-20 11:56:00 +0100207 ALOGV("MediaPlayerService created");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800208 mNextConnId = 1;
Gloria Wang9ee159b2011-02-24 14:51:45 -0800209
210 mBatteryAudio.refCount = 0;
211 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
212 mBatteryAudio.deviceOn[i] = 0;
213 mBatteryAudio.lastTime[i] = 0;
214 mBatteryAudio.totalTime[i] = 0;
215 }
216 // speaker is on by default
217 mBatteryAudio.deviceOn[SPEAKER] = 1;
John Grossman44a7e422012-06-21 17:29:24 -0700218
219 MediaPlayerFactory::registerBuiltinFactories();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800220}
221
222MediaPlayerService::~MediaPlayerService()
223{
Steve Block3856b092011-10-20 11:56:00 +0100224 ALOGV("MediaPlayerService destroyed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800225}
226
227sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
228{
Gloria Wangdac6a312009-10-29 15:46:37 -0700229 sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
230 wp<MediaRecorderClient> w = recorder;
231 Mutex::Autolock lock(mLock);
232 mMediaRecorderClients.add(w);
Steve Block3856b092011-10-20 11:56:00 +0100233 ALOGV("Create new media recorder client from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800234 return recorder;
235}
236
Gloria Wangdac6a312009-10-29 15:46:37 -0700237void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
238{
239 Mutex::Autolock lock(mLock);
240 mMediaRecorderClients.remove(client);
Steve Block3856b092011-10-20 11:56:00 +0100241 ALOGV("Delete media recorder client");
Gloria Wangdac6a312009-10-29 15:46:37 -0700242}
243
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800244sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
245{
246 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
Steve Block3856b092011-10-20 11:56:00 +0100247 ALOGV("Create new media retriever from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800248 return retriever;
249}
250
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
Dave Burked681bbb2011-08-30 14:39:17 +0100252 int audioSessionId)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800253{
254 int32_t connId = android_atomic_inc(&mNextConnId);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700255
256 sp<Client> c = new Client(
257 this, pid, connId, client, audioSessionId,
258 IPCThreadState::self()->getCallingUid());
259
Steve Block3856b092011-10-20 11:56:00 +0100260 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
Dave Burked681bbb2011-08-30 14:39:17 +0100261 IPCThreadState::self()->getCallingUid());
262
263 wp<Client> w = c;
264 {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800265 Mutex::Autolock lock(mLock);
266 mClients.add(w);
267 }
Andreas Hubere2b10282010-11-23 11:41:34 -0800268 return c;
269}
270
Andreas Huber318ad9c2009-10-15 13:46:54 -0700271sp<IOMX> MediaPlayerService::getOMX() {
272 Mutex::Autolock autoLock(mLock);
273
274 if (mOMX.get() == NULL) {
275 mOMX = new OMX;
276 }
277
278 return mOMX;
Andreas Huber20111aa2009-07-14 16:56:47 -0700279}
280
Andreas Hubered3e3e02012-03-26 11:13:27 -0700281sp<ICrypto> MediaPlayerService::makeCrypto() {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700282 return new Crypto;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700283}
284
Andreas Huberefbb7812012-09-18 10:36:32 -0700285sp<IHDCP> MediaPlayerService::makeHDCP() {
286 return new HDCP;
287}
288
Jeff Browne1045962012-09-04 21:38:42 -0700289sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
290 const sp<IRemoteDisplayClient>& client, const String8& iface) {
Jeff Brownb0192502012-09-07 17:38:58 -0700291 if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
292 return NULL;
293 }
294
Jeff Brown455d02e2012-09-05 17:48:03 -0700295 return new RemoteDisplay(client, iface.string());
Jeff Browne1045962012-09-04 21:38:42 -0700296}
297
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800298status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
299{
300 const size_t SIZE = 256;
301 char buffer[SIZE];
302 String8 result;
303
304 result.append(" AudioCache\n");
305 if (mHeap != 0) {
306 snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d), device(%s)\n",
307 mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
308 result.append(buffer);
309 }
Scott Fan7d409692013-04-28 10:13:54 +0800310 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 -0800311 mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
312 result.append(buffer);
313 snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
314 mSampleRate, mSize, mError, mCommandComplete?"true":"false");
315 result.append(buffer);
316 ::write(fd, result.string(), result.size());
317 return NO_ERROR;
318}
319
320status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
321{
322 const size_t SIZE = 256;
323 char buffer[SIZE];
324 String8 result;
325
326 result.append(" AudioOutput\n");
327 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
328 mStreamType, mLeftVolume, mRightVolume);
329 result.append(buffer);
330 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Eric Laurentdb354e52012-03-05 17:27:11 -0800331 mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800332 result.append(buffer);
Eric Laurent2beeb502010-07-16 07:43:46 -0700333 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
334 mAuxEffectId, mSendLevel);
335 result.append(buffer);
336
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800337 ::write(fd, result.string(), result.size());
338 if (mTrack != 0) {
339 mTrack->dump(fd, args);
340 }
341 return NO_ERROR;
342}
343
344status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
345{
346 const size_t SIZE = 256;
347 char buffer[SIZE];
348 String8 result;
349 result.append(" Client\n");
350 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
351 mPid, mConnId, mStatus, mLoop?"true": "false");
352 result.append(buffer);
353 write(fd, result.string(), result.size());
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700354 if (mPlayer != NULL) {
355 mPlayer->dump(fd, args);
356 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800357 if (mAudioOutput != 0) {
358 mAudioOutput->dump(fd, args);
359 }
360 write(fd, "\n", 1);
361 return NO_ERROR;
362}
363
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800364status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
365{
366 const size_t SIZE = 256;
367 char buffer[SIZE];
368 String8 result;
369 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
370 snprintf(buffer, SIZE, "Permission Denial: "
371 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
372 IPCThreadState::self()->getCallingPid(),
373 IPCThreadState::self()->getCallingUid());
374 result.append(buffer);
375 } else {
376 Mutex::Autolock lock(mLock);
377 for (int i = 0, n = mClients.size(); i < n; ++i) {
378 sp<Client> c = mClients[i].promote();
379 if (c != 0) c->dump(fd, args);
380 }
James Dongb9141222010-07-08 11:16:11 -0700381 if (mMediaRecorderClients.size() == 0) {
382 result.append(" No media recorder client\n\n");
383 } else {
384 for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
385 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
James Donge579e282011-10-18 22:29:20 -0700386 if (c != 0) {
387 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
388 result.append(buffer);
389 write(fd, result.string(), result.size());
390 result = "\n";
391 c->dump(fd, args);
392 }
James Dongb9141222010-07-08 11:16:11 -0700393 }
Gloria Wangdac6a312009-10-29 15:46:37 -0700394 }
395
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800396 result.append(" Files opened and/or mapped:\n");
Glenn Kasten0512ab52011-05-04 17:58:57 -0700397 snprintf(buffer, SIZE, "/proc/%d/maps", gettid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800398 FILE *f = fopen(buffer, "r");
399 if (f) {
400 while (!feof(f)) {
401 fgets(buffer, SIZE, f);
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700402 if (strstr(buffer, " /storage/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800403 strstr(buffer, " /system/sounds/") ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700404 strstr(buffer, " /data/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800405 strstr(buffer, " /system/media/")) {
406 result.append(" ");
407 result.append(buffer);
408 }
409 }
410 fclose(f);
411 } else {
412 result.append("couldn't open ");
413 result.append(buffer);
414 result.append("\n");
415 }
416
Glenn Kasten0512ab52011-05-04 17:58:57 -0700417 snprintf(buffer, SIZE, "/proc/%d/fd", gettid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800418 DIR *d = opendir(buffer);
419 if (d) {
420 struct dirent *ent;
421 while((ent = readdir(d)) != NULL) {
422 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
Glenn Kasten0512ab52011-05-04 17:58:57 -0700423 snprintf(buffer, SIZE, "/proc/%d/fd/%s", gettid(), ent->d_name);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800424 struct stat s;
425 if (lstat(buffer, &s) == 0) {
426 if ((s.st_mode & S_IFMT) == S_IFLNK) {
427 char linkto[256];
428 int len = readlink(buffer, linkto, sizeof(linkto));
429 if(len > 0) {
430 if(len > 255) {
431 linkto[252] = '.';
432 linkto[253] = '.';
433 linkto[254] = '.';
434 linkto[255] = 0;
435 } else {
436 linkto[len] = 0;
437 }
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700438 if (strstr(linkto, "/storage/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800439 strstr(linkto, "/system/sounds/") == linkto ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700440 strstr(linkto, "/data/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800441 strstr(linkto, "/system/media/") == linkto) {
442 result.append(" ");
443 result.append(buffer);
444 result.append(" -> ");
445 result.append(linkto);
446 result.append("\n");
447 }
448 }
449 } else {
450 result.append(" unexpected type for ");
451 result.append(buffer);
452 result.append("\n");
453 }
454 }
455 }
456 }
457 closedir(d);
458 } else {
459 result.append("couldn't open ");
460 result.append(buffer);
461 result.append("\n");
462 }
463
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800464 bool dumpMem = false;
465 for (size_t i = 0; i < args.size(); i++) {
466 if (args[i] == String16("-m")) {
467 dumpMem = true;
468 }
469 }
470 if (dumpMem) {
James Dong8635b7b2011-03-14 17:01:38 -0700471 dumpMemoryAddresses(fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800472 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800473 }
474 write(fd, result.string(), result.size());
475 return NO_ERROR;
476}
477
478void MediaPlayerService::removeClient(wp<Client> client)
479{
480 Mutex::Autolock lock(mLock);
481 mClients.remove(client);
482}
483
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700484MediaPlayerService::Client::Client(
485 const sp<MediaPlayerService>& service, pid_t pid,
486 int32_t connId, const sp<IMediaPlayerClient>& client,
487 int audioSessionId, uid_t uid)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800488{
Steve Block3856b092011-10-20 11:56:00 +0100489 ALOGV("Client(%d) constructor", connId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800490 mPid = pid;
491 mConnId = connId;
492 mService = service;
493 mClient = client;
494 mLoop = false;
495 mStatus = NO_INIT;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700496 mAudioSessionId = audioSessionId;
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700497 mUID = uid;
John Grossmanc795b642012-02-22 15:38:35 -0800498 mRetransmitEndpointValid = false;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700499
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800500#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000501 ALOGD("create Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800502 mAntagonizer = new Antagonizer(notify, this);
503#endif
504}
505
506MediaPlayerService::Client::~Client()
507{
Steve Block3856b092011-10-20 11:56:00 +0100508 ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800509 mAudioOutput.clear();
510 wp<Client> client(this);
511 disconnect();
512 mService->removeClient(client);
513}
514
515void MediaPlayerService::Client::disconnect()
516{
Steve Block3856b092011-10-20 11:56:00 +0100517 ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800518 // grab local reference and clear main reference to prevent future
519 // access to object
520 sp<MediaPlayerBase> p;
521 {
522 Mutex::Autolock l(mLock);
523 p = mPlayer;
beanzdcfefde2012-11-05 09:51:43 +0800524 mClient.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800525 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700526
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800527 mPlayer.clear();
528
529 // clear the notification to prevent callbacks to dead client
530 // and reset the player. We assume the player will serialize
531 // access to itself if necessary.
532 if (p != 0) {
533 p->setNotifyCallback(0, 0);
534#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000535 ALOGD("kill Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800536 mAntagonizer->kill();
537#endif
538 p->reset();
539 }
540
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700541 disconnectNativeWindow();
542
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800543 IPCThreadState::self()->flushCommands();
544}
545
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800546sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
547{
548 // determine if we have the right player type
549 sp<MediaPlayerBase> p = mPlayer;
550 if ((p != NULL) && (p->playerType() != playerType)) {
Steve Block3856b092011-10-20 11:56:00 +0100551 ALOGV("delete player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800552 p.clear();
553 }
554 if (p == NULL) {
John Grossman44a7e422012-06-21 17:29:24 -0700555 p = MediaPlayerFactory::createPlayer(playerType, this, notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800556 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700557
Jason Simmonsdb29e522011-08-12 13:46:55 -0700558 if (p != NULL) {
559 p->setUID(mUID);
560 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700561
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800562 return p;
563}
564
John Grossmanc795b642012-02-22 15:38:35 -0800565sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
566 player_type playerType)
567{
568 ALOGV("player type = %d", playerType);
569
570 // create the right type of player
571 sp<MediaPlayerBase> p = createPlayer(playerType);
572 if (p == NULL) {
573 return p;
574 }
575
576 if (!p->hardwareOutput()) {
577 mAudioOutput = new AudioOutput(mAudioSessionId);
578 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
579 }
580
581 return p;
582}
583
584void MediaPlayerService::Client::setDataSource_post(
585 const sp<MediaPlayerBase>& p,
586 status_t status)
587{
588 ALOGV(" setDataSource");
589 mStatus = status;
590 if (mStatus != OK) {
591 ALOGE(" error: %d", mStatus);
592 return;
593 }
594
595 // Set the re-transmission endpoint if one was chosen.
596 if (mRetransmitEndpointValid) {
597 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
598 if (mStatus != NO_ERROR) {
599 ALOGE("setRetransmitEndpoint error: %d", mStatus);
600 }
601 }
602
603 if (mStatus == OK) {
604 mPlayer = p;
605 }
606}
607
Andreas Huber2db84552010-01-28 11:19:57 -0800608status_t MediaPlayerService::Client::setDataSource(
609 const char *url, const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800610{
Steve Block3856b092011-10-20 11:56:00 +0100611 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800612 if (url == NULL)
613 return UNKNOWN_ERROR;
614
Dave Burked681bbb2011-08-30 14:39:17 +0100615 if ((strncmp(url, "http://", 7) == 0) ||
616 (strncmp(url, "https://", 8) == 0) ||
617 (strncmp(url, "rtsp://", 7) == 0)) {
618 if (!checkPermission("android.permission.INTERNET")) {
619 return PERMISSION_DENIED;
620 }
621 }
622
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800623 if (strncmp(url, "content://", 10) == 0) {
624 // get a filedescriptor for the content Uri and
625 // pass it to the setDataSource(fd) method
626
627 String16 url16(url);
628 int fd = android::openContentProviderFile(url16);
629 if (fd < 0)
630 {
Steve Block29357bc2012-01-06 19:20:56 +0000631 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800632 return UNKNOWN_ERROR;
633 }
634 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
635 close(fd);
636 return mStatus;
637 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700638 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800639 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
640 if (p == NULL) {
641 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800642 }
643
John Grossmanc795b642012-02-22 15:38:35 -0800644 setDataSource_post(p, p->setDataSource(url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800645 return mStatus;
646 }
647}
648
649status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
650{
Steve Block3856b092011-10-20 11:56:00 +0100651 ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800652 struct stat sb;
653 int ret = fstat(fd, &sb);
654 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000655 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800656 return UNKNOWN_ERROR;
657 }
658
Steve Block3856b092011-10-20 11:56:00 +0100659 ALOGV("st_dev = %llu", sb.st_dev);
660 ALOGV("st_mode = %u", sb.st_mode);
661 ALOGV("st_uid = %lu", sb.st_uid);
662 ALOGV("st_gid = %lu", sb.st_gid);
663 ALOGV("st_size = %llu", sb.st_size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800664
665 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000666 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800667 ::close(fd);
668 return UNKNOWN_ERROR;
669 }
670 if (offset + length > sb.st_size) {
671 length = sb.st_size - offset;
Steve Block3856b092011-10-20 11:56:00 +0100672 ALOGV("calculated length = %lld", length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800673 }
674
John Grossman44a7e422012-06-21 17:29:24 -0700675 player_type playerType = MediaPlayerFactory::getPlayerType(this,
676 fd,
677 offset,
678 length);
John Grossmanc795b642012-02-22 15:38:35 -0800679 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
680 if (p == NULL) {
681 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800682 }
683
684 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800685 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800686 return mStatus;
687}
688
Andreas Hubere2b10282010-11-23 11:41:34 -0800689status_t MediaPlayerService::Client::setDataSource(
690 const sp<IStreamSource> &source) {
691 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700692 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800693 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800694 if (p == NULL) {
695 return NO_INIT;
696 }
697
Andreas Hubere2b10282010-11-23 11:41:34 -0800698 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800699 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800700 return mStatus;
701}
702
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700703void MediaPlayerService::Client::disconnectNativeWindow() {
704 if (mConnectedWindow != NULL) {
705 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
706 NATIVE_WINDOW_API_MEDIA);
707
708 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000709 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700710 strerror(-err), err);
711 }
712 }
713 mConnectedWindow.clear();
714}
715
Glenn Kasten11731182011-02-08 17:26:17 -0800716status_t MediaPlayerService::Client::setVideoSurfaceTexture(
717 const sp<ISurfaceTexture>& surfaceTexture)
718{
Steve Block3856b092011-10-20 11:56:00 +0100719 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800720 sp<MediaPlayerBase> p = getPlayer();
721 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700722
723 sp<IBinder> binder(surfaceTexture == NULL ? NULL :
724 surfaceTexture->asBinder());
725 if (mConnectedWindowBinder == binder) {
726 return OK;
727 }
728
729 sp<ANativeWindow> anw;
730 if (surfaceTexture != NULL) {
731 anw = new SurfaceTextureClient(surfaceTexture);
732 status_t err = native_window_api_connect(anw.get(),
733 NATIVE_WINDOW_API_MEDIA);
734
735 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000736 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700737 // Note that we must do the reset before disconnecting from the ANW.
738 // Otherwise queue/dequeue calls could be made on the disconnected
739 // ANW, which may result in errors.
740 reset();
741
742 disconnectNativeWindow();
743
744 return err;
745 }
746 }
747
748 // Note that we must set the player's new SurfaceTexture before
749 // disconnecting the old one. Otherwise queue/dequeue calls could be made
750 // on the disconnected ANW, which may result in errors.
751 status_t err = p->setVideoSurfaceTexture(surfaceTexture);
752
753 disconnectNativeWindow();
754
755 mConnectedWindow = anw;
756
757 if (err == OK) {
758 mConnectedWindowBinder = binder;
759 } else {
760 disconnectNativeWindow();
761 }
762
763 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800764}
765
Nicolas Catania1d187f12009-05-12 23:25:55 -0700766status_t MediaPlayerService::Client::invoke(const Parcel& request,
767 Parcel *reply)
768{
769 sp<MediaPlayerBase> p = getPlayer();
770 if (p == NULL) return UNKNOWN_ERROR;
771 return p->invoke(request, reply);
772}
773
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700774// This call doesn't need to access the native player.
775status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
776{
777 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700778 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700779
Nicolas Catania48290382009-07-10 13:53:06 -0700780 if (unmarshallFilter(filter, &allow, &status) &&
781 unmarshallFilter(filter, &drop, &status)) {
782 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700783
784 mMetadataAllow = allow;
785 mMetadataDrop = drop;
786 }
787 return status;
788}
789
Nicolas Catania48290382009-07-10 13:53:06 -0700790status_t MediaPlayerService::Client::getMetadata(
791 bool update_only, bool apply_filter, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700792{
nikoa64c8c72009-07-20 15:07:26 -0700793 sp<MediaPlayerBase> player = getPlayer();
794 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700795
nikod608a812009-07-16 16:39:53 -0700796 status_t status;
797 // Placeholder for the return code, updated by the caller.
798 reply->writeInt32(-1);
799
nikoa64c8c72009-07-20 15:07:26 -0700800 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700801
802 // We don't block notifications while we fetch the data. We clear
803 // mMetadataUpdated first so we don't lose notifications happening
804 // during the rest of this call.
805 {
806 Mutex::Autolock lock(mLock);
807 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700808 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700809 }
810 mMetadataUpdated.clear();
811 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700812
nikoa64c8c72009-07-20 15:07:26 -0700813 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700814
nikoa64c8c72009-07-20 15:07:26 -0700815 metadata.appendHeader();
816 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700817
818 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700819 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000820 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700821 return status;
822 }
823
824 // FIXME: Implement filtering on the result. Not critical since
825 // filtering takes place on the update notifications already. This
826 // would be when all the metadata are fetch and a filter is set.
827
nikod608a812009-07-16 16:39:53 -0700828 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700829 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700830 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700831}
832
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800833status_t MediaPlayerService::Client::prepareAsync()
834{
Steve Block3856b092011-10-20 11:56:00 +0100835 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800836 sp<MediaPlayerBase> p = getPlayer();
837 if (p == 0) return UNKNOWN_ERROR;
838 status_t ret = p->prepareAsync();
839#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000840 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800841 if (ret == NO_ERROR) mAntagonizer->start();
842#endif
843 return ret;
844}
845
846status_t MediaPlayerService::Client::start()
847{
Steve Block3856b092011-10-20 11:56:00 +0100848 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800849 sp<MediaPlayerBase> p = getPlayer();
850 if (p == 0) return UNKNOWN_ERROR;
851 p->setLooping(mLoop);
852 return p->start();
853}
854
855status_t MediaPlayerService::Client::stop()
856{
Steve Block3856b092011-10-20 11:56:00 +0100857 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800858 sp<MediaPlayerBase> p = getPlayer();
859 if (p == 0) return UNKNOWN_ERROR;
860 return p->stop();
861}
862
863status_t MediaPlayerService::Client::pause()
864{
Steve Block3856b092011-10-20 11:56:00 +0100865 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800866 sp<MediaPlayerBase> p = getPlayer();
867 if (p == 0) return UNKNOWN_ERROR;
868 return p->pause();
869}
870
871status_t MediaPlayerService::Client::isPlaying(bool* state)
872{
873 *state = false;
874 sp<MediaPlayerBase> p = getPlayer();
875 if (p == 0) return UNKNOWN_ERROR;
876 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +0100877 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800878 return NO_ERROR;
879}
880
881status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
882{
Steve Block3856b092011-10-20 11:56:00 +0100883 ALOGV("getCurrentPosition");
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->getCurrentPosition(msec);
887 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +0100888 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800889 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000890 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800891 }
892 return ret;
893}
894
895status_t MediaPlayerService::Client::getDuration(int *msec)
896{
Steve Block3856b092011-10-20 11:56:00 +0100897 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800898 sp<MediaPlayerBase> p = getPlayer();
899 if (p == 0) return UNKNOWN_ERROR;
900 status_t ret = p->getDuration(msec);
901 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +0100902 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800903 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000904 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800905 }
906 return ret;
907}
908
Marco Nelissen6b74d672012-02-28 16:07:44 -0800909status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
910 ALOGV("setNextPlayer");
911 Mutex::Autolock l(mLock);
912 sp<Client> c = static_cast<Client*>(player.get());
913 mNextClient = c;
John Grossman2e5f22e2012-08-24 14:47:25 -0700914
915 if (c != NULL) {
916 if (mAudioOutput != NULL) {
917 mAudioOutput->setNextOutput(c->mAudioOutput);
918 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
919 ALOGE("no current audio output");
920 }
921
922 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
923 mPlayer->setNextPlayer(mNextClient->getPlayer());
924 }
Marco Nelissen6b74d672012-02-28 16:07:44 -0800925 }
John Grossman2e5f22e2012-08-24 14:47:25 -0700926
Marco Nelissen6b74d672012-02-28 16:07:44 -0800927 return OK;
928}
929
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800930status_t MediaPlayerService::Client::seekTo(int msec)
931{
Steve Block3856b092011-10-20 11:56:00 +0100932 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800933 sp<MediaPlayerBase> p = getPlayer();
934 if (p == 0) return UNKNOWN_ERROR;
935 return p->seekTo(msec);
936}
937
938status_t MediaPlayerService::Client::reset()
939{
Steve Block3856b092011-10-20 11:56:00 +0100940 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -0800941 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800942 sp<MediaPlayerBase> p = getPlayer();
943 if (p == 0) return UNKNOWN_ERROR;
944 return p->reset();
945}
946
Glenn Kastenfff6d712012-01-12 16:38:12 -0800947status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800948{
Steve Block3856b092011-10-20 11:56:00 +0100949 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800950 // TODO: for hardware output, call player instead
951 Mutex::Autolock l(mLock);
952 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
953 return NO_ERROR;
954}
955
956status_t MediaPlayerService::Client::setLooping(int loop)
957{
Steve Block3856b092011-10-20 11:56:00 +0100958 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800959 mLoop = loop;
960 sp<MediaPlayerBase> p = getPlayer();
961 if (p != 0) return p->setLooping(loop);
962 return NO_ERROR;
963}
964
965status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
966{
Steve Block3856b092011-10-20 11:56:00 +0100967 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -0800968
969 // for hardware output, call player instead
970 sp<MediaPlayerBase> p = getPlayer();
971 {
972 Mutex::Autolock l(mLock);
973 if (p != 0 && p->hardwareOutput()) {
974 MediaPlayerHWInterface* hwp =
975 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
976 return hwp->setVolume(leftVolume, rightVolume);
977 } else {
978 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
979 return NO_ERROR;
980 }
981 }
982
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800983 return NO_ERROR;
984}
985
Eric Laurent2beeb502010-07-16 07:43:46 -0700986status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
987{
Steve Block3856b092011-10-20 11:56:00 +0100988 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -0700989 Mutex::Autolock l(mLock);
990 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
991 return NO_ERROR;
992}
993
994status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
995{
Steve Block3856b092011-10-20 11:56:00 +0100996 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -0700997 Mutex::Autolock l(mLock);
998 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
999 return NO_ERROR;
1000}
Nicolas Catania48290382009-07-10 13:53:06 -07001001
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001002status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001003 ALOGV("[%d] setParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001004 sp<MediaPlayerBase> p = getPlayer();
1005 if (p == 0) return UNKNOWN_ERROR;
1006 return p->setParameter(key, request);
1007}
1008
1009status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001010 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001011 sp<MediaPlayerBase> p = getPlayer();
1012 if (p == 0) return UNKNOWN_ERROR;
1013 return p->getParameter(key, reply);
1014}
1015
John Grossmanc795b642012-02-22 15:38:35 -08001016status_t MediaPlayerService::Client::setRetransmitEndpoint(
1017 const struct sockaddr_in* endpoint) {
1018
1019 if (NULL != endpoint) {
1020 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1021 uint16_t p = ntohs(endpoint->sin_port);
1022 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1023 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1024 } else {
1025 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1026 }
1027
1028 sp<MediaPlayerBase> p = getPlayer();
1029
1030 // Right now, the only valid time to set a retransmit endpoint is before
1031 // player selection has been made (since the presence or absence of a
1032 // retransmit endpoint is going to determine which player is selected during
1033 // setDataSource).
1034 if (p != 0) return INVALID_OPERATION;
1035
1036 if (NULL != endpoint) {
1037 mRetransmitEndpoint = *endpoint;
1038 mRetransmitEndpointValid = true;
1039 } else {
1040 mRetransmitEndpointValid = false;
1041 }
1042
1043 return NO_ERROR;
1044}
1045
John Grossman44a7e422012-06-21 17:29:24 -07001046status_t MediaPlayerService::Client::getRetransmitEndpoint(
1047 struct sockaddr_in* endpoint)
1048{
1049 if (NULL == endpoint)
1050 return BAD_VALUE;
1051
1052 sp<MediaPlayerBase> p = getPlayer();
1053
1054 if (p != NULL)
1055 return p->getRetransmitEndpoint(endpoint);
1056
1057 if (!mRetransmitEndpointValid)
1058 return NO_INIT;
1059
1060 *endpoint = mRetransmitEndpoint;
1061
1062 return NO_ERROR;
1063}
1064
Gloria Wangb483c472011-04-11 17:23:27 -07001065void MediaPlayerService::Client::notify(
1066 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001067{
1068 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001069 if (client == NULL) {
1070 return;
1071 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001072
James Dongb8a98252012-08-26 16:13:03 -07001073 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001074 {
1075 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001076 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001077 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001078 if (client->mAudioOutput != NULL)
1079 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001080 client->mNextClient->start();
1081 client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1082 }
1083 }
1084
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001085 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001086 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001087 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001088
1089 if(client->shouldDropMetadata(metadata_type)) {
1090 return;
1091 }
1092
1093 // Update the list of metadata that have changed. getMetadata
1094 // also access mMetadataUpdated and clears it.
1095 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001096 }
James Dongb8a98252012-08-26 16:13:03 -07001097
1098 if (c != NULL) {
1099 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1100 c->notify(msg, ext1, ext2, obj);
1101 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001102}
1103
Nicolas Catania48290382009-07-10 13:53:06 -07001104
nikoa64c8c72009-07-20 15:07:26 -07001105bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001106{
Nicolas Catania48290382009-07-10 13:53:06 -07001107 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001108
Nicolas Catania48290382009-07-10 13:53:06 -07001109 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001110 return true;
1111 }
1112
Nicolas Catania48290382009-07-10 13:53:06 -07001113 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001114 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001115 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001116 return true;
1117 }
1118}
1119
Nicolas Catania48290382009-07-10 13:53:06 -07001120
nikoa64c8c72009-07-20 15:07:26 -07001121void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001122 Mutex::Autolock lock(mLock);
1123 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1124 mMetadataUpdated.add(metadata_type);
1125 }
1126}
1127
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001128#if CALLBACK_ANTAGONIZER
1129const int Antagonizer::interval = 10000; // 10 msecs
1130
1131Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1132 mExit(false), mActive(false), mClient(client), mCb(cb)
1133{
1134 createThread(callbackThread, this);
1135}
1136
1137void Antagonizer::kill()
1138{
1139 Mutex::Autolock _l(mLock);
1140 mActive = false;
1141 mExit = true;
1142 mCondition.wait(mLock);
1143}
1144
1145int Antagonizer::callbackThread(void* user)
1146{
Steve Blockb8a80522011-12-20 16:23:08 +00001147 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001148 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1149 while (!p->mExit) {
1150 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001151 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001152 p->mCb(p->mClient, 0, 0, 0);
1153 }
1154 usleep(interval);
1155 }
1156 Mutex::Autolock _l(p->mLock);
1157 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001158 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001159 return 0;
1160}
1161#endif
1162
1163static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
1164
Glenn Kastene1c39622012-01-04 09:36:37 -08001165sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001166{
Steve Block3856b092011-10-20 11:56:00 +01001167 ALOGV("decode(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001168 sp<MemoryBase> mem;
1169 sp<MediaPlayerBase> player;
1170
1171 // Protect our precious, precious DRMd ringtones by only allowing
1172 // decoding of http, but not filesystem paths or content Uris.
1173 // If the application wants to decode those, it should open a
1174 // filedescriptor for them and use that.
1175 if (url != NULL && strncmp(url, "http://", 7) != 0) {
Steve Blockb8a80522011-12-20 16:23:08 +00001176 ALOGD("Can't decode %s by path, use filedescriptor instead", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001177 return mem;
1178 }
1179
John Grossman44a7e422012-06-21 17:29:24 -07001180 player_type playerType =
1181 MediaPlayerFactory::getPlayerType(NULL /* client */, url);
Steve Block3856b092011-10-20 11:56:00 +01001182 ALOGV("player type = %d", playerType);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001183
1184 // create the right type of player
1185 sp<AudioCache> cache = new AudioCache(url);
John Grossman44a7e422012-06-21 17:29:24 -07001186 player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001187 if (player == NULL) goto Exit;
1188 if (player->hardwareOutput()) goto Exit;
1189
1190 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1191
1192 // set data source
1193 if (player->setDataSource(url) != NO_ERROR) goto Exit;
1194
Steve Block3856b092011-10-20 11:56:00 +01001195 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001196 player->prepareAsync();
1197
Steve Block3856b092011-10-20 11:56:00 +01001198 ALOGV("wait for prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001199 if (cache->wait() != NO_ERROR) goto Exit;
1200
Steve Block3856b092011-10-20 11:56:00 +01001201 ALOGV("start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001202 player->start();
1203
Steve Block3856b092011-10-20 11:56:00 +01001204 ALOGV("wait for playback complete");
Eric Laurent9cb839a2011-09-27 09:48:56 -07001205 cache->wait();
1206 // in case of error, return what was successfully decoded.
1207 if (cache->size() == 0) {
1208 goto Exit;
1209 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001210
1211 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
1212 *pSampleRate = cache->sampleRate();
1213 *pNumChannels = cache->channelCount();
Glenn Kastene1c39622012-01-04 09:36:37 -08001214 *pFormat = cache->format();
Steve Block3856b092011-10-20 11:56:00 +01001215 ALOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001216
1217Exit:
1218 if (player != 0) player->reset();
1219 return mem;
1220}
1221
Glenn Kastene1c39622012-01-04 09:36:37 -08001222sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001223{
Steve Block3856b092011-10-20 11:56:00 +01001224 ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001225 sp<MemoryBase> mem;
1226 sp<MediaPlayerBase> player;
1227
John Grossman44a7e422012-06-21 17:29:24 -07001228 player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
1229 fd,
1230 offset,
1231 length);
Steve Block3856b092011-10-20 11:56:00 +01001232 ALOGV("player type = %d", playerType);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001233
1234 // create the right type of player
1235 sp<AudioCache> cache = new AudioCache("decode_fd");
John Grossman44a7e422012-06-21 17:29:24 -07001236 player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001237 if (player == NULL) goto Exit;
1238 if (player->hardwareOutput()) goto Exit;
1239
1240 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1241
1242 // set data source
1243 if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
1244
Steve Block3856b092011-10-20 11:56:00 +01001245 ALOGV("prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001246 player->prepareAsync();
1247
Steve Block3856b092011-10-20 11:56:00 +01001248 ALOGV("wait for prepare");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001249 if (cache->wait() != NO_ERROR) goto Exit;
1250
Steve Block3856b092011-10-20 11:56:00 +01001251 ALOGV("start");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001252 player->start();
1253
Steve Block3856b092011-10-20 11:56:00 +01001254 ALOGV("wait for playback complete");
Eric Laurent9cb839a2011-09-27 09:48:56 -07001255 cache->wait();
1256 // in case of error, return what was successfully decoded.
1257 if (cache->size() == 0) {
1258 goto Exit;
1259 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001260
1261 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
1262 *pSampleRate = cache->sampleRate();
1263 *pNumChannels = cache->channelCount();
1264 *pFormat = cache->format();
Steve Block3856b092011-10-20 11:56:00 +01001265 ALOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001266
1267Exit:
1268 if (player != 0) player->reset();
1269 ::close(fd);
1270 return mem;
1271}
1272
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001273
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001274#undef LOG_TAG
1275#define LOG_TAG "AudioSink"
Eric Laurenta514bdb2010-06-21 09:27:30 -07001276MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
Andreas Huber20111aa2009-07-14 16:56:47 -07001277 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001278 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001279 mCallbackData(NULL),
Marco Nelissen4110c102012-03-29 09:31:28 -07001280 mBytesWritten(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001281 mSessionId(sessionId),
1282 mFlags(AUDIO_OUTPUT_FLAG_NONE) {
Steve Block3856b092011-10-20 11:56:00 +01001283 ALOGV("AudioOutput(%d)", sessionId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001284 mTrack = 0;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001285 mRecycledTrack = 0;
Dima Zavinfce7a472011-04-19 22:30:36 -07001286 mStreamType = AUDIO_STREAM_MUSIC;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001287 mLeftVolume = 1.0;
1288 mRightVolume = 1.0;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001289 mPlaybackRatePermille = 1000;
1290 mSampleRateHz = 0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001291 mMsecsPerFrame = 0;
Eric Laurent2beeb502010-07-16 07:43:46 -07001292 mAuxEffectId = 0;
1293 mSendLevel = 0.0;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001294 setMinBufferCount();
1295}
1296
1297MediaPlayerService::AudioOutput::~AudioOutput()
1298{
1299 close();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001300 delete mRecycledTrack;
1301 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001302}
1303
1304void MediaPlayerService::AudioOutput::setMinBufferCount()
1305{
1306 char value[PROPERTY_VALUE_MAX];
1307 if (property_get("ro.kernel.qemu", value, 0)) {
1308 mIsOnEmulator = true;
1309 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1310 }
1311}
1312
1313bool MediaPlayerService::AudioOutput::isOnEmulator()
1314{
1315 setMinBufferCount();
1316 return mIsOnEmulator;
1317}
1318
1319int MediaPlayerService::AudioOutput::getMinBufferCount()
1320{
1321 setMinBufferCount();
1322 return mMinBufferCount;
1323}
1324
1325ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1326{
1327 if (mTrack == 0) return NO_INIT;
1328 return mTrack->frameCount() * frameSize();
1329}
1330
1331ssize_t MediaPlayerService::AudioOutput::frameCount() const
1332{
1333 if (mTrack == 0) return NO_INIT;
1334 return mTrack->frameCount();
1335}
1336
1337ssize_t MediaPlayerService::AudioOutput::channelCount() const
1338{
1339 if (mTrack == 0) return NO_INIT;
1340 return mTrack->channelCount();
1341}
1342
1343ssize_t MediaPlayerService::AudioOutput::frameSize() const
1344{
1345 if (mTrack == 0) return NO_INIT;
1346 return mTrack->frameSize();
1347}
1348
1349uint32_t MediaPlayerService::AudioOutput::latency () const
1350{
Eric Laurentdb354e52012-03-05 17:27:11 -08001351 if (mTrack == 0) return 0;
1352 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001353}
1354
1355float MediaPlayerService::AudioOutput::msecsPerFrame() const
1356{
1357 return mMsecsPerFrame;
1358}
1359
Marco Nelissen4110c102012-03-29 09:31:28 -07001360status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001361{
1362 if (mTrack == 0) return NO_INIT;
1363 return mTrack->getPosition(position);
1364}
1365
Marco Nelissen4110c102012-03-29 09:31:28 -07001366status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1367{
1368 if (mTrack == 0) return NO_INIT;
1369 *frameswritten = mBytesWritten / frameSize();
1370 return OK;
1371}
1372
Andreas Huber20111aa2009-07-14 16:56:47 -07001373status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001374 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1375 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001376 AudioCallback cb, void *cookie,
1377 audio_output_flags_t flags)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001378{
Andreas Huber20111aa2009-07-14 16:56:47 -07001379 mCallback = cb;
1380 mCallbackCookie = cookie;
1381
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001382 // Check argument "bufferCount" against the mininum buffer count
1383 if (bufferCount < mMinBufferCount) {
Steve Blockb8a80522011-12-20 16:23:08 +00001384 ALOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001385 bufferCount = mMinBufferCount;
1386
1387 }
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001388 ALOGV("open(%u, %d, 0x%x, %d, %d, %d)", sampleRate, channelCount, channelMask,
1389 format, bufferCount, mSessionId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001390 int afSampleRate;
1391 int afFrameCount;
Eric Laurent1948eb32012-04-13 16:50:19 -07001392 uint32_t frameCount;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001393
1394 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1395 return NO_INIT;
1396 }
1397 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1398 return NO_INIT;
1399 }
1400
1401 frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
Andreas Huber20111aa2009-07-14 16:56:47 -07001402
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001403 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001404 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001405 if (0 == channelMask) {
1406 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1407 return NO_INIT;
1408 }
1409 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001410
Andreas Huber20111aa2009-07-14 16:56:47 -07001411 AudioTrack *t;
Marco Nelissen67295b52012-06-11 14:52:53 -07001412 CallbackData *newcbd = NULL;
Andreas Huber20111aa2009-07-14 16:56:47 -07001413 if (mCallback != NULL) {
Marco Nelissen67295b52012-06-11 14:52:53 -07001414 newcbd = new CallbackData(this);
Andreas Huber20111aa2009-07-14 16:56:47 -07001415 t = new AudioTrack(
Eric Laurentc2f1f072009-07-17 12:17:14 -07001416 mStreamType,
1417 sampleRate,
1418 format,
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001419 channelMask,
Eric Laurentc2f1f072009-07-17 12:17:14 -07001420 frameCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001421 flags,
Eric Laurentc2f1f072009-07-17 12:17:14 -07001422 CallbackWrapper,
Marco Nelissen67295b52012-06-11 14:52:53 -07001423 newcbd,
Glenn Kasten17a736c2012-02-14 08:52:15 -08001424 0, // notification frames
Eric Laurenta514bdb2010-06-21 09:27:30 -07001425 mSessionId);
Andreas Huber20111aa2009-07-14 16:56:47 -07001426 } else {
1427 t = new AudioTrack(
Eric Laurentc2f1f072009-07-17 12:17:14 -07001428 mStreamType,
1429 sampleRate,
1430 format,
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001431 channelMask,
Eric Laurenta514bdb2010-06-21 09:27:30 -07001432 frameCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001433 flags,
Eric Laurenta514bdb2010-06-21 09:27:30 -07001434 NULL,
1435 NULL,
1436 0,
1437 mSessionId);
Andreas Huber20111aa2009-07-14 16:56:47 -07001438 }
1439
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001440 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
Steve Block29357bc2012-01-06 19:20:56 +00001441 ALOGE("Unable to create audio track");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001442 delete t;
Marco Nelissen67295b52012-06-11 14:52:53 -07001443 delete newcbd;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001444 return NO_INIT;
1445 }
1446
Marco Nelissen67295b52012-06-11 14:52:53 -07001447
1448 if (mRecycledTrack) {
1449 // check if the existing track can be reused as-is, or if a new track needs to be created.
1450
1451 bool reuse = true;
1452 if ((mCallbackData == NULL && mCallback != NULL) ||
1453 (mCallbackData != NULL && mCallback == NULL)) {
1454 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1455 ALOGV("can't chain callback and write");
1456 reuse = false;
1457 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
1458 (mRecycledTrack->channelCount() != channelCount) ||
1459 (mRecycledTrack->frameCount() != t->frameCount())) {
1460 ALOGV("samplerate, channelcount or framecount differ: %d/%d Hz, %d/%d ch, %d/%d frames",
1461 mRecycledTrack->getSampleRate(), sampleRate,
1462 mRecycledTrack->channelCount(), channelCount,
1463 mRecycledTrack->frameCount(), t->frameCount());
1464 reuse = false;
1465 } else if (flags != mFlags) {
1466 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1467 reuse = false;
1468 }
1469 if (reuse) {
1470 ALOGV("chaining to next output");
1471 close();
1472 mTrack = mRecycledTrack;
1473 mRecycledTrack = NULL;
1474 if (mCallbackData != NULL) {
1475 mCallbackData->setOutput(this);
1476 }
1477 delete t;
1478 delete newcbd;
1479 return OK;
1480 }
1481
1482 // if we're not going to reuse the track, unblock and flush it
1483 if (mCallbackData != NULL) {
1484 mCallbackData->setOutput(NULL);
1485 mCallbackData->endTrackSwitch();
1486 }
1487 mRecycledTrack->flush();
1488 delete mRecycledTrack;
1489 mRecycledTrack = NULL;
1490 delete mCallbackData;
1491 mCallbackData = NULL;
1492 close();
1493 }
1494
1495 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001496 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001497 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001498
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001499 mSampleRateHz = sampleRate;
Eric Laurent1948eb32012-04-13 16:50:19 -07001500 mFlags = flags;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001501 mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
Marco Nelissen99448602012-04-02 12:16:49 -07001502 uint32_t pos;
1503 if (t->getPosition(&pos) == OK) {
1504 mBytesWritten = uint64_t(pos) * t->frameSize();
1505 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001506 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001507
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001508 status_t res = t->setSampleRate(mPlaybackRatePermille * mSampleRateHz / 1000);
1509 if (res != NO_ERROR) {
1510 return res;
1511 }
Eric Laurent2beeb502010-07-16 07:43:46 -07001512 t->setAuxEffectSendLevel(mSendLevel);
1513 return t->attachAuxEffect(mAuxEffectId);;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001514}
1515
1516void MediaPlayerService::AudioOutput::start()
1517{
Steve Block3856b092011-10-20 11:56:00 +01001518 ALOGV("start");
Marco Nelissen6b74d672012-02-28 16:07:44 -08001519 if (mCallbackData != NULL) {
1520 mCallbackData->endTrackSwitch();
1521 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001522 if (mTrack) {
1523 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001524 mTrack->setAuxEffectSendLevel(mSendLevel);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001525 mTrack->start();
1526 }
1527}
1528
Marco Nelissen6b74d672012-02-28 16:07:44 -08001529void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
1530 mNextOutput = nextOutput;
1531}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001532
1533
Marco Nelissen6b74d672012-02-28 16:07:44 -08001534void MediaPlayerService::AudioOutput::switchToNextOutput() {
1535 ALOGV("switchToNextOutput");
1536 if (mNextOutput != NULL) {
1537 if (mCallbackData != NULL) {
1538 mCallbackData->beginTrackSwitch();
1539 }
1540 delete mNextOutput->mCallbackData;
1541 mNextOutput->mCallbackData = mCallbackData;
1542 mCallbackData = NULL;
1543 mNextOutput->mRecycledTrack = mTrack;
1544 mTrack = NULL;
1545 mNextOutput->mSampleRateHz = mSampleRateHz;
1546 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
Marco Nelissen4110c102012-03-29 09:31:28 -07001547 mNextOutput->mBytesWritten = mBytesWritten;
Marco Nelissend791e092012-06-11 17:00:59 -07001548 mNextOutput->mFlags = mFlags;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001549 }
1550}
1551
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001552ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
1553{
Andreas Huber20111aa2009-07-14 16:56:47 -07001554 LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
1555
Steve Block3856b092011-10-20 11:56:00 +01001556 //ALOGV("write(%p, %u)", buffer, size);
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001557 if (mTrack) {
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001558 ssize_t ret = mTrack->write(buffer, size);
Marco Nelissen4110c102012-03-29 09:31:28 -07001559 mBytesWritten += ret;
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001560 return ret;
1561 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001562 return NO_INIT;
1563}
1564
1565void MediaPlayerService::AudioOutput::stop()
1566{
Steve Block3856b092011-10-20 11:56:00 +01001567 ALOGV("stop");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001568 if (mTrack) mTrack->stop();
1569}
1570
1571void MediaPlayerService::AudioOutput::flush()
1572{
Steve Block3856b092011-10-20 11:56:00 +01001573 ALOGV("flush");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001574 if (mTrack) mTrack->flush();
1575}
1576
1577void MediaPlayerService::AudioOutput::pause()
1578{
Steve Block3856b092011-10-20 11:56:00 +01001579 ALOGV("pause");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001580 if (mTrack) mTrack->pause();
1581}
1582
1583void MediaPlayerService::AudioOutput::close()
1584{
Steve Block3856b092011-10-20 11:56:00 +01001585 ALOGV("close");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001586 delete mTrack;
1587 mTrack = 0;
1588}
1589
1590void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1591{
Steve Block3856b092011-10-20 11:56:00 +01001592 ALOGV("setVolume(%f, %f)", left, right);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001593 mLeftVolume = left;
1594 mRightVolume = right;
1595 if (mTrack) {
1596 mTrack->setVolume(left, right);
1597 }
1598}
1599
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001600status_t MediaPlayerService::AudioOutput::setPlaybackRatePermille(int32_t ratePermille)
1601{
1602 ALOGV("setPlaybackRatePermille(%d)", ratePermille);
1603 status_t res = NO_ERROR;
1604 if (mTrack) {
1605 res = mTrack->setSampleRate(ratePermille * mSampleRateHz / 1000);
1606 } else {
1607 res = NO_INIT;
1608 }
1609 mPlaybackRatePermille = ratePermille;
1610 if (mSampleRateHz != 0) {
1611 mMsecsPerFrame = mPlaybackRatePermille / (float) mSampleRateHz;
1612 }
1613 return res;
1614}
1615
Eric Laurent2beeb502010-07-16 07:43:46 -07001616status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
1617{
Steve Block3856b092011-10-20 11:56:00 +01001618 ALOGV("setAuxEffectSendLevel(%f)", level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001619 mSendLevel = level;
1620 if (mTrack) {
1621 return mTrack->setAuxEffectSendLevel(level);
1622 }
1623 return NO_ERROR;
1624}
1625
1626status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
1627{
Steve Block3856b092011-10-20 11:56:00 +01001628 ALOGV("attachAuxEffect(%d)", effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001629 mAuxEffectId = effectId;
1630 if (mTrack) {
1631 return mTrack->attachAuxEffect(effectId);
1632 }
1633 return NO_ERROR;
1634}
1635
Andreas Huber20111aa2009-07-14 16:56:47 -07001636// static
1637void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07001638 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01001639 //ALOGV("callbackwrapper");
Andreas Huber20111aa2009-07-14 16:56:47 -07001640 if (event != AudioTrack::EVENT_MORE_DATA) {
1641 return;
1642 }
1643
Marco Nelissen6b74d672012-02-28 16:07:44 -08001644 CallbackData *data = (CallbackData*)cookie;
1645 data->lock();
1646 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07001647 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001648 if (me == NULL) {
1649 // no output set, likely because the track was scheduled to be reused
1650 // by another player, but the format turned out to be incompatible.
1651 data->unlock();
1652 buffer->size = 0;
1653 return;
1654 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001655
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001656 size_t actualSize = (*me->mCallback)(
Andreas Huber20111aa2009-07-14 16:56:47 -07001657 me, buffer->raw, buffer->size, me->mCallbackCookie);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001658
Marco Nelissen6b74d672012-02-28 16:07:44 -08001659 if (actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) {
Andreas Huber51c1e0e2011-04-04 11:43:40 -07001660 // We've reached EOS but the audio track is not stopped yet,
1661 // keep playing silence.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08001662
Andreas Huber51c1e0e2011-04-04 11:43:40 -07001663 memset(buffer->raw, 0, buffer->size);
1664 actualSize = buffer->size;
1665 }
1666
1667 buffer->size = actualSize;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001668 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07001669}
1670
Marco Nelissen4110c102012-03-29 09:31:28 -07001671int MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07001672{
1673 return mSessionId;
1674}
1675
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001676#undef LOG_TAG
1677#define LOG_TAG "AudioCache"
1678MediaPlayerService::AudioCache::AudioCache(const char* name) :
1679 mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
1680 mError(NO_ERROR), mCommandComplete(false)
1681{
1682 // create ashmem heap
1683 mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
1684}
1685
1686uint32_t MediaPlayerService::AudioCache::latency () const
1687{
1688 return 0;
1689}
1690
1691float MediaPlayerService::AudioCache::msecsPerFrame() const
1692{
1693 return mMsecsPerFrame;
1694}
1695
Marco Nelissen4110c102012-03-29 09:31:28 -07001696status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001697{
1698 if (position == 0) return BAD_VALUE;
1699 *position = mSize;
1700 return NO_ERROR;
1701}
1702
Marco Nelissen4110c102012-03-29 09:31:28 -07001703status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
1704{
1705 if (written == 0) return BAD_VALUE;
1706 *written = mSize;
1707 return NO_ERROR;
1708}
1709
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001710////////////////////////////////////////////////////////////////////////////////
1711
1712struct CallbackThread : public Thread {
1713 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
1714 MediaPlayerBase::AudioSink::AudioCallback cb,
1715 void *cookie);
1716
1717protected:
1718 virtual ~CallbackThread();
1719
1720 virtual bool threadLoop();
1721
1722private:
1723 wp<MediaPlayerBase::AudioSink> mSink;
1724 MediaPlayerBase::AudioSink::AudioCallback mCallback;
1725 void *mCookie;
1726 void *mBuffer;
1727 size_t mBufferSize;
1728
1729 CallbackThread(const CallbackThread &);
1730 CallbackThread &operator=(const CallbackThread &);
1731};
1732
1733CallbackThread::CallbackThread(
1734 const wp<MediaPlayerBase::AudioSink> &sink,
1735 MediaPlayerBase::AudioSink::AudioCallback cb,
1736 void *cookie)
1737 : mSink(sink),
1738 mCallback(cb),
1739 mCookie(cookie),
1740 mBuffer(NULL),
1741 mBufferSize(0) {
1742}
1743
1744CallbackThread::~CallbackThread() {
1745 if (mBuffer) {
1746 free(mBuffer);
1747 mBuffer = NULL;
1748 }
1749}
1750
1751bool CallbackThread::threadLoop() {
1752 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
1753 if (sink == NULL) {
1754 return false;
1755 }
1756
1757 if (mBuffer == NULL) {
1758 mBufferSize = sink->bufferSize();
1759 mBuffer = malloc(mBufferSize);
1760 }
1761
1762 size_t actualSize =
1763 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie);
1764
1765 if (actualSize > 0) {
1766 sink->write(mBuffer, actualSize);
1767 }
1768
1769 return true;
1770}
1771
1772////////////////////////////////////////////////////////////////////////////////
1773
Andreas Huber20111aa2009-07-14 16:56:47 -07001774status_t MediaPlayerService::AudioCache::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001775 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1776 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001777 AudioCallback cb, void *cookie, audio_output_flags_t flags)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001778{
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001779 ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
Dave Sparks8eb80112009-12-09 20:20:26 -08001780 if (mHeap->getHeapID() < 0) {
1781 return NO_INIT;
1782 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001783
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001784 mSampleRate = sampleRate;
1785 mChannelCount = (uint16_t)channelCount;
Glenn Kastene1c39622012-01-04 09:36:37 -08001786 mFormat = format;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001787 mMsecsPerFrame = 1.e3 / (float) sampleRate;
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001788
1789 if (cb != NULL) {
1790 mCallbackThread = new CallbackThread(this, cb, cookie);
1791 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001792 return NO_ERROR;
1793}
1794
Andreas Huber7d5b8a72010-02-09 16:59:18 -08001795void MediaPlayerService::AudioCache::start() {
1796 if (mCallbackThread != NULL) {
1797 mCallbackThread->run("AudioCache callback");
1798 }
1799}
1800
1801void MediaPlayerService::AudioCache::stop() {
1802 if (mCallbackThread != NULL) {
1803 mCallbackThread->requestExitAndWait();
1804 }
1805}
1806
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001807ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
1808{
Steve Block3856b092011-10-20 11:56:00 +01001809 ALOGV("write(%p, %u)", buffer, size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001810 if ((buffer == 0) || (size == 0)) return size;
1811
1812 uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
1813 if (p == NULL) return NO_INIT;
1814 p += mSize;
Steve Block3856b092011-10-20 11:56:00 +01001815 ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001816 if (mSize + size > mHeap->getSize()) {
Steve Block29357bc2012-01-06 19:20:56 +00001817 ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001818 size = mHeap->getSize() - mSize;
1819 }
1820 memcpy(p, buffer, size);
1821 mSize += size;
1822 return size;
1823}
1824
1825// call with lock held
1826status_t MediaPlayerService::AudioCache::wait()
1827{
1828 Mutex::Autolock lock(mLock);
Dave Sparks4bbc0ba2010-03-01 19:29:58 -08001829 while (!mCommandComplete) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001830 mSignal.wait(mLock);
1831 }
1832 mCommandComplete = false;
1833
1834 if (mError == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001835 ALOGV("wait - success");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001836 } else {
Steve Block3856b092011-10-20 11:56:00 +01001837 ALOGV("wait - error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001838 }
1839 return mError;
1840}
1841
Gloria Wangb483c472011-04-11 17:23:27 -07001842void MediaPlayerService::AudioCache::notify(
1843 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001844{
Steve Block3856b092011-10-20 11:56:00 +01001845 ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001846 AudioCache* p = static_cast<AudioCache*>(cookie);
1847
1848 // ignore buffering messages
Dave Sparks8eb80112009-12-09 20:20:26 -08001849 switch (msg)
1850 {
1851 case MEDIA_ERROR:
Steve Block29357bc2012-01-06 19:20:56 +00001852 ALOGE("Error %d, %d occurred", ext1, ext2);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001853 p->mError = ext1;
Dave Sparks8eb80112009-12-09 20:20:26 -08001854 break;
1855 case MEDIA_PREPARED:
Steve Block3856b092011-10-20 11:56:00 +01001856 ALOGV("prepared");
Dave Sparks8eb80112009-12-09 20:20:26 -08001857 break;
1858 case MEDIA_PLAYBACK_COMPLETE:
Steve Block3856b092011-10-20 11:56:00 +01001859 ALOGV("playback complete");
Dave Sparks8eb80112009-12-09 20:20:26 -08001860 break;
1861 default:
Steve Block3856b092011-10-20 11:56:00 +01001862 ALOGV("ignored");
Dave Sparks8eb80112009-12-09 20:20:26 -08001863 return;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001864 }
1865
1866 // wake up thread
Dave Sparksfe4c6f02010-03-02 12:56:37 -08001867 Mutex::Autolock lock(p->mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001868 p->mCommandComplete = true;
1869 p->mSignal.signal();
1870}
1871
Marco Nelissen4110c102012-03-29 09:31:28 -07001872int MediaPlayerService::AudioCache::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07001873{
1874 return 0;
1875}
1876
Gloria Wang7cf180c2011-02-19 18:37:57 -08001877void MediaPlayerService::addBatteryData(uint32_t params)
1878{
1879 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08001880
1881 int32_t time = systemTime() / 1000000L;
1882
1883 // change audio output devices. This notification comes from AudioFlinger
1884 if ((params & kBatteryDataSpeakerOn)
1885 || (params & kBatteryDataOtherAudioDeviceOn)) {
1886
1887 int deviceOn[NUM_AUDIO_DEVICES];
1888 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
1889 deviceOn[i] = 0;
1890 }
1891
1892 if ((params & kBatteryDataSpeakerOn)
1893 && (params & kBatteryDataOtherAudioDeviceOn)) {
1894 deviceOn[SPEAKER_AND_OTHER] = 1;
1895 } else if (params & kBatteryDataSpeakerOn) {
1896 deviceOn[SPEAKER] = 1;
1897 } else {
1898 deviceOn[OTHER_AUDIO_DEVICE] = 1;
1899 }
1900
1901 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
1902 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
1903
1904 if (mBatteryAudio.refCount > 0) { // if playing audio
1905 if (!deviceOn[i]) {
1906 mBatteryAudio.lastTime[i] += time;
1907 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
1908 mBatteryAudio.lastTime[i] = 0;
1909 } else {
1910 mBatteryAudio.lastTime[i] = 0 - time;
1911 }
1912 }
1913
1914 mBatteryAudio.deviceOn[i] = deviceOn[i];
1915 }
1916 }
1917 return;
1918 }
1919
1920 // an sudio stream is started
1921 if (params & kBatteryDataAudioFlingerStart) {
1922 // record the start time only if currently no other audio
1923 // is being played
1924 if (mBatteryAudio.refCount == 0) {
1925 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
1926 if (mBatteryAudio.deviceOn[i]) {
1927 mBatteryAudio.lastTime[i] -= time;
1928 }
1929 }
1930 }
1931
1932 mBatteryAudio.refCount ++;
1933 return;
1934
1935 } else if (params & kBatteryDataAudioFlingerStop) {
1936 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001937 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08001938 return;
1939 }
1940
1941 // record the stop time only if currently this is the only
1942 // audio being played
1943 if (mBatteryAudio.refCount == 1) {
1944 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
1945 if (mBatteryAudio.deviceOn[i]) {
1946 mBatteryAudio.lastTime[i] += time;
1947 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
1948 mBatteryAudio.lastTime[i] = 0;
1949 }
1950 }
1951 }
1952
1953 mBatteryAudio.refCount --;
1954 return;
1955 }
1956
Gloria Wang7cf180c2011-02-19 18:37:57 -08001957 int uid = IPCThreadState::self()->getCallingUid();
1958 if (uid == AID_MEDIA) {
1959 return;
1960 }
1961 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08001962
1963 if (index < 0) { // create a new entry for this UID
1964 BatteryUsageInfo info;
1965 info.audioTotalTime = 0;
1966 info.videoTotalTime = 0;
1967 info.audioLastTime = 0;
1968 info.videoLastTime = 0;
1969 info.refCount = 0;
1970
Gloria Wang9ee159b2011-02-24 14:51:45 -08001971 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00001972 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08001973 return;
1974 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08001975 }
1976
1977 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
1978
1979 if (params & kBatteryDataCodecStarted) {
1980 if (params & kBatteryDataTrackAudio) {
1981 info.audioLastTime -= time;
1982 info.refCount ++;
1983 }
1984 if (params & kBatteryDataTrackVideo) {
1985 info.videoLastTime -= time;
1986 info.refCount ++;
1987 }
1988 } else {
1989 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001990 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08001991 return;
1992 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001993 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08001994 mBatteryData.removeItem(uid);
1995 return;
1996 }
1997
1998 if (params & kBatteryDataTrackAudio) {
1999 info.audioLastTime += time;
2000 info.refCount --;
2001 }
2002 if (params & kBatteryDataTrackVideo) {
2003 info.videoLastTime += time;
2004 info.refCount --;
2005 }
2006
2007 // no stream is being played by this UID
2008 if (info.refCount == 0) {
2009 info.audioTotalTime += info.audioLastTime;
2010 info.audioLastTime = 0;
2011 info.videoTotalTime += info.videoLastTime;
2012 info.videoLastTime = 0;
2013 }
2014 }
2015}
2016
2017status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2018 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002019
2020 // audio output devices usage
2021 int32_t time = systemTime() / 1000000L; //in ms
2022 int32_t totalTime;
2023
2024 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2025 totalTime = mBatteryAudio.totalTime[i];
2026
2027 if (mBatteryAudio.deviceOn[i]
2028 && (mBatteryAudio.lastTime[i] != 0)) {
2029 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2030 totalTime += tmpTime;
2031 }
2032
2033 reply->writeInt32(totalTime);
2034 // reset the total time
2035 mBatteryAudio.totalTime[i] = 0;
2036 }
2037
2038 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002039 BatteryUsageInfo info;
2040 int size = mBatteryData.size();
2041
2042 reply->writeInt32(size);
2043 int i = 0;
2044
2045 while (i < size) {
2046 info = mBatteryData.valueAt(i);
2047
2048 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2049 reply->writeInt32(info.audioTotalTime);
2050 reply->writeInt32(info.videoTotalTime);
2051
2052 info.audioTotalTime = 0;
2053 info.videoTotalTime = 0;
2054
2055 // remove the UID entry where no stream is being played
2056 if (info.refCount <= 0) {
2057 mBatteryData.removeItemsAt(i);
2058 size --;
2059 i --;
2060 }
2061 i++;
2062 }
2063 return NO_ERROR;
2064}
nikoa64c8c72009-07-20 15:07:26 -07002065} // namespace android