blob: 4b40b9991e8f4655c68f73cbaafe5b40f057bd5f [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>
Lajos Molnar06ad1522014-08-28 07:27:44 -070045#include <utils/Timers.h>
Nicolas Catania1d187f12009-05-12 23:25:55 -070046#include <utils/Vector.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080047
Eric Laurent43562692015-07-15 16:49:07 -070048#include <media/AudioPolicyHelper.h>
Andreas Huber1b86fe02014-01-29 11:13:26 -080049#include <media/IMediaHTTPService.h>
Jeff Brown2013a542012-09-04 21:38:42 -070050#include <media/IRemoteDisplay.h>
51#include <media/IRemoteDisplayClient.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080052#include <media/MediaPlayerInterface.h>
53#include <media/mediarecorder.h>
54#include <media/MediaMetadataRetrieverInterface.h>
nikoa64c8c72009-07-20 15:07:26 -070055#include <media/Metadata.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080056#include <media/AudioTrack.h>
James Dong8635b7b2011-03-14 17:01:38 -070057#include <media/MemoryLeakTrackUtil.h>
Lajos Molnar1381d4b2014-08-07 15:18:35 -070058#include <media/stagefright/MediaCodecList.h>
Eric Laurent9cb839a2011-09-27 09:48:56 -070059#include <media/stagefright/MediaErrors.h>
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +010060#include <media/stagefright/AudioPlayer.h>
61#include <media/stagefright/foundation/ADebug.h>
Marco Nelissenf09611f2015-02-13 14:12:42 -080062#include <media/stagefright/foundation/ALooperRoster.h>
Ruben Brunk99e69712015-05-26 17:25:07 -070063#include <mediautils/BatteryNotifier.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080064
Dima Zavin64760242011-05-11 14:15:23 -070065#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070066
Gloria Wang7cf180c2011-02-19 18:37:57 -080067#include <private/android_filesystem_config.h>
68
James Dong559bf282012-03-28 10:29:14 -070069#include "ActivityManager.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080070#include "MediaRecorderClient.h"
71#include "MediaPlayerService.h"
72#include "MetadataRetrieverClient.h"
John Grossman44a7e422012-06-21 17:29:24 -070073#include "MediaPlayerFactory.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080074
Nicolas Catania14d27472009-07-13 14:37:49 -070075#include "TestPlayerStub.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070076#include "StagefrightPlayer.h"
Andreas Huberf9334412010-12-15 15:17:42 -080077#include "nuplayer/NuPlayerDriver.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070078
Andreas Huber20111aa2009-07-14 16:56:47 -070079#include <OMX.h>
Nicolas Catania14d27472009-07-13 14:37:49 -070080
Andreas Hubered3e3e02012-03-26 11:13:27 -070081#include "Crypto.h"
Jeff Tinkercc82dc62013-02-08 10:18:35 -080082#include "Drm.h"
Andreas Huber59451f82012-09-18 10:36:32 -070083#include "HDCP.h"
Andreas Huberb7319a72013-05-29 14:20:52 -070084#include "HTTPBase.h"
Andreas Huber35213f12012-08-29 11:41:50 -070085#include "RemoteDisplay.h"
Andreas Hubered3e3e02012-03-26 11:13:27 -070086
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070087namespace {
nikoa64c8c72009-07-20 15:07:26 -070088using android::media::Metadata;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070089using android::status_t;
90using android::OK;
91using android::BAD_VALUE;
92using android::NOT_ENOUGH_DATA;
93using android::Parcel;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070094
95// Max number of entries in the filter.
96const int kMaxFilterSize = 64; // I pulled that out of thin air.
97
nikoa64c8c72009-07-20 15:07:26 -070098// FIXME: Move all the metadata related function in the Metadata.cpp
nikod608a812009-07-16 16:39:53 -070099
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700100
101// Unmarshall a filter from a Parcel.
102// Filter format in a parcel:
103//
104// 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
105// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106// | number of entries (n) |
107// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108// | metadata type 1 |
109// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110// | metadata type 2 |
111// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112// ....
113// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114// | metadata type n |
115// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116//
117// @param p Parcel that should start with a filter.
118// @param[out] filter On exit contains the list of metadata type to be
119// filtered.
120// @param[out] status On exit contains the status code to be returned.
121// @return true if the parcel starts with a valid filter.
122bool unmarshallFilter(const Parcel& p,
nikoa64c8c72009-07-20 15:07:26 -0700123 Metadata::Filter *filter,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700124 status_t *status)
125{
Nicolas Catania48290382009-07-10 13:53:06 -0700126 int32_t val;
127 if (p.readInt32(&val) != OK)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700128 {
Steve Block29357bc2012-01-06 19:20:56 +0000129 ALOGE("Failed to read filter's length");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700130 *status = NOT_ENOUGH_DATA;
131 return false;
132 }
133
Nicolas Catania48290382009-07-10 13:53:06 -0700134 if( val > kMaxFilterSize || val < 0)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700135 {
Steve Block29357bc2012-01-06 19:20:56 +0000136 ALOGE("Invalid filter len %d", val);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700137 *status = BAD_VALUE;
138 return false;
139 }
140
Nicolas Catania48290382009-07-10 13:53:06 -0700141 const size_t num = val;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700142
143 filter->clear();
Nicolas Catania48290382009-07-10 13:53:06 -0700144 filter->setCapacity(num);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700145
nikoa64c8c72009-07-20 15:07:26 -0700146 size_t size = num * sizeof(Metadata::Type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700147
Nicolas Catania48290382009-07-10 13:53:06 -0700148
149 if (p.dataAvail() < size)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700150 {
Steve Block29357bc2012-01-06 19:20:56 +0000151 ALOGE("Filter too short expected %d but got %d", size, p.dataAvail());
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700152 *status = NOT_ENOUGH_DATA;
153 return false;
154 }
155
nikoa64c8c72009-07-20 15:07:26 -0700156 const Metadata::Type *data =
157 static_cast<const Metadata::Type*>(p.readInplace(size));
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700158
Nicolas Catania48290382009-07-10 13:53:06 -0700159 if (NULL == data)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700160 {
Steve Block29357bc2012-01-06 19:20:56 +0000161 ALOGE("Filter had no data");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700162 *status = BAD_VALUE;
163 return false;
164 }
165
166 // TODO: The stl impl of vector would be more efficient here
167 // because it degenerates into a memcpy on pod types. Try to
168 // replace later or use stl::set.
Nicolas Catania48290382009-07-10 13:53:06 -0700169 for (size_t i = 0; i < num; ++i)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700170 {
Nicolas Catania48290382009-07-10 13:53:06 -0700171 filter->add(*data);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700172 ++data;
173 }
174 *status = OK;
175 return true;
176}
177
Nicolas Catania48290382009-07-10 13:53:06 -0700178// @param filter Of metadata type.
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700179// @param val To be searched.
180// @return true if a match was found.
nikoa64c8c72009-07-20 15:07:26 -0700181bool findMetadata(const Metadata::Filter& filter, const int32_t val)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700182{
183 // Deal with empty and ANY right away
184 if (filter.isEmpty()) return false;
nikoa64c8c72009-07-20 15:07:26 -0700185 if (filter[0] == Metadata::kAny) return true;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700186
Nicolas Catania48290382009-07-10 13:53:06 -0700187 return filter.indexOf(val) >= 0;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700188}
189
190} // anonymous namespace
191
192
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700193namespace {
194using android::Parcel;
195using android::String16;
196
197// marshalling tag indicating flattened utf16 tags
198// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
199const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
200
201// Audio attributes format in a parcel:
202//
203// 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
204// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205// | usage |
206// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
207// | content_type |
208// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Hyejin Kim4f418f92014-09-05 15:50:03 +0900209// | source |
210// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700211// | flags |
212// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213// | kAudioAttributesMarshallTagFlattenTags | // ignore tags if not found
214// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215// | flattened tags in UTF16 |
216// | ... |
217// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
218//
219// @param p Parcel that contains audio attributes.
220// @param[out] attributes On exit points to an initialized audio_attributes_t structure
221// @param[out] status On exit contains the status code to be returned.
222void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes)
223{
224 attributes->usage = (audio_usage_t) parcel.readInt32();
225 attributes->content_type = (audio_content_type_t) parcel.readInt32();
Hyejin Kim4f418f92014-09-05 15:50:03 +0900226 attributes->source = (audio_source_t) parcel.readInt32();
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700227 attributes->flags = (audio_flags_mask_t) parcel.readInt32();
228 const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
229 if (hasFlattenedTag) {
230 // the tags are UTF16, convert to UTF8
231 String16 tags = parcel.readString16();
232 ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
233 if (realTagSize <= 0) {
234 strcpy(attributes->tags, "");
235 } else {
236 // copy the flattened string into the attributes as the destination for the conversion:
237 // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
238 size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
239 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
Sergio Giro0c9742d2016-06-28 18:24:52 +0100240 utf16_to_utf8(tags.string(), tagSize, attributes->tags,
241 sizeof(attributes->tags) / sizeof(attributes->tags[0]));
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700242 }
243 } else {
244 ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
245 strcpy(attributes->tags, "");
246 }
247}
248} // anonymous namespace
249
250
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251namespace android {
252
Marco Nelissenf09611f2015-02-13 14:12:42 -0800253extern ALooperRoster gLooperRoster;
254
255
Dave Burked681bbb2011-08-30 14:39:17 +0100256static bool checkPermission(const char* permissionString) {
257#ifndef HAVE_ANDROID_OS
258 return true;
259#endif
260 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
261 bool ok = checkCallingPermission(String16(permissionString));
Steve Block29357bc2012-01-06 19:20:56 +0000262 if (!ok) ALOGE("Request requires %s", permissionString);
Dave Burked681bbb2011-08-30 14:39:17 +0100263 return ok;
264}
265
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800266// 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 -0800267/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
268/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
269
270void MediaPlayerService::instantiate() {
271 defaultServiceManager()->addService(
272 String16("media.player"), new MediaPlayerService());
273}
274
275MediaPlayerService::MediaPlayerService()
276{
Steve Block3856b092011-10-20 11:56:00 +0100277 ALOGV("MediaPlayerService created");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800278 mNextConnId = 1;
Gloria Wang9ee159b2011-02-24 14:51:45 -0800279
280 mBatteryAudio.refCount = 0;
281 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
282 mBatteryAudio.deviceOn[i] = 0;
283 mBatteryAudio.lastTime[i] = 0;
284 mBatteryAudio.totalTime[i] = 0;
285 }
286 // speaker is on by default
287 mBatteryAudio.deviceOn[SPEAKER] = 1;
John Grossman44a7e422012-06-21 17:29:24 -0700288
Chong Zhang0b30fd42014-07-23 14:46:05 -0700289 // reset battery stats
290 // if the mediaserver has crashed, battery stats could be left
291 // in bad state, reset the state upon service start.
Ruben Brunk99e69712015-05-26 17:25:07 -0700292 BatteryNotifier& notifier(BatteryNotifier::getInstance());
293 notifier.noteResetVideo();
294 notifier.noteResetAudio();
Chong Zhang0b30fd42014-07-23 14:46:05 -0700295
John Grossman44a7e422012-06-21 17:29:24 -0700296 MediaPlayerFactory::registerBuiltinFactories();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800297}
298
299MediaPlayerService::~MediaPlayerService()
300{
Steve Block3856b092011-10-20 11:56:00 +0100301 ALOGV("MediaPlayerService destroyed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800302}
303
Svet Ganovbe71aa22015-04-28 12:06:02 -0700304sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(const String16 &opPackageName)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800305{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800306 pid_t pid = IPCThreadState::self()->getCallingPid();
Svet Ganovbe71aa22015-04-28 12:06:02 -0700307 sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid, opPackageName);
Gloria Wangdac6a312009-10-29 15:46:37 -0700308 wp<MediaRecorderClient> w = recorder;
309 Mutex::Autolock lock(mLock);
310 mMediaRecorderClients.add(w);
Steve Block3856b092011-10-20 11:56:00 +0100311 ALOGV("Create new media recorder client from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800312 return recorder;
313}
314
Gloria Wangdac6a312009-10-29 15:46:37 -0700315void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
316{
317 Mutex::Autolock lock(mLock);
318 mMediaRecorderClients.remove(client);
Steve Block3856b092011-10-20 11:56:00 +0100319 ALOGV("Delete media recorder client");
Gloria Wangdac6a312009-10-29 15:46:37 -0700320}
321
Glenn Kastenf37971f2012-02-03 11:06:53 -0800322sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800323{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800324 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800325 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
Steve Block3856b092011-10-20 11:56:00 +0100326 ALOGV("Create new media retriever from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800327 return retriever;
328}
329
Glenn Kastenf37971f2012-02-03 11:06:53 -0800330sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
Dave Burked681bbb2011-08-30 14:39:17 +0100331 int audioSessionId)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800332{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800333 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800334 int32_t connId = android_atomic_inc(&mNextConnId);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700335
336 sp<Client> c = new Client(
337 this, pid, connId, client, audioSessionId,
338 IPCThreadState::self()->getCallingUid());
339
Steve Block3856b092011-10-20 11:56:00 +0100340 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
Dave Burked681bbb2011-08-30 14:39:17 +0100341 IPCThreadState::self()->getCallingUid());
342
343 wp<Client> w = c;
344 {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800345 Mutex::Autolock lock(mLock);
346 mClients.add(w);
347 }
Andreas Hubere2b10282010-11-23 11:41:34 -0800348 return c;
349}
350
Lajos Molnar1381d4b2014-08-07 15:18:35 -0700351sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
352 return MediaCodecList::getLocalInstance();
353}
354
Andreas Huber318ad9c2009-10-15 13:46:54 -0700355sp<IOMX> MediaPlayerService::getOMX() {
356 Mutex::Autolock autoLock(mLock);
357
358 if (mOMX.get() == NULL) {
359 mOMX = new OMX;
360 }
361
362 return mOMX;
Andreas Huber20111aa2009-07-14 16:56:47 -0700363}
364
Andreas Hubered3e3e02012-03-26 11:13:27 -0700365sp<ICrypto> MediaPlayerService::makeCrypto() {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700366 return new Crypto;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700367}
368
Jeff Tinkercc82dc62013-02-08 10:18:35 -0800369sp<IDrm> MediaPlayerService::makeDrm() {
370 return new Drm;
371}
372
Andreas Huber279dcd82013-01-30 10:41:25 -0800373sp<IHDCP> MediaPlayerService::makeHDCP(bool createEncryptionModule) {
374 return new HDCP(createEncryptionModule);
Andreas Huber59451f82012-09-18 10:36:32 -0700375}
376
Jeff Brown2013a542012-09-04 21:38:42 -0700377sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
Svet Ganovbe71aa22015-04-28 12:06:02 -0700378 const String16 &opPackageName,
Jeff Brown2013a542012-09-04 21:38:42 -0700379 const sp<IRemoteDisplayClient>& client, const String8& iface) {
Jeff Brownaba33d52012-09-07 17:38:58 -0700380 if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
381 return NULL;
382 }
383
Svet Ganovbe71aa22015-04-28 12:06:02 -0700384 return new RemoteDisplay(opPackageName, client, iface.string());
Jeff Brown2013a542012-09-04 21:38:42 -0700385}
386
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800387status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
388{
389 const size_t SIZE = 256;
390 char buffer[SIZE];
391 String8 result;
392
393 result.append(" AudioOutput\n");
394 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
395 mStreamType, mLeftVolume, mRightVolume);
396 result.append(buffer);
397 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Eric Laurentdb354e52012-03-05 17:27:11 -0800398 mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800399 result.append(buffer);
Eric Laurent2beeb502010-07-16 07:43:46 -0700400 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
401 mAuxEffectId, mSendLevel);
402 result.append(buffer);
403
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800404 ::write(fd, result.string(), result.size());
405 if (mTrack != 0) {
406 mTrack->dump(fd, args);
407 }
408 return NO_ERROR;
409}
410
Lajos Molnar6d339f12015-04-17 16:15:53 -0700411status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800412{
413 const size_t SIZE = 256;
414 char buffer[SIZE];
415 String8 result;
416 result.append(" Client\n");
417 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
418 mPid, mConnId, mStatus, mLoop?"true": "false");
419 result.append(buffer);
420 write(fd, result.string(), result.size());
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700421 if (mPlayer != NULL) {
422 mPlayer->dump(fd, args);
423 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800424 if (mAudioOutput != 0) {
425 mAudioOutput->dump(fd, args);
426 }
427 write(fd, "\n", 1);
428 return NO_ERROR;
429}
430
Marco Nelissenf09611f2015-02-13 14:12:42 -0800431/**
432 * The only arguments this understands right now are -c, -von and -voff,
433 * which are parsed by ALooperRoster::dump()
434 */
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800435status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
436{
437 const size_t SIZE = 256;
438 char buffer[SIZE];
439 String8 result;
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530440 SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
441 SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
442
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800443 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
444 snprintf(buffer, SIZE, "Permission Denial: "
445 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
446 IPCThreadState::self()->getCallingPid(),
447 IPCThreadState::self()->getCallingUid());
448 result.append(buffer);
449 } else {
450 Mutex::Autolock lock(mLock);
451 for (int i = 0, n = mClients.size(); i < n; ++i) {
452 sp<Client> c = mClients[i].promote();
453 if (c != 0) c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530454 clients.add(c);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800455 }
James Dongb9141222010-07-08 11:16:11 -0700456 if (mMediaRecorderClients.size() == 0) {
457 result.append(" No media recorder client\n\n");
458 } else {
459 for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
460 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
James Donge579e282011-10-18 22:29:20 -0700461 if (c != 0) {
462 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
463 result.append(buffer);
464 write(fd, result.string(), result.size());
465 result = "\n";
466 c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530467 mediaRecorderClients.add(c);
James Donge579e282011-10-18 22:29:20 -0700468 }
James Dongb9141222010-07-08 11:16:11 -0700469 }
Gloria Wangdac6a312009-10-29 15:46:37 -0700470 }
471
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800472 result.append(" Files opened and/or mapped:\n");
Marco Nelissenf09611f2015-02-13 14:12:42 -0800473 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800474 FILE *f = fopen(buffer, "r");
475 if (f) {
476 while (!feof(f)) {
477 fgets(buffer, SIZE, f);
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700478 if (strstr(buffer, " /storage/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800479 strstr(buffer, " /system/sounds/") ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700480 strstr(buffer, " /data/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800481 strstr(buffer, " /system/media/")) {
482 result.append(" ");
483 result.append(buffer);
484 }
485 }
486 fclose(f);
487 } else {
488 result.append("couldn't open ");
489 result.append(buffer);
490 result.append("\n");
491 }
492
Marco Nelissenf09611f2015-02-13 14:12:42 -0800493 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800494 DIR *d = opendir(buffer);
495 if (d) {
496 struct dirent *ent;
497 while((ent = readdir(d)) != NULL) {
498 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
Marco Nelissenf09611f2015-02-13 14:12:42 -0800499 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800500 struct stat s;
501 if (lstat(buffer, &s) == 0) {
502 if ((s.st_mode & S_IFMT) == S_IFLNK) {
503 char linkto[256];
504 int len = readlink(buffer, linkto, sizeof(linkto));
505 if(len > 0) {
506 if(len > 255) {
507 linkto[252] = '.';
508 linkto[253] = '.';
509 linkto[254] = '.';
510 linkto[255] = 0;
511 } else {
512 linkto[len] = 0;
513 }
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700514 if (strstr(linkto, "/storage/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800515 strstr(linkto, "/system/sounds/") == linkto ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700516 strstr(linkto, "/data/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800517 strstr(linkto, "/system/media/") == linkto) {
518 result.append(" ");
519 result.append(buffer);
520 result.append(" -> ");
521 result.append(linkto);
522 result.append("\n");
523 }
524 }
525 } else {
526 result.append(" unexpected type for ");
527 result.append(buffer);
528 result.append("\n");
529 }
530 }
531 }
532 }
533 closedir(d);
534 } else {
535 result.append("couldn't open ");
536 result.append(buffer);
537 result.append("\n");
538 }
539
Marco Nelissenf09611f2015-02-13 14:12:42 -0800540 gLooperRoster.dump(fd, args);
541
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800542 bool dumpMem = false;
543 for (size_t i = 0; i < args.size(); i++) {
544 if (args[i] == String16("-m")) {
545 dumpMem = true;
546 }
547 }
548 if (dumpMem) {
James Dong8635b7b2011-03-14 17:01:38 -0700549 dumpMemoryAddresses(fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800550 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800551 }
552 write(fd, result.string(), result.size());
553 return NO_ERROR;
554}
555
556void MediaPlayerService::removeClient(wp<Client> client)
557{
558 Mutex::Autolock lock(mLock);
559 mClients.remove(client);
560}
561
Robert Shihee0a0e32016-08-16 16:50:54 -0700562bool MediaPlayerService::hasClient(wp<Client> client)
563{
564 Mutex::Autolock lock(mLock);
565 return mClients.indexOf(client) != NAME_NOT_FOUND;
566}
567
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700568MediaPlayerService::Client::Client(
569 const sp<MediaPlayerService>& service, pid_t pid,
570 int32_t connId, const sp<IMediaPlayerClient>& client,
571 int audioSessionId, uid_t uid)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800572{
Steve Block3856b092011-10-20 11:56:00 +0100573 ALOGV("Client(%d) constructor", connId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800574 mPid = pid;
575 mConnId = connId;
576 mService = service;
577 mClient = client;
578 mLoop = false;
579 mStatus = NO_INIT;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700580 mAudioSessionId = audioSessionId;
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700581 mUID = uid;
John Grossmanc795b642012-02-22 15:38:35 -0800582 mRetransmitEndpointValid = false;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700583 mAudioAttributes = NULL;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700584
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800585#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000586 ALOGD("create Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800587 mAntagonizer = new Antagonizer(notify, this);
588#endif
589}
590
591MediaPlayerService::Client::~Client()
592{
Steve Block3856b092011-10-20 11:56:00 +0100593 ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800594 mAudioOutput.clear();
595 wp<Client> client(this);
596 disconnect();
597 mService->removeClient(client);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700598 if (mAudioAttributes != NULL) {
599 free(mAudioAttributes);
600 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800601}
602
603void MediaPlayerService::Client::disconnect()
604{
Steve Block3856b092011-10-20 11:56:00 +0100605 ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800606 // grab local reference and clear main reference to prevent future
607 // access to object
608 sp<MediaPlayerBase> p;
609 {
610 Mutex::Autolock l(mLock);
611 p = mPlayer;
beanzdcfefde2012-11-05 09:51:43 +0800612 mClient.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800613 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700614
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800615 mPlayer.clear();
616
617 // clear the notification to prevent callbacks to dead client
618 // and reset the player. We assume the player will serialize
619 // access to itself if necessary.
620 if (p != 0) {
621 p->setNotifyCallback(0, 0);
622#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000623 ALOGD("kill Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800624 mAntagonizer->kill();
625#endif
626 p->reset();
627 }
628
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700629 disconnectNativeWindow();
630
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800631 IPCThreadState::self()->flushCommands();
632}
633
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800634sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
635{
636 // determine if we have the right player type
637 sp<MediaPlayerBase> p = mPlayer;
638 if ((p != NULL) && (p->playerType() != playerType)) {
Steve Block3856b092011-10-20 11:56:00 +0100639 ALOGV("delete player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800640 p.clear();
641 }
642 if (p == NULL) {
Ronghua Wu68845c12015-07-21 09:50:48 -0700643 p = MediaPlayerFactory::createPlayer(playerType, this, notify, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800644 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700645
Jason Simmonsdb29e522011-08-12 13:46:55 -0700646 if (p != NULL) {
647 p->setUID(mUID);
648 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700649
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800650 return p;
651}
652
John Grossmanc795b642012-02-22 15:38:35 -0800653sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
654 player_type playerType)
655{
656 ALOGV("player type = %d", playerType);
657
658 // create the right type of player
659 sp<MediaPlayerBase> p = createPlayer(playerType);
660 if (p == NULL) {
661 return p;
662 }
663
664 if (!p->hardwareOutput()) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -0700665 Mutex::Autolock l(mLock);
Marco Nelissend457c972014-02-11 08:47:07 -0800666 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700667 mPid, mAudioAttributes);
John Grossmanc795b642012-02-22 15:38:35 -0800668 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
669 }
670
671 return p;
672}
673
674void MediaPlayerService::Client::setDataSource_post(
675 const sp<MediaPlayerBase>& p,
676 status_t status)
677{
678 ALOGV(" setDataSource");
679 mStatus = status;
680 if (mStatus != OK) {
681 ALOGE(" error: %d", mStatus);
682 return;
683 }
684
685 // Set the re-transmission endpoint if one was chosen.
686 if (mRetransmitEndpointValid) {
687 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
688 if (mStatus != NO_ERROR) {
689 ALOGE("setRetransmitEndpoint error: %d", mStatus);
690 }
691 }
692
693 if (mStatus == OK) {
694 mPlayer = p;
695 }
696}
697
Andreas Huber2db84552010-01-28 11:19:57 -0800698status_t MediaPlayerService::Client::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800699 const sp<IMediaHTTPService> &httpService,
700 const char *url,
701 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800702{
Steve Block3856b092011-10-20 11:56:00 +0100703 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800704 if (url == NULL)
705 return UNKNOWN_ERROR;
706
Dave Burked681bbb2011-08-30 14:39:17 +0100707 if ((strncmp(url, "http://", 7) == 0) ||
708 (strncmp(url, "https://", 8) == 0) ||
709 (strncmp(url, "rtsp://", 7) == 0)) {
710 if (!checkPermission("android.permission.INTERNET")) {
711 return PERMISSION_DENIED;
712 }
713 }
714
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800715 if (strncmp(url, "content://", 10) == 0) {
716 // get a filedescriptor for the content Uri and
717 // pass it to the setDataSource(fd) method
718
719 String16 url16(url);
720 int fd = android::openContentProviderFile(url16);
721 if (fd < 0)
722 {
Steve Block29357bc2012-01-06 19:20:56 +0000723 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800724 return UNKNOWN_ERROR;
725 }
726 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
727 close(fd);
728 return mStatus;
729 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700730 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800731 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
732 if (p == NULL) {
733 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800734 }
735
Andreas Huber1b86fe02014-01-29 11:13:26 -0800736 setDataSource_post(p, p->setDataSource(httpService, url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800737 return mStatus;
738 }
739}
740
741status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
742{
Steve Block3856b092011-10-20 11:56:00 +0100743 ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800744 struct stat sb;
745 int ret = fstat(fd, &sb);
746 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000747 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800748 return UNKNOWN_ERROR;
749 }
750
Ying Wang5fde15d2015-04-20 22:13:22 -0700751 ALOGV("st_dev = %llu", static_cast<uint64_t>(sb.st_dev));
Steve Block3856b092011-10-20 11:56:00 +0100752 ALOGV("st_mode = %u", sb.st_mode);
Mark Salyzyn77342f72014-06-18 16:31:32 -0700753 ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
754 ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
Steve Block3856b092011-10-20 11:56:00 +0100755 ALOGV("st_size = %llu", sb.st_size);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800756
757 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000758 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800759 ::close(fd);
760 return UNKNOWN_ERROR;
761 }
762 if (offset + length > sb.st_size) {
763 length = sb.st_size - offset;
Steve Block3856b092011-10-20 11:56:00 +0100764 ALOGV("calculated length = %lld", length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800765 }
766
John Grossman44a7e422012-06-21 17:29:24 -0700767 player_type playerType = MediaPlayerFactory::getPlayerType(this,
768 fd,
769 offset,
770 length);
John Grossmanc795b642012-02-22 15:38:35 -0800771 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
772 if (p == NULL) {
773 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800774 }
775
776 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800777 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800778 return mStatus;
779}
780
Andreas Hubere2b10282010-11-23 11:41:34 -0800781status_t MediaPlayerService::Client::setDataSource(
782 const sp<IStreamSource> &source) {
783 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700784 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800785 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800786 if (p == NULL) {
787 return NO_INIT;
788 }
789
Andreas Hubere2b10282010-11-23 11:41:34 -0800790 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800791 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800792 return mStatus;
793}
794
Chris Watkins99f31602015-03-20 13:06:33 -0700795status_t MediaPlayerService::Client::setDataSource(
796 const sp<IDataSource> &source) {
797 sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source);
798 player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource);
799 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
800 if (p == NULL) {
801 return NO_INIT;
802 }
803 // now set data source
804 setDataSource_post(p, p->setDataSource(dataSource));
805 return mStatus;
806}
807
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700808void MediaPlayerService::Client::disconnectNativeWindow() {
809 if (mConnectedWindow != NULL) {
810 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
811 NATIVE_WINDOW_API_MEDIA);
812
813 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000814 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700815 strerror(-err), err);
816 }
817 }
818 mConnectedWindow.clear();
819}
820
Glenn Kasten11731182011-02-08 17:26:17 -0800821status_t MediaPlayerService::Client::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800822 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800823{
Andy McFadden484566c2012-12-18 09:46:54 -0800824 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800825 sp<MediaPlayerBase> p = getPlayer();
826 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700827
Marco Nelissenf8880202014-11-14 07:58:25 -0800828 sp<IBinder> binder(IInterface::asBinder(bufferProducer));
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700829 if (mConnectedWindowBinder == binder) {
830 return OK;
831 }
832
833 sp<ANativeWindow> anw;
Andy McFadden484566c2012-12-18 09:46:54 -0800834 if (bufferProducer != NULL) {
Marco Nelissenee08f7e2013-09-16 13:30:01 -0700835 anw = new Surface(bufferProducer, true /* controlledByApp */);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700836 status_t err = native_window_api_connect(anw.get(),
837 NATIVE_WINDOW_API_MEDIA);
838
839 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000840 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700841 // Note that we must do the reset before disconnecting from the ANW.
842 // Otherwise queue/dequeue calls could be made on the disconnected
843 // ANW, which may result in errors.
844 reset();
845
846 disconnectNativeWindow();
847
848 return err;
849 }
850 }
851
Andy McFadden484566c2012-12-18 09:46:54 -0800852 // Note that we must set the player's new GraphicBufferProducer before
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700853 // disconnecting the old one. Otherwise queue/dequeue calls could be made
854 // on the disconnected ANW, which may result in errors.
Andy McFadden484566c2012-12-18 09:46:54 -0800855 status_t err = p->setVideoSurfaceTexture(bufferProducer);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700856
857 disconnectNativeWindow();
858
859 mConnectedWindow = anw;
860
861 if (err == OK) {
862 mConnectedWindowBinder = binder;
863 } else {
864 disconnectNativeWindow();
865 }
866
867 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800868}
869
Nicolas Catania1d187f12009-05-12 23:25:55 -0700870status_t MediaPlayerService::Client::invoke(const Parcel& request,
871 Parcel *reply)
872{
873 sp<MediaPlayerBase> p = getPlayer();
874 if (p == NULL) return UNKNOWN_ERROR;
875 return p->invoke(request, reply);
876}
877
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700878// This call doesn't need to access the native player.
879status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
880{
881 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700882 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700883
Nicolas Catania48290382009-07-10 13:53:06 -0700884 if (unmarshallFilter(filter, &allow, &status) &&
885 unmarshallFilter(filter, &drop, &status)) {
886 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700887
888 mMetadataAllow = allow;
889 mMetadataDrop = drop;
890 }
891 return status;
892}
893
Nicolas Catania48290382009-07-10 13:53:06 -0700894status_t MediaPlayerService::Client::getMetadata(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700895 bool update_only, bool /*apply_filter*/, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700896{
nikoa64c8c72009-07-20 15:07:26 -0700897 sp<MediaPlayerBase> player = getPlayer();
898 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700899
nikod608a812009-07-16 16:39:53 -0700900 status_t status;
901 // Placeholder for the return code, updated by the caller.
902 reply->writeInt32(-1);
903
nikoa64c8c72009-07-20 15:07:26 -0700904 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700905
906 // We don't block notifications while we fetch the data. We clear
907 // mMetadataUpdated first so we don't lose notifications happening
908 // during the rest of this call.
909 {
910 Mutex::Autolock lock(mLock);
911 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700912 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700913 }
914 mMetadataUpdated.clear();
915 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700916
nikoa64c8c72009-07-20 15:07:26 -0700917 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700918
nikoa64c8c72009-07-20 15:07:26 -0700919 metadata.appendHeader();
920 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700921
922 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700923 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000924 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700925 return status;
926 }
927
928 // FIXME: Implement filtering on the result. Not critical since
929 // filtering takes place on the update notifications already. This
930 // would be when all the metadata are fetch and a filter is set.
931
nikod608a812009-07-16 16:39:53 -0700932 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700933 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700934 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700935}
936
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800937status_t MediaPlayerService::Client::prepareAsync()
938{
Steve Block3856b092011-10-20 11:56:00 +0100939 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800940 sp<MediaPlayerBase> p = getPlayer();
941 if (p == 0) return UNKNOWN_ERROR;
942 status_t ret = p->prepareAsync();
943#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000944 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800945 if (ret == NO_ERROR) mAntagonizer->start();
946#endif
947 return ret;
948}
949
950status_t MediaPlayerService::Client::start()
951{
Steve Block3856b092011-10-20 11:56:00 +0100952 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800953 sp<MediaPlayerBase> p = getPlayer();
954 if (p == 0) return UNKNOWN_ERROR;
955 p->setLooping(mLoop);
956 return p->start();
957}
958
959status_t MediaPlayerService::Client::stop()
960{
Steve Block3856b092011-10-20 11:56:00 +0100961 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800962 sp<MediaPlayerBase> p = getPlayer();
963 if (p == 0) return UNKNOWN_ERROR;
964 return p->stop();
965}
966
967status_t MediaPlayerService::Client::pause()
968{
Steve Block3856b092011-10-20 11:56:00 +0100969 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800970 sp<MediaPlayerBase> p = getPlayer();
971 if (p == 0) return UNKNOWN_ERROR;
972 return p->pause();
973}
974
975status_t MediaPlayerService::Client::isPlaying(bool* state)
976{
977 *state = false;
978 sp<MediaPlayerBase> p = getPlayer();
979 if (p == 0) return UNKNOWN_ERROR;
980 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +0100981 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800982 return NO_ERROR;
983}
984
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700985status_t MediaPlayerService::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -0800986{
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700987 ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
988 mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Wei Jia98160162015-02-04 17:01:11 -0800989 sp<MediaPlayerBase> p = getPlayer();
990 if (p == 0) return UNKNOWN_ERROR;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700991 return p->setPlaybackSettings(rate);
992}
993
994status_t MediaPlayerService::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
995{
996 sp<MediaPlayerBase> p = getPlayer();
997 if (p == 0) return UNKNOWN_ERROR;
998 status_t ret = p->getPlaybackSettings(rate);
999 if (ret == NO_ERROR) {
1000 ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
1001 mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
1002 } else {
1003 ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
1004 }
1005 return ret;
1006}
1007
1008status_t MediaPlayerService::Client::setSyncSettings(
1009 const AVSyncSettings& sync, float videoFpsHint)
1010{
1011 ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
1012 mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
1013 sp<MediaPlayerBase> p = getPlayer();
1014 if (p == 0) return UNKNOWN_ERROR;
1015 return p->setSyncSettings(sync, videoFpsHint);
1016}
1017
1018status_t MediaPlayerService::Client::getSyncSettings(
1019 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
1020{
1021 sp<MediaPlayerBase> p = getPlayer();
1022 if (p == 0) return UNKNOWN_ERROR;
1023 status_t ret = p->getSyncSettings(sync, videoFps);
1024 if (ret == NO_ERROR) {
1025 ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
1026 mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
1027 } else {
1028 ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
1029 }
1030 return ret;
Wei Jia98160162015-02-04 17:01:11 -08001031}
1032
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001033status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
1034{
Steve Block3856b092011-10-20 11:56:00 +01001035 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001036 sp<MediaPlayerBase> p = getPlayer();
1037 if (p == 0) return UNKNOWN_ERROR;
1038 status_t ret = p->getCurrentPosition(msec);
1039 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001040 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001041 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001042 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001043 }
1044 return ret;
1045}
1046
1047status_t MediaPlayerService::Client::getDuration(int *msec)
1048{
Steve Block3856b092011-10-20 11:56:00 +01001049 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001050 sp<MediaPlayerBase> p = getPlayer();
1051 if (p == 0) return UNKNOWN_ERROR;
1052 status_t ret = p->getDuration(msec);
1053 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001054 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001055 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001056 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001057 }
1058 return ret;
1059}
1060
Marco Nelissen6b74d672012-02-28 16:07:44 -08001061status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
1062 ALOGV("setNextPlayer");
1063 Mutex::Autolock l(mLock);
1064 sp<Client> c = static_cast<Client*>(player.get());
Wei Jia28284122016-08-30 13:49:06 -07001065 if (c != NULL && !mService->hasClient(c)) {
Robert Shihee0a0e32016-08-16 16:50:54 -07001066 return BAD_VALUE;
1067 }
1068
Marco Nelissen6b74d672012-02-28 16:07:44 -08001069 mNextClient = c;
John Grossman5f7e55e2012-08-24 14:47:25 -07001070
1071 if (c != NULL) {
1072 if (mAudioOutput != NULL) {
1073 mAudioOutput->setNextOutput(c->mAudioOutput);
1074 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
1075 ALOGE("no current audio output");
1076 }
1077
1078 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
1079 mPlayer->setNextPlayer(mNextClient->getPlayer());
1080 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001081 }
John Grossman5f7e55e2012-08-24 14:47:25 -07001082
Marco Nelissen6b74d672012-02-28 16:07:44 -08001083 return OK;
1084}
1085
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001086status_t MediaPlayerService::Client::seekTo(int msec)
1087{
Steve Block3856b092011-10-20 11:56:00 +01001088 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001089 sp<MediaPlayerBase> p = getPlayer();
1090 if (p == 0) return UNKNOWN_ERROR;
1091 return p->seekTo(msec);
1092}
1093
1094status_t MediaPlayerService::Client::reset()
1095{
Steve Block3856b092011-10-20 11:56:00 +01001096 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -08001097 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001098 sp<MediaPlayerBase> p = getPlayer();
1099 if (p == 0) return UNKNOWN_ERROR;
1100 return p->reset();
1101}
1102
Glenn Kastenfff6d712012-01-12 16:38:12 -08001103status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001104{
Steve Block3856b092011-10-20 11:56:00 +01001105 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001106 // TODO: for hardware output, call player instead
1107 Mutex::Autolock l(mLock);
1108 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1109 return NO_ERROR;
1110}
1111
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001112status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
1113{
1114 if (mAudioAttributes != NULL) { free(mAudioAttributes); }
1115 mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001116 if (mAudioAttributes == NULL) {
1117 return NO_MEMORY;
1118 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001119 unmarshallAudioAttributes(parcel, mAudioAttributes);
1120
1121 ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
1122 mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
1123 mAudioAttributes->tags);
1124
1125 if (mAudioOutput != 0) {
1126 mAudioOutput->setAudioAttributes(mAudioAttributes);
1127 }
1128 return NO_ERROR;
1129}
1130
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001131status_t MediaPlayerService::Client::setLooping(int loop)
1132{
Steve Block3856b092011-10-20 11:56:00 +01001133 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001134 mLoop = loop;
1135 sp<MediaPlayerBase> p = getPlayer();
1136 if (p != 0) return p->setLooping(loop);
1137 return NO_ERROR;
1138}
1139
1140status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1141{
Steve Block3856b092011-10-20 11:56:00 +01001142 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -08001143
1144 // for hardware output, call player instead
1145 sp<MediaPlayerBase> p = getPlayer();
1146 {
1147 Mutex::Autolock l(mLock);
1148 if (p != 0 && p->hardwareOutput()) {
1149 MediaPlayerHWInterface* hwp =
1150 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1151 return hwp->setVolume(leftVolume, rightVolume);
1152 } else {
1153 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1154 return NO_ERROR;
1155 }
1156 }
1157
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001158 return NO_ERROR;
1159}
1160
Eric Laurent2beeb502010-07-16 07:43:46 -07001161status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1162{
Steve Block3856b092011-10-20 11:56:00 +01001163 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001164 Mutex::Autolock l(mLock);
1165 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1166 return NO_ERROR;
1167}
1168
1169status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1170{
Steve Block3856b092011-10-20 11:56:00 +01001171 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001172 Mutex::Autolock l(mLock);
1173 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1174 return NO_ERROR;
1175}
Nicolas Catania48290382009-07-10 13:53:06 -07001176
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001177status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001178 ALOGV("[%d] setParameter(%d)", mConnId, key);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001179 switch (key) {
1180 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
1181 {
1182 Mutex::Autolock l(mLock);
1183 return setAudioAttributes_l(request);
1184 }
1185 default:
1186 sp<MediaPlayerBase> p = getPlayer();
1187 if (p == 0) { return UNKNOWN_ERROR; }
1188 return p->setParameter(key, request);
1189 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001190}
1191
1192status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001193 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001194 sp<MediaPlayerBase> p = getPlayer();
1195 if (p == 0) return UNKNOWN_ERROR;
1196 return p->getParameter(key, reply);
1197}
1198
John Grossmanc795b642012-02-22 15:38:35 -08001199status_t MediaPlayerService::Client::setRetransmitEndpoint(
1200 const struct sockaddr_in* endpoint) {
1201
1202 if (NULL != endpoint) {
1203 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1204 uint16_t p = ntohs(endpoint->sin_port);
1205 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1206 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1207 } else {
1208 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1209 }
1210
1211 sp<MediaPlayerBase> p = getPlayer();
1212
1213 // Right now, the only valid time to set a retransmit endpoint is before
1214 // player selection has been made (since the presence or absence of a
1215 // retransmit endpoint is going to determine which player is selected during
1216 // setDataSource).
1217 if (p != 0) return INVALID_OPERATION;
1218
1219 if (NULL != endpoint) {
1220 mRetransmitEndpoint = *endpoint;
1221 mRetransmitEndpointValid = true;
1222 } else {
1223 mRetransmitEndpointValid = false;
1224 }
1225
1226 return NO_ERROR;
1227}
1228
John Grossman44a7e422012-06-21 17:29:24 -07001229status_t MediaPlayerService::Client::getRetransmitEndpoint(
1230 struct sockaddr_in* endpoint)
1231{
1232 if (NULL == endpoint)
1233 return BAD_VALUE;
1234
1235 sp<MediaPlayerBase> p = getPlayer();
1236
1237 if (p != NULL)
1238 return p->getRetransmitEndpoint(endpoint);
1239
1240 if (!mRetransmitEndpointValid)
1241 return NO_INIT;
1242
1243 *endpoint = mRetransmitEndpoint;
1244
1245 return NO_ERROR;
1246}
1247
Gloria Wangb483c472011-04-11 17:23:27 -07001248void MediaPlayerService::Client::notify(
1249 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001250{
1251 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001252 if (client == NULL) {
1253 return;
1254 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001255
James Dongb8a98252012-08-26 16:13:03 -07001256 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001257 {
1258 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001259 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001260 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001261 if (client->mAudioOutput != NULL)
1262 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001263 client->mNextClient->start();
1264 client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1265 }
1266 }
1267
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001268 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001269 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001270 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001271
1272 if(client->shouldDropMetadata(metadata_type)) {
1273 return;
1274 }
1275
1276 // Update the list of metadata that have changed. getMetadata
1277 // also access mMetadataUpdated and clears it.
1278 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001279 }
James Dongb8a98252012-08-26 16:13:03 -07001280
1281 if (c != NULL) {
1282 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1283 c->notify(msg, ext1, ext2, obj);
1284 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001285}
1286
Nicolas Catania48290382009-07-10 13:53:06 -07001287
nikoa64c8c72009-07-20 15:07:26 -07001288bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001289{
Nicolas Catania48290382009-07-10 13:53:06 -07001290 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001291
Nicolas Catania48290382009-07-10 13:53:06 -07001292 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001293 return true;
1294 }
1295
Nicolas Catania48290382009-07-10 13:53:06 -07001296 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001297 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001298 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001299 return true;
1300 }
1301}
1302
Nicolas Catania48290382009-07-10 13:53:06 -07001303
nikoa64c8c72009-07-20 15:07:26 -07001304void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001305 Mutex::Autolock lock(mLock);
1306 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1307 mMetadataUpdated.add(metadata_type);
1308 }
1309}
1310
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001311#if CALLBACK_ANTAGONIZER
1312const int Antagonizer::interval = 10000; // 10 msecs
1313
1314Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1315 mExit(false), mActive(false), mClient(client), mCb(cb)
1316{
1317 createThread(callbackThread, this);
1318}
1319
1320void Antagonizer::kill()
1321{
1322 Mutex::Autolock _l(mLock);
1323 mActive = false;
1324 mExit = true;
1325 mCondition.wait(mLock);
1326}
1327
1328int Antagonizer::callbackThread(void* user)
1329{
Steve Blockb8a80522011-12-20 16:23:08 +00001330 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001331 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1332 while (!p->mExit) {
1333 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001334 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001335 p->mCb(p->mClient, 0, 0, 0);
1336 }
1337 usleep(interval);
1338 }
1339 Mutex::Autolock _l(p->mLock);
1340 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001341 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001342 return 0;
1343}
1344#endif
1345
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001346#undef LOG_TAG
1347#define LOG_TAG "AudioSink"
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001348MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
1349 const audio_attributes_t* attr)
Andreas Huber20111aa2009-07-14 16:56:47 -07001350 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001351 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001352 mCallbackData(NULL),
Marco Nelissen4110c102012-03-29 09:31:28 -07001353 mBytesWritten(0),
Andy Hungd1c74342015-07-07 16:54:23 -07001354 mStreamType(AUDIO_STREAM_MUSIC),
Andy Hungd1c74342015-07-07 16:54:23 -07001355 mLeftVolume(1.0),
1356 mRightVolume(1.0),
1357 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
1358 mSampleRateHz(0),
1359 mMsecsPerFrame(0),
1360 mFrameSize(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001361 mSessionId(sessionId),
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001362 mUid(uid),
Marco Nelissend457c972014-02-11 08:47:07 -08001363 mPid(pid),
Andy Hungd1c74342015-07-07 16:54:23 -07001364 mSendLevel(0.0),
1365 mAuxEffectId(0),
1366 mFlags(AUDIO_OUTPUT_FLAG_NONE)
1367{
Steve Block3856b092011-10-20 11:56:00 +01001368 ALOGV("AudioOutput(%d)", sessionId);
Eric Laurent43562692015-07-15 16:49:07 -07001369 if (attr != NULL) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001370 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1371 if (mAttributes != NULL) {
1372 memcpy(mAttributes, attr, sizeof(audio_attributes_t));
1373 mStreamType = audio_attributes_to_stream_type(attr);
1374 }
1375 } else {
1376 mAttributes = NULL;
Eric Laurent43562692015-07-15 16:49:07 -07001377 }
1378
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001379 setMinBufferCount();
1380}
1381
1382MediaPlayerService::AudioOutput::~AudioOutput()
1383{
1384 close();
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001385 free(mAttributes);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001386 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001387}
1388
Andy Hungd1c74342015-07-07 16:54:23 -07001389//static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001390void MediaPlayerService::AudioOutput::setMinBufferCount()
1391{
1392 char value[PROPERTY_VALUE_MAX];
1393 if (property_get("ro.kernel.qemu", value, 0)) {
1394 mIsOnEmulator = true;
1395 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1396 }
1397}
1398
Andy Hungd1c74342015-07-07 16:54:23 -07001399// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001400bool MediaPlayerService::AudioOutput::isOnEmulator()
1401{
Andy Hungd1c74342015-07-07 16:54:23 -07001402 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001403 return mIsOnEmulator;
1404}
1405
Andy Hungd1c74342015-07-07 16:54:23 -07001406// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001407int MediaPlayerService::AudioOutput::getMinBufferCount()
1408{
Andy Hungd1c74342015-07-07 16:54:23 -07001409 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001410 return mMinBufferCount;
1411}
1412
1413ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1414{
Andy Hungd1c74342015-07-07 16:54:23 -07001415 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001416 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001417 return mTrack->frameCount() * mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001418}
1419
1420ssize_t MediaPlayerService::AudioOutput::frameCount() const
1421{
Andy Hungd1c74342015-07-07 16:54:23 -07001422 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001423 if (mTrack == 0) return NO_INIT;
1424 return mTrack->frameCount();
1425}
1426
1427ssize_t MediaPlayerService::AudioOutput::channelCount() const
1428{
Andy Hungd1c74342015-07-07 16:54:23 -07001429 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001430 if (mTrack == 0) return NO_INIT;
1431 return mTrack->channelCount();
1432}
1433
1434ssize_t MediaPlayerService::AudioOutput::frameSize() const
1435{
Andy Hungd1c74342015-07-07 16:54:23 -07001436 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001437 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001438 return mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001439}
1440
1441uint32_t MediaPlayerService::AudioOutput::latency () const
1442{
Andy Hungd1c74342015-07-07 16:54:23 -07001443 Mutex::Autolock lock(mLock);
Eric Laurentdb354e52012-03-05 17:27:11 -08001444 if (mTrack == 0) return 0;
1445 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001446}
1447
1448float MediaPlayerService::AudioOutput::msecsPerFrame() const
1449{
Andy Hungd1c74342015-07-07 16:54:23 -07001450 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001451 return mMsecsPerFrame;
1452}
1453
Marco Nelissen4110c102012-03-29 09:31:28 -07001454status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001455{
Andy Hungd1c74342015-07-07 16:54:23 -07001456 Mutex::Autolock lock(mLock);
Eric Laurent342e9cf2010-01-19 17:37:09 -08001457 if (mTrack == 0) return NO_INIT;
1458 return mTrack->getPosition(position);
1459}
1460
Lajos Molnar06ad1522014-08-28 07:27:44 -07001461status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const
1462{
Andy Hungd1c74342015-07-07 16:54:23 -07001463 Mutex::Autolock lock(mLock);
Lajos Molnar06ad1522014-08-28 07:27:44 -07001464 if (mTrack == 0) return NO_INIT;
1465 return mTrack->getTimestamp(ts);
1466}
1467
Marco Nelissen4110c102012-03-29 09:31:28 -07001468status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1469{
Andy Hungd1c74342015-07-07 16:54:23 -07001470 Mutex::Autolock lock(mLock);
Marco Nelissen4110c102012-03-29 09:31:28 -07001471 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001472 *frameswritten = mBytesWritten / mFrameSize;
Marco Nelissen4110c102012-03-29 09:31:28 -07001473 return OK;
1474}
1475
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001476status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
1477{
Andy Hungd1c74342015-07-07 16:54:23 -07001478 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001479 if (mTrack == 0) return NO_INIT;
1480 return mTrack->setParameters(keyValuePairs);
1481}
1482
1483String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
1484{
Andy Hungd1c74342015-07-07 16:54:23 -07001485 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001486 if (mTrack == 0) return String8::empty();
1487 return mTrack->getParameters(keys);
1488}
1489
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001490void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
Andy Hungd1c74342015-07-07 16:54:23 -07001491 Mutex::Autolock lock(mLock);
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001492 if (attributes == NULL) {
1493 free(mAttributes);
1494 mAttributes = NULL;
1495 } else {
1496 if (mAttributes == NULL) {
1497 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1498 }
1499 memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
Eric Laurent43562692015-07-15 16:49:07 -07001500 mStreamType = audio_attributes_to_stream_type(attributes);
1501 }
1502}
1503
1504void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
1505{
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001506 Mutex::Autolock lock(mLock);
Eric Laurent43562692015-07-15 16:49:07 -07001507 // do not allow direct stream type modification if attributes have been set
1508 if (mAttributes == NULL) {
1509 mStreamType = streamType;
1510 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001511}
1512
Andy Hungd1c74342015-07-07 16:54:23 -07001513void MediaPlayerService::AudioOutput::deleteRecycledTrack_l()
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001514{
Andy Hungd1c74342015-07-07 16:54:23 -07001515 ALOGV("deleteRecycledTrack_l");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001516 if (mRecycledTrack != 0) {
1517
1518 if (mCallbackData != NULL) {
1519 mCallbackData->setOutput(NULL);
1520 mCallbackData->endTrackSwitch();
1521 }
1522
1523 if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
1524 mRecycledTrack->flush();
1525 }
1526 // An offloaded track isn't flushed because the STREAM_END is reported
1527 // slightly prematurely to allow time for the gapless track switch
1528 // but this means that if we decide not to recycle the track there
1529 // could be a small amount of residual data still playing. We leave
1530 // AudioFlinger to drain the track.
1531
1532 mRecycledTrack.clear();
Andy Hungd1c74342015-07-07 16:54:23 -07001533 close_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001534 delete mCallbackData;
1535 mCallbackData = NULL;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001536 }
1537}
1538
Andy Hungd1c74342015-07-07 16:54:23 -07001539void MediaPlayerService::AudioOutput::close_l()
1540{
1541 mTrack.clear();
1542}
1543
Andreas Huber20111aa2009-07-14 16:56:47 -07001544status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001545 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1546 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001547 AudioCallback cb, void *cookie,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001548 audio_output_flags_t flags,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001549 const audio_offload_info_t *offloadInfo,
Andy Hung179652e2015-05-31 22:49:46 -07001550 bool doNotReconnect,
1551 uint32_t suggestedFrameCount)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001552{
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001553 ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
1554 format, bufferCount, mSessionId, flags);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001555
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001556 // offloading is only supported in callback mode for now.
1557 // offloadInfo must be present if offload flag is set
1558 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
1559 ((cb == NULL) || (offloadInfo == NULL))) {
1560 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001561 }
1562
Andy Hung179652e2015-05-31 22:49:46 -07001563 // compute frame count for the AudioTrack internal buffer
1564 size_t frameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001565 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1566 frameCount = 0; // AudioTrack will get frame count from AudioFlinger
1567 } else {
Andy Hung179652e2015-05-31 22:49:46 -07001568 // try to estimate the buffer processing fetch size from AudioFlinger.
1569 // framesPerBuffer is approximate and generally correct, except when it's not :-).
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001570 uint32_t afSampleRate;
1571 size_t afFrameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001572 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1573 return NO_INIT;
1574 }
1575 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1576 return NO_INIT;
1577 }
Andy Hung179652e2015-05-31 22:49:46 -07001578 const size_t framesPerBuffer =
1579 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001580
Andy Hung179652e2015-05-31 22:49:46 -07001581 if (bufferCount == 0) {
1582 // use suggestedFrameCount
1583 bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
1584 }
1585 // Check argument bufferCount against the mininum buffer count
1586 if (bufferCount != 0 && bufferCount < mMinBufferCount) {
1587 ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
1588 bufferCount = mMinBufferCount;
1589 }
1590 // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
1591 // which will be the minimum size permitted.
1592 frameCount = bufferCount * framesPerBuffer;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001593 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001594
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001595 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001596 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001597 if (0 == channelMask) {
1598 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1599 return NO_INIT;
1600 }
1601 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001602
Andy Hungd1c74342015-07-07 16:54:23 -07001603 Mutex::Autolock lock(mLock);
Andy Hung179652e2015-05-31 22:49:46 -07001604 mCallback = cb;
1605 mCallbackCookie = cookie;
1606
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001607 // Check whether we can recycle the track
1608 bool reuse = false;
1609 bool bothOffloaded = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001610
Glenn Kasten2799d742013-05-30 14:33:29 -07001611 if (mRecycledTrack != 0) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001612 // check whether we are switching between two offloaded tracks
1613 bothOffloaded = (flags & mRecycledTrack->getFlags()
1614 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
Marco Nelissen67295b52012-06-11 14:52:53 -07001615
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001616 // check if the existing track can be reused as-is, or if a new track needs to be created.
1617 reuse = true;
1618
Marco Nelissen67295b52012-06-11 14:52:53 -07001619 if ((mCallbackData == NULL && mCallback != NULL) ||
1620 (mCallbackData != NULL && mCallback == NULL)) {
1621 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1622 ALOGV("can't chain callback and write");
1623 reuse = false;
1624 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001625 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
1626 ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
Marco Nelissen67295b52012-06-11 14:52:53 -07001627 mRecycledTrack->getSampleRate(), sampleRate,
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001628 mRecycledTrack->channelCount(), channelCount);
Marco Nelissen67295b52012-06-11 14:52:53 -07001629 reuse = false;
1630 } else if (flags != mFlags) {
1631 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1632 reuse = false;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001633 } else if (mRecycledTrack->format() != format) {
1634 reuse = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001635 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001636 } else {
1637 ALOGV("no track available to recycle");
1638 }
1639
1640 ALOGV_IF(bothOffloaded, "both tracks offloaded");
1641
1642 // If we can't recycle and both tracks are offloaded
1643 // we must close the previous output before opening a new one
1644 if (bothOffloaded && !reuse) {
1645 ALOGV("both offloaded and not recycling");
Andy Hungd1c74342015-07-07 16:54:23 -07001646 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001647 }
1648
1649 sp<AudioTrack> t;
1650 CallbackData *newcbd = NULL;
1651
1652 // We don't attempt to create a new track if we are recycling an
1653 // offloaded track. But, if we are recycling a non-offloaded or we
1654 // are switching where one is offloaded and one isn't then we create
1655 // the new track in advance so that we can read additional stream info
1656
1657 if (!(reuse && bothOffloaded)) {
1658 ALOGV("creating new AudioTrack");
1659
1660 if (mCallback != NULL) {
1661 newcbd = new CallbackData(this);
1662 t = new AudioTrack(
1663 mStreamType,
1664 sampleRate,
1665 format,
1666 channelMask,
1667 frameCount,
1668 flags,
1669 CallbackWrapper,
1670 newcbd,
1671 0, // notification frames
1672 mSessionId,
1673 AudioTrack::TRANSFER_CALLBACK,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001674 offloadInfo,
Marco Nelissend457c972014-02-11 08:47:07 -08001675 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001676 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001677 mAttributes,
1678 doNotReconnect);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001679 } else {
1680 t = new AudioTrack(
1681 mStreamType,
1682 sampleRate,
1683 format,
1684 channelMask,
1685 frameCount,
1686 flags,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001687 NULL, // callback
1688 NULL, // user data
1689 0, // notification frames
1690 mSessionId,
1691 AudioTrack::TRANSFER_DEFAULT,
1692 NULL, // offload info
Marco Nelissend457c972014-02-11 08:47:07 -08001693 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001694 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001695 mAttributes,
1696 doNotReconnect);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001697 }
1698
1699 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1700 ALOGE("Unable to create audio track");
1701 delete newcbd;
Glenn Kasten3e98ecd2015-05-18 13:13:24 -07001702 // t goes out of scope, so reference count drops to zero
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001703 return NO_INIT;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001704 } else {
1705 // successful AudioTrack initialization implies a legacy stream type was generated
1706 // from the audio attributes
1707 mStreamType = t->streamType();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001708 }
1709 }
1710
1711 if (reuse) {
1712 CHECK(mRecycledTrack != NULL);
1713
1714 if (!bothOffloaded) {
1715 if (mRecycledTrack->frameCount() != t->frameCount()) {
1716 ALOGV("framecount differs: %u/%u frames",
1717 mRecycledTrack->frameCount(), t->frameCount());
1718 reuse = false;
1719 }
1720 }
1721
Marco Nelissen67295b52012-06-11 14:52:53 -07001722 if (reuse) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001723 ALOGV("chaining to next output and recycling track");
Andy Hungd1c74342015-07-07 16:54:23 -07001724 close_l();
Marco Nelissen67295b52012-06-11 14:52:53 -07001725 mTrack = mRecycledTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001726 mRecycledTrack.clear();
Marco Nelissen67295b52012-06-11 14:52:53 -07001727 if (mCallbackData != NULL) {
1728 mCallbackData->setOutput(this);
1729 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001730 delete newcbd;
1731 return OK;
1732 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001733 }
1734
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001735 // we're not going to reuse the track, unblock and flush it
1736 // this was done earlier if both tracks are offloaded
1737 if (!bothOffloaded) {
Andy Hungd1c74342015-07-07 16:54:23 -07001738 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001739 }
1740
1741 CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
1742
Marco Nelissen67295b52012-06-11 14:52:53 -07001743 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001744 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001745 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001746
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001747 mSampleRateHz = sampleRate;
Wei Jia0162d002015-06-09 11:59:33 -07001748 mFlags = t->getFlags(); // we suggest the flags above, but new AudioTrack() may not grant it.
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001749 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Andy Hungd1c74342015-07-07 16:54:23 -07001750 mFrameSize = t->frameSize();
Marco Nelissen99448602012-04-02 12:16:49 -07001751 uint32_t pos;
1752 if (t->getPosition(&pos) == OK) {
Andy Hungd1c74342015-07-07 16:54:23 -07001753 mBytesWritten = uint64_t(pos) * mFrameSize;
Marco Nelissen99448602012-04-02 12:16:49 -07001754 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001755 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001756
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001757 status_t res = NO_ERROR;
Wei Jia0162d002015-06-09 11:59:33 -07001758 // Note some output devices may give us a direct track even though we don't specify it.
1759 // Example: Line application b/17459982.
1760 if ((mFlags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001761 res = t->setPlaybackRate(mPlaybackRate);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001762 if (res == NO_ERROR) {
1763 t->setAuxEffectSendLevel(mSendLevel);
1764 res = t->attachAuxEffect(mAuxEffectId);
1765 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001766 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001767 ALOGV("open() DONE status %d", res);
1768 return res;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001769}
1770
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001771status_t MediaPlayerService::AudioOutput::start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001772{
Steve Block3856b092011-10-20 11:56:00 +01001773 ALOGV("start");
Andy Hungd1c74342015-07-07 16:54:23 -07001774 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001775 if (mCallbackData != NULL) {
1776 mCallbackData->endTrackSwitch();
1777 }
Glenn Kasten2799d742013-05-30 14:33:29 -07001778 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001779 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001780 mTrack->setAuxEffectSendLevel(mSendLevel);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001781 return mTrack->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001782 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001783 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001784}
1785
Marco Nelissen6b74d672012-02-28 16:07:44 -08001786void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
Andy Hungd1c74342015-07-07 16:54:23 -07001787 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001788 mNextOutput = nextOutput;
1789}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001790
Marco Nelissen6b74d672012-02-28 16:07:44 -08001791void MediaPlayerService::AudioOutput::switchToNextOutput() {
1792 ALOGV("switchToNextOutput");
Andy Hungd1c74342015-07-07 16:54:23 -07001793
1794 // Try to acquire the callback lock before moving track (without incurring deadlock).
1795 const unsigned kMaxSwitchTries = 100;
1796 Mutex::Autolock lock(mLock);
1797 for (unsigned tries = 0;;) {
1798 if (mTrack == 0) {
1799 return;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001800 }
Andy Hungd1c74342015-07-07 16:54:23 -07001801 if (mNextOutput != NULL && mNextOutput != this) {
1802 if (mCallbackData != NULL) {
1803 // two alternative approaches
1804#if 1
1805 CallbackData *callbackData = mCallbackData;
1806 mLock.unlock();
1807 // proper acquisition sequence
1808 callbackData->lock();
1809 mLock.lock();
1810 // Caution: it is unlikely that someone deleted our callback or changed our target
1811 if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
1812 // fatal if we are starved out.
1813 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1814 "switchToNextOutput() cannot obtain correct lock sequence");
1815 callbackData->unlock();
1816 continue;
1817 }
1818 callbackData->mSwitching = true; // begin track switch
1819#else
1820 // tryBeginTrackSwitch() returns false if the callback has the lock.
1821 if (!mCallbackData->tryBeginTrackSwitch()) {
1822 // fatal if we are starved out.
1823 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1824 "switchToNextOutput() cannot obtain callback lock");
1825 mLock.unlock();
1826 usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
1827 mLock.lock();
1828 continue;
1829 }
1830#endif
1831 }
1832
1833 Mutex::Autolock nextLock(mNextOutput->mLock);
1834
1835 // If the next output track is not NULL, then it has been
1836 // opened already for playback.
1837 // This is possible even without the next player being started,
1838 // for example, the next player could be prepared and seeked.
1839 //
1840 // Presuming it isn't advisable to force the track over.
1841 if (mNextOutput->mTrack == NULL) {
1842 ALOGD("Recycling track for gapless playback");
1843 delete mNextOutput->mCallbackData;
1844 mNextOutput->mCallbackData = mCallbackData;
1845 mNextOutput->mRecycledTrack = mTrack;
1846 mNextOutput->mSampleRateHz = mSampleRateHz;
1847 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
1848 mNextOutput->mBytesWritten = mBytesWritten;
1849 mNextOutput->mFlags = mFlags;
1850 mNextOutput->mFrameSize = mFrameSize;
1851 close_l();
1852 mCallbackData = NULL; // destruction handled by mNextOutput
1853 } else {
1854 ALOGW("Ignoring gapless playback because next player has already started");
1855 // remove track in case resource needed for future players.
1856 if (mCallbackData != NULL) {
1857 mCallbackData->endTrackSwitch(); // release lock for callbacks before close.
1858 }
1859 close_l();
1860 }
1861 }
1862 break;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001863 }
1864}
1865
Wei Jia7d3f4df2015-03-03 15:28:00 -08001866ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001867{
Andy Hungd1c74342015-07-07 16:54:23 -07001868 Mutex::Autolock lock(mLock);
Glenn Kastenadad3d72014-02-21 14:51:43 -08001869 LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
Andreas Huber20111aa2009-07-14 16:56:47 -07001870
Steve Block3856b092011-10-20 11:56:00 +01001871 //ALOGV("write(%p, %u)", buffer, size);
Glenn Kasten2799d742013-05-30 14:33:29 -07001872 if (mTrack != 0) {
Wei Jia7d3f4df2015-03-03 15:28:00 -08001873 ssize_t ret = mTrack->write(buffer, size, blocking);
Andy Hunga31335a2014-08-20 17:37:59 -07001874 if (ret >= 0) {
1875 mBytesWritten += ret;
1876 }
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001877 return ret;
1878 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001879 return NO_INIT;
1880}
1881
1882void MediaPlayerService::AudioOutput::stop()
1883{
Steve Block3856b092011-10-20 11:56:00 +01001884 ALOGV("stop");
Andy Hungd1c74342015-07-07 16:54:23 -07001885 Mutex::Autolock lock(mLock);
Andy Hungda17c042015-06-01 15:53:14 -07001886 mBytesWritten = 0;
Glenn Kasten2799d742013-05-30 14:33:29 -07001887 if (mTrack != 0) mTrack->stop();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001888}
1889
1890void MediaPlayerService::AudioOutput::flush()
1891{
Steve Block3856b092011-10-20 11:56:00 +01001892 ALOGV("flush");
Andy Hungd1c74342015-07-07 16:54:23 -07001893 Mutex::Autolock lock(mLock);
Andy Hungda17c042015-06-01 15:53:14 -07001894 mBytesWritten = 0;
Glenn Kasten2799d742013-05-30 14:33:29 -07001895 if (mTrack != 0) mTrack->flush();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001896}
1897
1898void MediaPlayerService::AudioOutput::pause()
1899{
Steve Block3856b092011-10-20 11:56:00 +01001900 ALOGV("pause");
Andy Hungd1c74342015-07-07 16:54:23 -07001901 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001902 if (mTrack != 0) mTrack->pause();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001903}
1904
1905void MediaPlayerService::AudioOutput::close()
1906{
Steve Block3856b092011-10-20 11:56:00 +01001907 ALOGV("close");
Andy Hungd1c74342015-07-07 16:54:23 -07001908 Mutex::Autolock lock(mLock);
1909 close_l();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001910}
1911
1912void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1913{
Steve Block3856b092011-10-20 11:56:00 +01001914 ALOGV("setVolume(%f, %f)", left, right);
Andy Hungd1c74342015-07-07 16:54:23 -07001915 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001916 mLeftVolume = left;
1917 mRightVolume = right;
Glenn Kasten2799d742013-05-30 14:33:29 -07001918 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001919 mTrack->setVolume(left, right);
1920 }
1921}
1922
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001923status_t MediaPlayerService::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001924{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001925 ALOGV("setPlaybackRate(%f %f %d %d)",
1926 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Andy Hungd1c74342015-07-07 16:54:23 -07001927 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001928 if (mTrack == 0) {
1929 // remember rate so that we can set it when the track is opened
1930 mPlaybackRate = rate;
1931 return OK;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001932 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001933 status_t res = mTrack->setPlaybackRate(rate);
1934 if (res != NO_ERROR) {
1935 return res;
1936 }
1937 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
1938 CHECK_GT(rate.mSpeed, 0.f);
1939 mPlaybackRate = rate;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001940 if (mSampleRateHz != 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001941 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001942 }
1943 return res;
1944}
1945
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001946status_t MediaPlayerService::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
1947{
1948 ALOGV("setPlaybackRate");
Andy Hungd1c74342015-07-07 16:54:23 -07001949 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001950 if (mTrack == 0) {
1951 return NO_INIT;
1952 }
1953 *rate = mTrack->getPlaybackRate();
1954 return NO_ERROR;
1955}
1956
Eric Laurent2beeb502010-07-16 07:43:46 -07001957status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
1958{
Steve Block3856b092011-10-20 11:56:00 +01001959 ALOGV("setAuxEffectSendLevel(%f)", level);
Andy Hungd1c74342015-07-07 16:54:23 -07001960 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07001961 mSendLevel = level;
Glenn Kasten2799d742013-05-30 14:33:29 -07001962 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07001963 return mTrack->setAuxEffectSendLevel(level);
1964 }
1965 return NO_ERROR;
1966}
1967
1968status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
1969{
Steve Block3856b092011-10-20 11:56:00 +01001970 ALOGV("attachAuxEffect(%d)", effectId);
Andy Hungd1c74342015-07-07 16:54:23 -07001971 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07001972 mAuxEffectId = effectId;
Glenn Kasten2799d742013-05-30 14:33:29 -07001973 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07001974 return mTrack->attachAuxEffect(effectId);
1975 }
1976 return NO_ERROR;
1977}
1978
Andreas Huber20111aa2009-07-14 16:56:47 -07001979// static
1980void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07001981 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01001982 //ALOGV("callbackwrapper");
Marco Nelissen6b74d672012-02-28 16:07:44 -08001983 CallbackData *data = (CallbackData*)cookie;
Andy Hungd1c74342015-07-07 16:54:23 -07001984 // lock to ensure we aren't caught in the middle of a track switch.
Marco Nelissen6b74d672012-02-28 16:07:44 -08001985 data->lock();
1986 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07001987 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001988 if (me == NULL) {
1989 // no output set, likely because the track was scheduled to be reused
1990 // by another player, but the format turned out to be incompatible.
1991 data->unlock();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001992 if (buffer != NULL) {
1993 buffer->size = 0;
1994 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001995 return;
1996 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001997
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001998 switch(event) {
1999 case AudioTrack::EVENT_MORE_DATA: {
2000 size_t actualSize = (*me->mCallback)(
2001 me, buffer->raw, buffer->size, me->mCallbackCookie,
2002 CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002003
Andy Hung719b46b2015-05-31 22:18:25 -07002004 // Log when no data is returned from the callback.
2005 // (1) We may have no data (especially with network streaming sources).
2006 // (2) We may have reached the EOS and the audio track is not stopped yet.
2007 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
2008 // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill).
2009 //
2010 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
2011 // nevertheless for power reasons, we don't want to see too many of these.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08002012
Andy Hung719b46b2015-05-31 22:18:25 -07002013 ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002014
Andy Hung719b46b2015-05-31 22:18:25 -07002015 me->mBytesWritten += actualSize; // benign race with reader.
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002016 buffer->size = actualSize;
2017 } break;
2018
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002019 case AudioTrack::EVENT_STREAM_END:
Andy Hung719b46b2015-05-31 22:18:25 -07002020 // currently only occurs for offloaded callbacks
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002021 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
2022 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2023 me->mCallbackCookie, CB_EVENT_STREAM_END);
2024 break;
2025
2026 case AudioTrack::EVENT_NEW_IAUDIOTRACK :
2027 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
2028 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2029 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
2030 break;
2031
Glenn Kasten421743b2015-06-01 08:18:08 -07002032 case AudioTrack::EVENT_UNDERRUN:
Andy Hung719b46b2015-05-31 22:18:25 -07002033 // This occurs when there is no data available, typically
Glenn Kasten421743b2015-06-01 08:18:08 -07002034 // when there is a failure to supply data to the AudioTrack. It can also
2035 // occur in non-offloaded mode when the audio device comes out of standby.
2036 //
Andy Hung719b46b2015-05-31 22:18:25 -07002037 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
2038 // it may sound like an audible pop or glitch.
2039 //
2040 // The underrun event is sent once per track underrun; the condition is reset
2041 // when more data is sent to the AudioTrack.
Glenn Kasten421743b2015-06-01 08:18:08 -07002042 ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
2043 break;
2044
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002045 default:
2046 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
Andreas Huber51c1e0e2011-04-04 11:43:40 -07002047 }
2048
Marco Nelissen6b74d672012-02-28 16:07:44 -08002049 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07002050}
2051
Marco Nelissen4110c102012-03-29 09:31:28 -07002052int MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07002053{
Andy Hungd1c74342015-07-07 16:54:23 -07002054 Mutex::Autolock lock(mLock);
Eric Laurent8c563ed2010-10-07 18:23:03 -07002055 return mSessionId;
2056}
2057
Eric Laurent6f59db12013-07-26 17:16:50 -07002058uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
2059{
Andy Hungd1c74342015-07-07 16:54:23 -07002060 Mutex::Autolock lock(mLock);
Eric Laurent6f59db12013-07-26 17:16:50 -07002061 if (mTrack == 0) return 0;
2062 return mTrack->getSampleRate();
2063}
2064
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002065////////////////////////////////////////////////////////////////////////////////
2066
2067struct CallbackThread : public Thread {
2068 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
2069 MediaPlayerBase::AudioSink::AudioCallback cb,
2070 void *cookie);
2071
2072protected:
2073 virtual ~CallbackThread();
2074
2075 virtual bool threadLoop();
2076
2077private:
2078 wp<MediaPlayerBase::AudioSink> mSink;
2079 MediaPlayerBase::AudioSink::AudioCallback mCallback;
2080 void *mCookie;
2081 void *mBuffer;
2082 size_t mBufferSize;
2083
2084 CallbackThread(const CallbackThread &);
2085 CallbackThread &operator=(const CallbackThread &);
2086};
2087
2088CallbackThread::CallbackThread(
2089 const wp<MediaPlayerBase::AudioSink> &sink,
2090 MediaPlayerBase::AudioSink::AudioCallback cb,
2091 void *cookie)
2092 : mSink(sink),
2093 mCallback(cb),
2094 mCookie(cookie),
2095 mBuffer(NULL),
2096 mBufferSize(0) {
2097}
2098
2099CallbackThread::~CallbackThread() {
2100 if (mBuffer) {
2101 free(mBuffer);
2102 mBuffer = NULL;
2103 }
2104}
2105
2106bool CallbackThread::threadLoop() {
2107 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
2108 if (sink == NULL) {
2109 return false;
2110 }
2111
2112 if (mBuffer == NULL) {
2113 mBufferSize = sink->bufferSize();
2114 mBuffer = malloc(mBufferSize);
2115 }
2116
2117 size_t actualSize =
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00002118 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
2119 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002120
2121 if (actualSize > 0) {
2122 sink->write(mBuffer, actualSize);
Andy Hunga31335a2014-08-20 17:37:59 -07002123 // Could return false on sink->write() error or short count.
2124 // Not necessarily appropriate but would work for AudioCache behavior.
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002125 }
2126
2127 return true;
2128}
2129
2130////////////////////////////////////////////////////////////////////////////////
2131
Gloria Wang7cf180c2011-02-19 18:37:57 -08002132void MediaPlayerService::addBatteryData(uint32_t params)
2133{
2134 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002135
2136 int32_t time = systemTime() / 1000000L;
2137
2138 // change audio output devices. This notification comes from AudioFlinger
2139 if ((params & kBatteryDataSpeakerOn)
2140 || (params & kBatteryDataOtherAudioDeviceOn)) {
2141
2142 int deviceOn[NUM_AUDIO_DEVICES];
2143 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2144 deviceOn[i] = 0;
2145 }
2146
2147 if ((params & kBatteryDataSpeakerOn)
2148 && (params & kBatteryDataOtherAudioDeviceOn)) {
2149 deviceOn[SPEAKER_AND_OTHER] = 1;
2150 } else if (params & kBatteryDataSpeakerOn) {
2151 deviceOn[SPEAKER] = 1;
2152 } else {
2153 deviceOn[OTHER_AUDIO_DEVICE] = 1;
2154 }
2155
2156 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2157 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2158
2159 if (mBatteryAudio.refCount > 0) { // if playing audio
2160 if (!deviceOn[i]) {
2161 mBatteryAudio.lastTime[i] += time;
2162 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2163 mBatteryAudio.lastTime[i] = 0;
2164 } else {
2165 mBatteryAudio.lastTime[i] = 0 - time;
2166 }
2167 }
2168
2169 mBatteryAudio.deviceOn[i] = deviceOn[i];
2170 }
2171 }
2172 return;
2173 }
2174
Marco Nelissenb7848f12014-12-04 08:57:56 -08002175 // an audio stream is started
Gloria Wang9ee159b2011-02-24 14:51:45 -08002176 if (params & kBatteryDataAudioFlingerStart) {
2177 // record the start time only if currently no other audio
2178 // is being played
2179 if (mBatteryAudio.refCount == 0) {
2180 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2181 if (mBatteryAudio.deviceOn[i]) {
2182 mBatteryAudio.lastTime[i] -= time;
2183 }
2184 }
2185 }
2186
2187 mBatteryAudio.refCount ++;
2188 return;
2189
2190 } else if (params & kBatteryDataAudioFlingerStop) {
2191 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002192 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002193 return;
2194 }
2195
2196 // record the stop time only if currently this is the only
2197 // audio being played
2198 if (mBatteryAudio.refCount == 1) {
2199 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2200 if (mBatteryAudio.deviceOn[i]) {
2201 mBatteryAudio.lastTime[i] += time;
2202 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2203 mBatteryAudio.lastTime[i] = 0;
2204 }
2205 }
2206 }
2207
2208 mBatteryAudio.refCount --;
2209 return;
2210 }
2211
Gloria Wang7cf180c2011-02-19 18:37:57 -08002212 int uid = IPCThreadState::self()->getCallingUid();
2213 if (uid == AID_MEDIA) {
2214 return;
2215 }
2216 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08002217
2218 if (index < 0) { // create a new entry for this UID
2219 BatteryUsageInfo info;
2220 info.audioTotalTime = 0;
2221 info.videoTotalTime = 0;
2222 info.audioLastTime = 0;
2223 info.videoLastTime = 0;
2224 info.refCount = 0;
2225
Gloria Wang9ee159b2011-02-24 14:51:45 -08002226 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00002227 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002228 return;
2229 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08002230 }
2231
2232 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2233
2234 if (params & kBatteryDataCodecStarted) {
2235 if (params & kBatteryDataTrackAudio) {
2236 info.audioLastTime -= time;
2237 info.refCount ++;
2238 }
2239 if (params & kBatteryDataTrackVideo) {
2240 info.videoLastTime -= time;
2241 info.refCount ++;
2242 }
2243 } else {
2244 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002245 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002246 return;
2247 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00002248 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002249 mBatteryData.removeItem(uid);
2250 return;
2251 }
2252
2253 if (params & kBatteryDataTrackAudio) {
2254 info.audioLastTime += time;
2255 info.refCount --;
2256 }
2257 if (params & kBatteryDataTrackVideo) {
2258 info.videoLastTime += time;
2259 info.refCount --;
2260 }
2261
2262 // no stream is being played by this UID
2263 if (info.refCount == 0) {
2264 info.audioTotalTime += info.audioLastTime;
2265 info.audioLastTime = 0;
2266 info.videoTotalTime += info.videoLastTime;
2267 info.videoLastTime = 0;
2268 }
2269 }
2270}
2271
2272status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2273 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002274
2275 // audio output devices usage
2276 int32_t time = systemTime() / 1000000L; //in ms
2277 int32_t totalTime;
2278
2279 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2280 totalTime = mBatteryAudio.totalTime[i];
2281
2282 if (mBatteryAudio.deviceOn[i]
2283 && (mBatteryAudio.lastTime[i] != 0)) {
2284 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2285 totalTime += tmpTime;
2286 }
2287
2288 reply->writeInt32(totalTime);
2289 // reset the total time
2290 mBatteryAudio.totalTime[i] = 0;
2291 }
2292
2293 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002294 BatteryUsageInfo info;
2295 int size = mBatteryData.size();
2296
2297 reply->writeInt32(size);
2298 int i = 0;
2299
2300 while (i < size) {
2301 info = mBatteryData.valueAt(i);
2302
2303 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2304 reply->writeInt32(info.audioTotalTime);
2305 reply->writeInt32(info.videoTotalTime);
2306
2307 info.audioTotalTime = 0;
2308 info.videoTotalTime = 0;
2309
2310 // remove the UID entry where no stream is being played
2311 if (info.refCount <= 0) {
2312 mBatteryData.removeItemsAt(i);
2313 size --;
2314 i --;
2315 }
2316 i++;
2317 }
2318 return NO_ERROR;
2319}
nikoa64c8c72009-07-20 15:07:26 -07002320} // namespace android