blob: f0190c4f4e5bb909c9e29e17dc41c41d45f089a0 [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>
Marco Nelissen83b0fd92015-09-16 13:48:07 -070060#include <media/stagefright/Utils.h>
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +010061#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
Andy Hung53541292016-04-13 16:48:51 -070065#include <memunreachable/memunreachable.h>
Dima Zavin64760242011-05-11 14:15:23 -070066#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070067
Gloria Wang7cf180c2011-02-19 18:37:57 -080068#include <private/android_filesystem_config.h>
69
James Dong559bf282012-03-28 10:29:14 -070070#include "ActivityManager.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080071#include "MediaRecorderClient.h"
72#include "MediaPlayerService.h"
73#include "MetadataRetrieverClient.h"
John Grossman44a7e422012-06-21 17:29:24 -070074#include "MediaPlayerFactory.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080075
Nicolas Catania14d27472009-07-13 14:37:49 -070076#include "TestPlayerStub.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 Huber59451f82012-09-18 10:36:32 -070081#include "HDCP.h"
Andreas Huberb7319a72013-05-29 14:20:52 -070082#include "HTTPBase.h"
Andreas Huber35213f12012-08-29 11:41:50 -070083#include "RemoteDisplay.h"
Andreas Hubered3e3e02012-03-26 11:13:27 -070084
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070085namespace {
nikoa64c8c72009-07-20 15:07:26 -070086using android::media::Metadata;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070087using android::status_t;
88using android::OK;
89using android::BAD_VALUE;
90using android::NOT_ENOUGH_DATA;
91using android::Parcel;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070092
93// Max number of entries in the filter.
94const int kMaxFilterSize = 64; // I pulled that out of thin air.
95
Andy Hungff874dc2016-04-11 16:49:09 -070096const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
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 {
Andy Hung833b4752016-04-04 17:15:48 -0700151 ALOGE("Filter too short expected %zu but got %zu", 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;
240 utf16_to_utf8(tags.string(), tagSize, attributes->tags);
241 }
242 } else {
243 ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
244 strcpy(attributes->tags, "");
245 }
246}
247} // anonymous namespace
248
249
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800250namespace android {
251
Marco Nelissenf09611f2015-02-13 14:12:42 -0800252extern ALooperRoster gLooperRoster;
253
254
Dave Burked681bbb2011-08-30 14:39:17 +0100255static bool checkPermission(const char* permissionString) {
Dave Burked681bbb2011-08-30 14:39:17 +0100256 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
257 bool ok = checkCallingPermission(String16(permissionString));
Steve Block29357bc2012-01-06 19:20:56 +0000258 if (!ok) ALOGE("Request requires %s", permissionString);
Dave Burked681bbb2011-08-30 14:39:17 +0100259 return ok;
260}
261
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800262// 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 -0800263/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
264/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
265
266void MediaPlayerService::instantiate() {
267 defaultServiceManager()->addService(
268 String16("media.player"), new MediaPlayerService());
269}
270
271MediaPlayerService::MediaPlayerService()
272{
Steve Block3856b092011-10-20 11:56:00 +0100273 ALOGV("MediaPlayerService created");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800274 mNextConnId = 1;
Gloria Wang9ee159b2011-02-24 14:51:45 -0800275
276 mBatteryAudio.refCount = 0;
277 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
278 mBatteryAudio.deviceOn[i] = 0;
279 mBatteryAudio.lastTime[i] = 0;
280 mBatteryAudio.totalTime[i] = 0;
281 }
282 // speaker is on by default
283 mBatteryAudio.deviceOn[SPEAKER] = 1;
John Grossman44a7e422012-06-21 17:29:24 -0700284
Chong Zhang0b30fd42014-07-23 14:46:05 -0700285 // reset battery stats
286 // if the mediaserver has crashed, battery stats could be left
287 // in bad state, reset the state upon service start.
Wei Jia3f273d12015-11-24 09:06:49 -0800288 BatteryNotifier::getInstance().noteResetVideo();
Chong Zhang0b30fd42014-07-23 14:46:05 -0700289
John Grossman44a7e422012-06-21 17:29:24 -0700290 MediaPlayerFactory::registerBuiltinFactories();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800291}
292
293MediaPlayerService::~MediaPlayerService()
294{
Steve Block3856b092011-10-20 11:56:00 +0100295 ALOGV("MediaPlayerService destroyed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800296}
297
Svet Ganovbe71aa22015-04-28 12:06:02 -0700298sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(const String16 &opPackageName)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800299{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800300 pid_t pid = IPCThreadState::self()->getCallingPid();
Svet Ganovbe71aa22015-04-28 12:06:02 -0700301 sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid, opPackageName);
Gloria Wangdac6a312009-10-29 15:46:37 -0700302 wp<MediaRecorderClient> w = recorder;
303 Mutex::Autolock lock(mLock);
304 mMediaRecorderClients.add(w);
Steve Block3856b092011-10-20 11:56:00 +0100305 ALOGV("Create new media recorder client from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800306 return recorder;
307}
308
Gloria Wangdac6a312009-10-29 15:46:37 -0700309void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
310{
311 Mutex::Autolock lock(mLock);
312 mMediaRecorderClients.remove(client);
Steve Block3856b092011-10-20 11:56:00 +0100313 ALOGV("Delete media recorder client");
Gloria Wangdac6a312009-10-29 15:46:37 -0700314}
315
Glenn Kastenf37971f2012-02-03 11:06:53 -0800316sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800317{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800318 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800319 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
Steve Block3856b092011-10-20 11:56:00 +0100320 ALOGV("Create new media retriever from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800321 return retriever;
322}
323
Glenn Kastenf37971f2012-02-03 11:06:53 -0800324sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
Glenn Kastend848eb42016-03-08 13:42:11 -0800325 audio_session_t audioSessionId)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800326{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800327 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800328 int32_t connId = android_atomic_inc(&mNextConnId);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700329
330 sp<Client> c = new Client(
331 this, pid, connId, client, audioSessionId,
332 IPCThreadState::self()->getCallingUid());
333
Steve Block3856b092011-10-20 11:56:00 +0100334 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
Dave Burked681bbb2011-08-30 14:39:17 +0100335 IPCThreadState::self()->getCallingUid());
336
337 wp<Client> w = c;
338 {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800339 Mutex::Autolock lock(mLock);
340 mClients.add(w);
341 }
Andreas Hubere2b10282010-11-23 11:41:34 -0800342 return c;
343}
344
Lajos Molnar1381d4b2014-08-07 15:18:35 -0700345sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
346 return MediaCodecList::getLocalInstance();
347}
348
Marco Nelissen260e56c2016-01-28 21:41:25 +0000349sp<IOMX> MediaPlayerService::getOMX() {
Marco Nelissen1900e772016-02-02 16:12:16 -0800350 ALOGI("MediaPlayerService::getOMX");
Marco Nelissen260e56c2016-01-28 21:41:25 +0000351 Mutex::Autolock autoLock(mLock);
352
353 if (mOMX.get() == NULL) {
354 mOMX = new OMX;
355 }
356
357 return mOMX;
358}
359
Andreas Huber279dcd82013-01-30 10:41:25 -0800360sp<IHDCP> MediaPlayerService::makeHDCP(bool createEncryptionModule) {
361 return new HDCP(createEncryptionModule);
Andreas Huber59451f82012-09-18 10:36:32 -0700362}
363
Jeff Brown2013a542012-09-04 21:38:42 -0700364sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
Svet Ganovbe71aa22015-04-28 12:06:02 -0700365 const String16 &opPackageName,
Jeff Brown2013a542012-09-04 21:38:42 -0700366 const sp<IRemoteDisplayClient>& client, const String8& iface) {
Jeff Brownaba33d52012-09-07 17:38:58 -0700367 if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
368 return NULL;
369 }
370
Svet Ganovbe71aa22015-04-28 12:06:02 -0700371 return new RemoteDisplay(opPackageName, client, iface.string());
Jeff Brown2013a542012-09-04 21:38:42 -0700372}
373
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800374status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
375{
376 const size_t SIZE = 256;
377 char buffer[SIZE];
378 String8 result;
379
380 result.append(" AudioOutput\n");
381 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
382 mStreamType, mLeftVolume, mRightVolume);
383 result.append(buffer);
384 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Eric Laurentdb354e52012-03-05 17:27:11 -0800385 mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800386 result.append(buffer);
Eric Laurent2beeb502010-07-16 07:43:46 -0700387 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
388 mAuxEffectId, mSendLevel);
389 result.append(buffer);
390
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800391 ::write(fd, result.string(), result.size());
392 if (mTrack != 0) {
393 mTrack->dump(fd, args);
394 }
395 return NO_ERROR;
396}
397
Lajos Molnar6d339f12015-04-17 16:15:53 -0700398status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800399{
400 const size_t SIZE = 256;
401 char buffer[SIZE];
402 String8 result;
403 result.append(" Client\n");
404 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
405 mPid, mConnId, mStatus, mLoop?"true": "false");
406 result.append(buffer);
407 write(fd, result.string(), result.size());
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700408 if (mPlayer != NULL) {
409 mPlayer->dump(fd, args);
410 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800411 if (mAudioOutput != 0) {
412 mAudioOutput->dump(fd, args);
413 }
414 write(fd, "\n", 1);
415 return NO_ERROR;
416}
417
Marco Nelissenf09611f2015-02-13 14:12:42 -0800418/**
419 * The only arguments this understands right now are -c, -von and -voff,
420 * which are parsed by ALooperRoster::dump()
421 */
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800422status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
423{
424 const size_t SIZE = 256;
425 char buffer[SIZE];
426 String8 result;
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530427 SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
428 SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
429
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800430 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
431 snprintf(buffer, SIZE, "Permission Denial: "
432 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
433 IPCThreadState::self()->getCallingPid(),
434 IPCThreadState::self()->getCallingUid());
435 result.append(buffer);
436 } else {
437 Mutex::Autolock lock(mLock);
438 for (int i = 0, n = mClients.size(); i < n; ++i) {
439 sp<Client> c = mClients[i].promote();
440 if (c != 0) c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530441 clients.add(c);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800442 }
James Dongb9141222010-07-08 11:16:11 -0700443 if (mMediaRecorderClients.size() == 0) {
444 result.append(" No media recorder client\n\n");
445 } else {
446 for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
447 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
James Donge579e282011-10-18 22:29:20 -0700448 if (c != 0) {
449 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
450 result.append(buffer);
451 write(fd, result.string(), result.size());
452 result = "\n";
453 c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530454 mediaRecorderClients.add(c);
James Donge579e282011-10-18 22:29:20 -0700455 }
James Dongb9141222010-07-08 11:16:11 -0700456 }
Gloria Wangdac6a312009-10-29 15:46:37 -0700457 }
458
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800459 result.append(" Files opened and/or mapped:\n");
Marco Nelissenf09611f2015-02-13 14:12:42 -0800460 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800461 FILE *f = fopen(buffer, "r");
462 if (f) {
463 while (!feof(f)) {
464 fgets(buffer, SIZE, f);
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700465 if (strstr(buffer, " /storage/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800466 strstr(buffer, " /system/sounds/") ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700467 strstr(buffer, " /data/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800468 strstr(buffer, " /system/media/")) {
469 result.append(" ");
470 result.append(buffer);
471 }
472 }
473 fclose(f);
474 } else {
475 result.append("couldn't open ");
476 result.append(buffer);
477 result.append("\n");
478 }
479
Marco Nelissenf09611f2015-02-13 14:12:42 -0800480 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800481 DIR *d = opendir(buffer);
482 if (d) {
483 struct dirent *ent;
484 while((ent = readdir(d)) != NULL) {
485 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
Marco Nelissenf09611f2015-02-13 14:12:42 -0800486 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800487 struct stat s;
488 if (lstat(buffer, &s) == 0) {
489 if ((s.st_mode & S_IFMT) == S_IFLNK) {
490 char linkto[256];
491 int len = readlink(buffer, linkto, sizeof(linkto));
492 if(len > 0) {
493 if(len > 255) {
494 linkto[252] = '.';
495 linkto[253] = '.';
496 linkto[254] = '.';
497 linkto[255] = 0;
498 } else {
499 linkto[len] = 0;
500 }
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700501 if (strstr(linkto, "/storage/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800502 strstr(linkto, "/system/sounds/") == linkto ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700503 strstr(linkto, "/data/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800504 strstr(linkto, "/system/media/") == linkto) {
505 result.append(" ");
506 result.append(buffer);
507 result.append(" -> ");
508 result.append(linkto);
509 result.append("\n");
510 }
511 }
512 } else {
513 result.append(" unexpected type for ");
514 result.append(buffer);
515 result.append("\n");
516 }
517 }
518 }
519 }
520 closedir(d);
521 } else {
522 result.append("couldn't open ");
523 result.append(buffer);
524 result.append("\n");
525 }
526
Marco Nelissenf09611f2015-02-13 14:12:42 -0800527 gLooperRoster.dump(fd, args);
528
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800529 bool dumpMem = false;
Andy Hung53541292016-04-13 16:48:51 -0700530 bool unreachableMemory = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800531 for (size_t i = 0; i < args.size(); i++) {
532 if (args[i] == String16("-m")) {
533 dumpMem = true;
Andy Hung53541292016-04-13 16:48:51 -0700534 } else if (args[i] == String16("--unreachable")) {
535 unreachableMemory = true;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800536 }
537 }
538 if (dumpMem) {
James Dong8635b7b2011-03-14 17:01:38 -0700539 dumpMemoryAddresses(fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800540 }
Andy Hung53541292016-04-13 16:48:51 -0700541 if (unreachableMemory) {
542 result.append("\nDumping unreachable memory:\n");
543 // TODO - should limit be an argument parameter?
544 std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
545 result.append(s.c_str(), s.size());
546 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800547 }
548 write(fd, result.string(), result.size());
549 return NO_ERROR;
550}
551
552void MediaPlayerService::removeClient(wp<Client> client)
553{
554 Mutex::Autolock lock(mLock);
555 mClients.remove(client);
556}
557
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700558MediaPlayerService::Client::Client(
559 const sp<MediaPlayerService>& service, pid_t pid,
560 int32_t connId, const sp<IMediaPlayerClient>& client,
Glenn Kastend848eb42016-03-08 13:42:11 -0800561 audio_session_t audioSessionId, uid_t uid)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800562{
Steve Block3856b092011-10-20 11:56:00 +0100563 ALOGV("Client(%d) constructor", connId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800564 mPid = pid;
565 mConnId = connId;
566 mService = service;
567 mClient = client;
568 mLoop = false;
569 mStatus = NO_INIT;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700570 mAudioSessionId = audioSessionId;
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700571 mUID = uid;
John Grossmanc795b642012-02-22 15:38:35 -0800572 mRetransmitEndpointValid = false;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700573 mAudioAttributes = NULL;
Eric Laurenta514bdb2010-06-21 09:27:30 -0700574
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800575#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000576 ALOGD("create Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800577 mAntagonizer = new Antagonizer(notify, this);
578#endif
579}
580
581MediaPlayerService::Client::~Client()
582{
Steve Block3856b092011-10-20 11:56:00 +0100583 ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800584 mAudioOutput.clear();
585 wp<Client> client(this);
586 disconnect();
587 mService->removeClient(client);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700588 if (mAudioAttributes != NULL) {
589 free(mAudioAttributes);
590 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800591}
592
593void MediaPlayerService::Client::disconnect()
594{
Steve Block3856b092011-10-20 11:56:00 +0100595 ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800596 // grab local reference and clear main reference to prevent future
597 // access to object
598 sp<MediaPlayerBase> p;
599 {
600 Mutex::Autolock l(mLock);
601 p = mPlayer;
beanzdcfefde2012-11-05 09:51:43 +0800602 mClient.clear();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800603 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700604
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800605 mPlayer.clear();
606
607 // clear the notification to prevent callbacks to dead client
608 // and reset the player. We assume the player will serialize
609 // access to itself if necessary.
610 if (p != 0) {
611 p->setNotifyCallback(0, 0);
612#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000613 ALOGD("kill Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800614 mAntagonizer->kill();
615#endif
616 p->reset();
617 }
618
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700619 disconnectNativeWindow();
620
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800621 IPCThreadState::self()->flushCommands();
622}
623
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800624sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
625{
626 // determine if we have the right player type
627 sp<MediaPlayerBase> p = mPlayer;
628 if ((p != NULL) && (p->playerType() != playerType)) {
Steve Block3856b092011-10-20 11:56:00 +0100629 ALOGV("delete player");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800630 p.clear();
631 }
632 if (p == NULL) {
Ronghua Wu68845c12015-07-21 09:50:48 -0700633 p = MediaPlayerFactory::createPlayer(playerType, this, notify, mPid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800634 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700635
Jason Simmonsdb29e522011-08-12 13:46:55 -0700636 if (p != NULL) {
637 p->setUID(mUID);
638 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700639
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800640 return p;
641}
642
Marco Nelissen6dc3a3e2016-04-29 15:42:06 -0700643MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
644 const sp<IBinder>& service,
645 const sp<MediaPlayerBase>& listener,
646 int which) {
647 mService = service;
648 mListener = listener;
649 mWhich = which;
650}
651
652MediaPlayerService::Client::ServiceDeathNotifier::~ServiceDeathNotifier() {
653 mService->unlinkToDeath(this);
654}
655
656void MediaPlayerService::Client::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
657 sp<MediaPlayerBase> listener = mListener.promote();
658 if (listener != NULL) {
659 listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
660 } else {
661 ALOGW("listener for process %d death is gone", mWhich);
662 }
663}
664
John Grossmanc795b642012-02-22 15:38:35 -0800665sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
666 player_type playerType)
667{
668 ALOGV("player type = %d", playerType);
669
670 // create the right type of player
671 sp<MediaPlayerBase> p = createPlayer(playerType);
672 if (p == NULL) {
673 return p;
674 }
675
Marco Nelissen6dc3a3e2016-04-29 15:42:06 -0700676 sp<IServiceManager> sm = defaultServiceManager();
677 sp<IBinder> binder = sm->getService(String16("media.extractor"));
678 mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
679 binder->linkToDeath(mExtractorDeathListener);
680
681 binder = sm->getService(String16("media.codec"));
682 mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
683 binder->linkToDeath(mCodecDeathListener);
684
John Grossmanc795b642012-02-22 15:38:35 -0800685 if (!p->hardwareOutput()) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -0700686 Mutex::Autolock l(mLock);
Marco Nelissend457c972014-02-11 08:47:07 -0800687 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700688 mPid, mAudioAttributes);
John Grossmanc795b642012-02-22 15:38:35 -0800689 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
690 }
691
692 return p;
693}
694
695void MediaPlayerService::Client::setDataSource_post(
696 const sp<MediaPlayerBase>& p,
697 status_t status)
698{
699 ALOGV(" setDataSource");
700 mStatus = status;
701 if (mStatus != OK) {
702 ALOGE(" error: %d", mStatus);
703 return;
704 }
705
706 // Set the re-transmission endpoint if one was chosen.
707 if (mRetransmitEndpointValid) {
708 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
709 if (mStatus != NO_ERROR) {
710 ALOGE("setRetransmitEndpoint error: %d", mStatus);
711 }
712 }
713
714 if (mStatus == OK) {
715 mPlayer = p;
716 }
717}
718
Andreas Huber2db84552010-01-28 11:19:57 -0800719status_t MediaPlayerService::Client::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800720 const sp<IMediaHTTPService> &httpService,
721 const char *url,
722 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800723{
Steve Block3856b092011-10-20 11:56:00 +0100724 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800725 if (url == NULL)
726 return UNKNOWN_ERROR;
727
Dave Burked681bbb2011-08-30 14:39:17 +0100728 if ((strncmp(url, "http://", 7) == 0) ||
729 (strncmp(url, "https://", 8) == 0) ||
730 (strncmp(url, "rtsp://", 7) == 0)) {
731 if (!checkPermission("android.permission.INTERNET")) {
732 return PERMISSION_DENIED;
733 }
734 }
735
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800736 if (strncmp(url, "content://", 10) == 0) {
737 // get a filedescriptor for the content Uri and
738 // pass it to the setDataSource(fd) method
739
740 String16 url16(url);
741 int fd = android::openContentProviderFile(url16);
742 if (fd < 0)
743 {
Steve Block29357bc2012-01-06 19:20:56 +0000744 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800745 return UNKNOWN_ERROR;
746 }
747 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
748 close(fd);
749 return mStatus;
750 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700751 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800752 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
753 if (p == NULL) {
754 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800755 }
756
Andreas Huber1b86fe02014-01-29 11:13:26 -0800757 setDataSource_post(p, p->setDataSource(httpService, url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800758 return mStatus;
759 }
760}
761
762status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
763{
Marco Nelissen83b0fd92015-09-16 13:48:07 -0700764 ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
765 fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800766 struct stat sb;
767 int ret = fstat(fd, &sb);
768 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000769 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800770 return UNKNOWN_ERROR;
771 }
772
Andy Hung833b4752016-04-04 17:15:48 -0700773 ALOGV("st_dev = %llu", static_cast<unsigned long long>(sb.st_dev));
Steve Block3856b092011-10-20 11:56:00 +0100774 ALOGV("st_mode = %u", sb.st_mode);
Mark Salyzyn77342f72014-06-18 16:31:32 -0700775 ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
776 ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
Andy Hung833b4752016-04-04 17:15:48 -0700777 ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800778
779 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000780 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800781 return UNKNOWN_ERROR;
782 }
783 if (offset + length > sb.st_size) {
784 length = sb.st_size - offset;
Andy Hung833b4752016-04-04 17:15:48 -0700785 ALOGV("calculated length = %lld", (long long)length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800786 }
787
John Grossman44a7e422012-06-21 17:29:24 -0700788 player_type playerType = MediaPlayerFactory::getPlayerType(this,
789 fd,
790 offset,
791 length);
John Grossmanc795b642012-02-22 15:38:35 -0800792 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
793 if (p == NULL) {
794 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800795 }
796
797 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800798 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800799 return mStatus;
800}
801
Andreas Hubere2b10282010-11-23 11:41:34 -0800802status_t MediaPlayerService::Client::setDataSource(
803 const sp<IStreamSource> &source) {
804 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700805 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800806 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800807 if (p == NULL) {
808 return NO_INIT;
809 }
810
Andreas Hubere2b10282010-11-23 11:41:34 -0800811 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800812 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800813 return mStatus;
814}
815
Chris Watkins99f31602015-03-20 13:06:33 -0700816status_t MediaPlayerService::Client::setDataSource(
817 const sp<IDataSource> &source) {
818 sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source);
819 player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource);
820 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
821 if (p == NULL) {
822 return NO_INIT;
823 }
824 // now set data source
825 setDataSource_post(p, p->setDataSource(dataSource));
826 return mStatus;
827}
828
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700829void MediaPlayerService::Client::disconnectNativeWindow() {
830 if (mConnectedWindow != NULL) {
831 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
832 NATIVE_WINDOW_API_MEDIA);
833
834 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000835 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700836 strerror(-err), err);
837 }
838 }
839 mConnectedWindow.clear();
840}
841
Glenn Kasten11731182011-02-08 17:26:17 -0800842status_t MediaPlayerService::Client::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800843 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800844{
Andy McFadden484566c2012-12-18 09:46:54 -0800845 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800846 sp<MediaPlayerBase> p = getPlayer();
847 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700848
Marco Nelissenf8880202014-11-14 07:58:25 -0800849 sp<IBinder> binder(IInterface::asBinder(bufferProducer));
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700850 if (mConnectedWindowBinder == binder) {
851 return OK;
852 }
853
854 sp<ANativeWindow> anw;
Andy McFadden484566c2012-12-18 09:46:54 -0800855 if (bufferProducer != NULL) {
Marco Nelissenee08f7e2013-09-16 13:30:01 -0700856 anw = new Surface(bufferProducer, true /* controlledByApp */);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700857 status_t err = native_window_api_connect(anw.get(),
858 NATIVE_WINDOW_API_MEDIA);
859
860 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000861 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700862 // Note that we must do the reset before disconnecting from the ANW.
863 // Otherwise queue/dequeue calls could be made on the disconnected
864 // ANW, which may result in errors.
865 reset();
866
867 disconnectNativeWindow();
868
869 return err;
870 }
871 }
872
Andy McFadden484566c2012-12-18 09:46:54 -0800873 // Note that we must set the player's new GraphicBufferProducer before
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700874 // disconnecting the old one. Otherwise queue/dequeue calls could be made
875 // on the disconnected ANW, which may result in errors.
Andy McFadden484566c2012-12-18 09:46:54 -0800876 status_t err = p->setVideoSurfaceTexture(bufferProducer);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700877
878 disconnectNativeWindow();
879
880 mConnectedWindow = anw;
881
882 if (err == OK) {
883 mConnectedWindowBinder = binder;
884 } else {
885 disconnectNativeWindow();
886 }
887
888 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800889}
890
Nicolas Catania1d187f12009-05-12 23:25:55 -0700891status_t MediaPlayerService::Client::invoke(const Parcel& request,
892 Parcel *reply)
893{
894 sp<MediaPlayerBase> p = getPlayer();
895 if (p == NULL) return UNKNOWN_ERROR;
896 return p->invoke(request, reply);
897}
898
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700899// This call doesn't need to access the native player.
900status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
901{
902 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700903 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700904
Nicolas Catania48290382009-07-10 13:53:06 -0700905 if (unmarshallFilter(filter, &allow, &status) &&
906 unmarshallFilter(filter, &drop, &status)) {
907 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700908
909 mMetadataAllow = allow;
910 mMetadataDrop = drop;
911 }
912 return status;
913}
914
Nicolas Catania48290382009-07-10 13:53:06 -0700915status_t MediaPlayerService::Client::getMetadata(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700916 bool update_only, bool /*apply_filter*/, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700917{
nikoa64c8c72009-07-20 15:07:26 -0700918 sp<MediaPlayerBase> player = getPlayer();
919 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700920
nikod608a812009-07-16 16:39:53 -0700921 status_t status;
922 // Placeholder for the return code, updated by the caller.
923 reply->writeInt32(-1);
924
nikoa64c8c72009-07-20 15:07:26 -0700925 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700926
927 // We don't block notifications while we fetch the data. We clear
928 // mMetadataUpdated first so we don't lose notifications happening
929 // during the rest of this call.
930 {
931 Mutex::Autolock lock(mLock);
932 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700933 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700934 }
935 mMetadataUpdated.clear();
936 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700937
nikoa64c8c72009-07-20 15:07:26 -0700938 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700939
nikoa64c8c72009-07-20 15:07:26 -0700940 metadata.appendHeader();
941 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700942
943 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700944 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000945 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700946 return status;
947 }
948
949 // FIXME: Implement filtering on the result. Not critical since
950 // filtering takes place on the update notifications already. This
951 // would be when all the metadata are fetch and a filter is set.
952
nikod608a812009-07-16 16:39:53 -0700953 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700954 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700955 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700956}
957
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800958status_t MediaPlayerService::Client::prepareAsync()
959{
Steve Block3856b092011-10-20 11:56:00 +0100960 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800961 sp<MediaPlayerBase> p = getPlayer();
962 if (p == 0) return UNKNOWN_ERROR;
963 status_t ret = p->prepareAsync();
964#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000965 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800966 if (ret == NO_ERROR) mAntagonizer->start();
967#endif
968 return ret;
969}
970
971status_t MediaPlayerService::Client::start()
972{
Steve Block3856b092011-10-20 11:56:00 +0100973 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800974 sp<MediaPlayerBase> p = getPlayer();
975 if (p == 0) return UNKNOWN_ERROR;
976 p->setLooping(mLoop);
977 return p->start();
978}
979
980status_t MediaPlayerService::Client::stop()
981{
Steve Block3856b092011-10-20 11:56:00 +0100982 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800983 sp<MediaPlayerBase> p = getPlayer();
984 if (p == 0) return UNKNOWN_ERROR;
985 return p->stop();
986}
987
988status_t MediaPlayerService::Client::pause()
989{
Steve Block3856b092011-10-20 11:56:00 +0100990 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800991 sp<MediaPlayerBase> p = getPlayer();
992 if (p == 0) return UNKNOWN_ERROR;
993 return p->pause();
994}
995
996status_t MediaPlayerService::Client::isPlaying(bool* state)
997{
998 *state = false;
999 sp<MediaPlayerBase> p = getPlayer();
1000 if (p == 0) return UNKNOWN_ERROR;
1001 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +01001002 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001003 return NO_ERROR;
1004}
1005
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001006status_t MediaPlayerService::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -08001007{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001008 ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
1009 mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Wei Jia98160162015-02-04 17:01:11 -08001010 sp<MediaPlayerBase> p = getPlayer();
1011 if (p == 0) return UNKNOWN_ERROR;
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001012 return p->setPlaybackSettings(rate);
1013}
1014
1015status_t MediaPlayerService::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
1016{
1017 sp<MediaPlayerBase> p = getPlayer();
1018 if (p == 0) return UNKNOWN_ERROR;
1019 status_t ret = p->getPlaybackSettings(rate);
1020 if (ret == NO_ERROR) {
1021 ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
1022 mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
1023 } else {
1024 ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
1025 }
1026 return ret;
1027}
1028
1029status_t MediaPlayerService::Client::setSyncSettings(
1030 const AVSyncSettings& sync, float videoFpsHint)
1031{
1032 ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
1033 mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
1034 sp<MediaPlayerBase> p = getPlayer();
1035 if (p == 0) return UNKNOWN_ERROR;
1036 return p->setSyncSettings(sync, videoFpsHint);
1037}
1038
1039status_t MediaPlayerService::Client::getSyncSettings(
1040 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
1041{
1042 sp<MediaPlayerBase> p = getPlayer();
1043 if (p == 0) return UNKNOWN_ERROR;
1044 status_t ret = p->getSyncSettings(sync, videoFps);
1045 if (ret == NO_ERROR) {
1046 ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
1047 mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
1048 } else {
1049 ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
1050 }
1051 return ret;
Wei Jia98160162015-02-04 17:01:11 -08001052}
1053
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001054status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
1055{
Steve Block3856b092011-10-20 11:56:00 +01001056 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001057 sp<MediaPlayerBase> p = getPlayer();
1058 if (p == 0) return UNKNOWN_ERROR;
1059 status_t ret = p->getCurrentPosition(msec);
1060 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001061 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001062 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001063 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001064 }
1065 return ret;
1066}
1067
1068status_t MediaPlayerService::Client::getDuration(int *msec)
1069{
Steve Block3856b092011-10-20 11:56:00 +01001070 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001071 sp<MediaPlayerBase> p = getPlayer();
1072 if (p == 0) return UNKNOWN_ERROR;
1073 status_t ret = p->getDuration(msec);
1074 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001075 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001076 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001077 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001078 }
1079 return ret;
1080}
1081
Marco Nelissen6b74d672012-02-28 16:07:44 -08001082status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
1083 ALOGV("setNextPlayer");
1084 Mutex::Autolock l(mLock);
1085 sp<Client> c = static_cast<Client*>(player.get());
1086 mNextClient = c;
John Grossman5f7e55e2012-08-24 14:47:25 -07001087
1088 if (c != NULL) {
1089 if (mAudioOutput != NULL) {
1090 mAudioOutput->setNextOutput(c->mAudioOutput);
1091 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
1092 ALOGE("no current audio output");
1093 }
1094
1095 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
1096 mPlayer->setNextPlayer(mNextClient->getPlayer());
1097 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001098 }
John Grossman5f7e55e2012-08-24 14:47:25 -07001099
Marco Nelissen6b74d672012-02-28 16:07:44 -08001100 return OK;
1101}
1102
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001103status_t MediaPlayerService::Client::seekTo(int msec)
1104{
Steve Block3856b092011-10-20 11:56:00 +01001105 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001106 sp<MediaPlayerBase> p = getPlayer();
1107 if (p == 0) return UNKNOWN_ERROR;
1108 return p->seekTo(msec);
1109}
1110
1111status_t MediaPlayerService::Client::reset()
1112{
Steve Block3856b092011-10-20 11:56:00 +01001113 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -08001114 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001115 sp<MediaPlayerBase> p = getPlayer();
1116 if (p == 0) return UNKNOWN_ERROR;
1117 return p->reset();
1118}
1119
Glenn Kastenfff6d712012-01-12 16:38:12 -08001120status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001121{
Steve Block3856b092011-10-20 11:56:00 +01001122 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001123 // TODO: for hardware output, call player instead
1124 Mutex::Autolock l(mLock);
1125 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1126 return NO_ERROR;
1127}
1128
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001129status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
1130{
1131 if (mAudioAttributes != NULL) { free(mAudioAttributes); }
1132 mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001133 if (mAudioAttributes == NULL) {
1134 return NO_MEMORY;
1135 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001136 unmarshallAudioAttributes(parcel, mAudioAttributes);
1137
1138 ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
1139 mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
1140 mAudioAttributes->tags);
1141
1142 if (mAudioOutput != 0) {
1143 mAudioOutput->setAudioAttributes(mAudioAttributes);
1144 }
1145 return NO_ERROR;
1146}
1147
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001148status_t MediaPlayerService::Client::setLooping(int loop)
1149{
Steve Block3856b092011-10-20 11:56:00 +01001150 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001151 mLoop = loop;
1152 sp<MediaPlayerBase> p = getPlayer();
1153 if (p != 0) return p->setLooping(loop);
1154 return NO_ERROR;
1155}
1156
1157status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1158{
Steve Block3856b092011-10-20 11:56:00 +01001159 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -08001160
1161 // for hardware output, call player instead
1162 sp<MediaPlayerBase> p = getPlayer();
1163 {
1164 Mutex::Autolock l(mLock);
1165 if (p != 0 && p->hardwareOutput()) {
1166 MediaPlayerHWInterface* hwp =
1167 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1168 return hwp->setVolume(leftVolume, rightVolume);
1169 } else {
1170 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1171 return NO_ERROR;
1172 }
1173 }
1174
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001175 return NO_ERROR;
1176}
1177
Eric Laurent2beeb502010-07-16 07:43:46 -07001178status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1179{
Steve Block3856b092011-10-20 11:56:00 +01001180 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001181 Mutex::Autolock l(mLock);
1182 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1183 return NO_ERROR;
1184}
1185
1186status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1187{
Steve Block3856b092011-10-20 11:56:00 +01001188 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001189 Mutex::Autolock l(mLock);
1190 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1191 return NO_ERROR;
1192}
Nicolas Catania48290382009-07-10 13:53:06 -07001193
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001194status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001195 ALOGV("[%d] setParameter(%d)", mConnId, key);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001196 switch (key) {
1197 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
1198 {
1199 Mutex::Autolock l(mLock);
1200 return setAudioAttributes_l(request);
1201 }
1202 default:
1203 sp<MediaPlayerBase> p = getPlayer();
1204 if (p == 0) { return UNKNOWN_ERROR; }
1205 return p->setParameter(key, request);
1206 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001207}
1208
1209status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001210 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001211 sp<MediaPlayerBase> p = getPlayer();
1212 if (p == 0) return UNKNOWN_ERROR;
1213 return p->getParameter(key, reply);
1214}
1215
John Grossmanc795b642012-02-22 15:38:35 -08001216status_t MediaPlayerService::Client::setRetransmitEndpoint(
1217 const struct sockaddr_in* endpoint) {
1218
1219 if (NULL != endpoint) {
1220 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1221 uint16_t p = ntohs(endpoint->sin_port);
1222 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1223 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1224 } else {
1225 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1226 }
1227
1228 sp<MediaPlayerBase> p = getPlayer();
1229
1230 // Right now, the only valid time to set a retransmit endpoint is before
1231 // player selection has been made (since the presence or absence of a
1232 // retransmit endpoint is going to determine which player is selected during
1233 // setDataSource).
1234 if (p != 0) return INVALID_OPERATION;
1235
1236 if (NULL != endpoint) {
1237 mRetransmitEndpoint = *endpoint;
1238 mRetransmitEndpointValid = true;
1239 } else {
1240 mRetransmitEndpointValid = false;
1241 }
1242
1243 return NO_ERROR;
1244}
1245
John Grossman44a7e422012-06-21 17:29:24 -07001246status_t MediaPlayerService::Client::getRetransmitEndpoint(
1247 struct sockaddr_in* endpoint)
1248{
1249 if (NULL == endpoint)
1250 return BAD_VALUE;
1251
1252 sp<MediaPlayerBase> p = getPlayer();
1253
1254 if (p != NULL)
1255 return p->getRetransmitEndpoint(endpoint);
1256
1257 if (!mRetransmitEndpointValid)
1258 return NO_INIT;
1259
1260 *endpoint = mRetransmitEndpoint;
1261
1262 return NO_ERROR;
1263}
1264
Gloria Wangb483c472011-04-11 17:23:27 -07001265void MediaPlayerService::Client::notify(
1266 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001267{
1268 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001269 if (client == NULL) {
1270 return;
1271 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001272
James Dongb8a98252012-08-26 16:13:03 -07001273 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001274 {
1275 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001276 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001277 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001278 if (client->mAudioOutput != NULL)
1279 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001280 client->mNextClient->start();
Wei Jia2afac0c2016-01-07 12:13:07 -08001281 if (client->mNextClient->mClient != NULL) {
1282 client->mNextClient->mClient->notify(
1283 MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1284 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001285 }
1286 }
1287
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001288 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001289 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001290 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001291
1292 if(client->shouldDropMetadata(metadata_type)) {
1293 return;
1294 }
1295
1296 // Update the list of metadata that have changed. getMetadata
1297 // also access mMetadataUpdated and clears it.
1298 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001299 }
James Dongb8a98252012-08-26 16:13:03 -07001300
1301 if (c != NULL) {
1302 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1303 c->notify(msg, ext1, ext2, obj);
1304 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001305}
1306
Nicolas Catania48290382009-07-10 13:53:06 -07001307
nikoa64c8c72009-07-20 15:07:26 -07001308bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001309{
Nicolas Catania48290382009-07-10 13:53:06 -07001310 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001311
Nicolas Catania48290382009-07-10 13:53:06 -07001312 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001313 return true;
1314 }
1315
Nicolas Catania48290382009-07-10 13:53:06 -07001316 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001317 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001318 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001319 return true;
1320 }
1321}
1322
Nicolas Catania48290382009-07-10 13:53:06 -07001323
nikoa64c8c72009-07-20 15:07:26 -07001324void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001325 Mutex::Autolock lock(mLock);
1326 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1327 mMetadataUpdated.add(metadata_type);
1328 }
1329}
1330
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001331#if CALLBACK_ANTAGONIZER
1332const int Antagonizer::interval = 10000; // 10 msecs
1333
1334Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1335 mExit(false), mActive(false), mClient(client), mCb(cb)
1336{
1337 createThread(callbackThread, this);
1338}
1339
1340void Antagonizer::kill()
1341{
1342 Mutex::Autolock _l(mLock);
1343 mActive = false;
1344 mExit = true;
1345 mCondition.wait(mLock);
1346}
1347
1348int Antagonizer::callbackThread(void* user)
1349{
Steve Blockb8a80522011-12-20 16:23:08 +00001350 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001351 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1352 while (!p->mExit) {
1353 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001354 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001355 p->mCb(p->mClient, 0, 0, 0);
1356 }
1357 usleep(interval);
1358 }
1359 Mutex::Autolock _l(p->mLock);
1360 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001361 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001362 return 0;
1363}
1364#endif
1365
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001366#undef LOG_TAG
1367#define LOG_TAG "AudioSink"
Glenn Kastend848eb42016-03-08 13:42:11 -08001368MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, int uid, int pid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001369 const audio_attributes_t* attr)
Andreas Huber20111aa2009-07-14 16:56:47 -07001370 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001371 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001372 mCallbackData(NULL),
Andy Hungd1c74342015-07-07 16:54:23 -07001373 mStreamType(AUDIO_STREAM_MUSIC),
Andy Hungd1c74342015-07-07 16:54:23 -07001374 mLeftVolume(1.0),
1375 mRightVolume(1.0),
1376 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
1377 mSampleRateHz(0),
1378 mMsecsPerFrame(0),
1379 mFrameSize(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001380 mSessionId(sessionId),
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001381 mUid(uid),
Marco Nelissend457c972014-02-11 08:47:07 -08001382 mPid(pid),
Andy Hungd1c74342015-07-07 16:54:23 -07001383 mSendLevel(0.0),
1384 mAuxEffectId(0),
1385 mFlags(AUDIO_OUTPUT_FLAG_NONE)
1386{
Steve Block3856b092011-10-20 11:56:00 +01001387 ALOGV("AudioOutput(%d)", sessionId);
Eric Laurent43562692015-07-15 16:49:07 -07001388 if (attr != NULL) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001389 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1390 if (mAttributes != NULL) {
1391 memcpy(mAttributes, attr, sizeof(audio_attributes_t));
1392 mStreamType = audio_attributes_to_stream_type(attr);
1393 }
1394 } else {
1395 mAttributes = NULL;
Eric Laurent43562692015-07-15 16:49:07 -07001396 }
1397
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001398 setMinBufferCount();
1399}
1400
1401MediaPlayerService::AudioOutput::~AudioOutput()
1402{
1403 close();
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001404 free(mAttributes);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001405 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001406}
1407
Andy Hungd1c74342015-07-07 16:54:23 -07001408//static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001409void MediaPlayerService::AudioOutput::setMinBufferCount()
1410{
1411 char value[PROPERTY_VALUE_MAX];
1412 if (property_get("ro.kernel.qemu", value, 0)) {
1413 mIsOnEmulator = true;
1414 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1415 }
1416}
1417
Andy Hungd1c74342015-07-07 16:54:23 -07001418// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001419bool MediaPlayerService::AudioOutput::isOnEmulator()
1420{
Andy Hungd1c74342015-07-07 16:54:23 -07001421 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001422 return mIsOnEmulator;
1423}
1424
Andy Hungd1c74342015-07-07 16:54:23 -07001425// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001426int MediaPlayerService::AudioOutput::getMinBufferCount()
1427{
Andy Hungd1c74342015-07-07 16:54:23 -07001428 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001429 return mMinBufferCount;
1430}
1431
1432ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1433{
Andy Hungd1c74342015-07-07 16:54:23 -07001434 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001435 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001436 return mTrack->frameCount() * mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001437}
1438
1439ssize_t MediaPlayerService::AudioOutput::frameCount() const
1440{
Andy Hungd1c74342015-07-07 16:54:23 -07001441 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001442 if (mTrack == 0) return NO_INIT;
1443 return mTrack->frameCount();
1444}
1445
1446ssize_t MediaPlayerService::AudioOutput::channelCount() const
1447{
Andy Hungd1c74342015-07-07 16:54:23 -07001448 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001449 if (mTrack == 0) return NO_INIT;
1450 return mTrack->channelCount();
1451}
1452
1453ssize_t MediaPlayerService::AudioOutput::frameSize() const
1454{
Andy Hungd1c74342015-07-07 16:54:23 -07001455 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001456 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001457 return mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001458}
1459
1460uint32_t MediaPlayerService::AudioOutput::latency () const
1461{
Andy Hungd1c74342015-07-07 16:54:23 -07001462 Mutex::Autolock lock(mLock);
Eric Laurentdb354e52012-03-05 17:27:11 -08001463 if (mTrack == 0) return 0;
1464 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001465}
1466
1467float MediaPlayerService::AudioOutput::msecsPerFrame() const
1468{
Andy Hungd1c74342015-07-07 16:54:23 -07001469 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001470 return mMsecsPerFrame;
1471}
1472
Marco Nelissen4110c102012-03-29 09:31:28 -07001473status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001474{
Andy Hungd1c74342015-07-07 16:54:23 -07001475 Mutex::Autolock lock(mLock);
Eric Laurent342e9cf2010-01-19 17:37:09 -08001476 if (mTrack == 0) return NO_INIT;
1477 return mTrack->getPosition(position);
1478}
1479
Lajos Molnar06ad1522014-08-28 07:27:44 -07001480status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const
1481{
Andy Hungd1c74342015-07-07 16:54:23 -07001482 Mutex::Autolock lock(mLock);
Lajos Molnar06ad1522014-08-28 07:27:44 -07001483 if (mTrack == 0) return NO_INIT;
1484 return mTrack->getTimestamp(ts);
1485}
1486
Wei Jiac4ac8172015-10-21 10:35:48 -07001487// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
1488// as it acquires locks and may query the audio driver.
1489//
1490// Some calls could conceivably retrieve extrapolated data instead of
1491// accessing getTimestamp() or getPosition() every time a data buffer with
1492// a media time is received.
1493//
1494// Calculate duration of played samples if played at normal rate (i.e., 1.0).
1495int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const
1496{
1497 Mutex::Autolock lock(mLock);
1498 if (mTrack == 0 || mSampleRateHz == 0) {
Wei Jia213f4902015-10-22 08:55:25 -07001499 return 0;
Wei Jiac4ac8172015-10-21 10:35:48 -07001500 }
1501
1502 uint32_t numFramesPlayed;
1503 int64_t numFramesPlayedAt;
1504 AudioTimestamp ts;
1505 static const int64_t kStaleTimestamp100ms = 100000;
1506
1507 status_t res = mTrack->getTimestamp(ts);
1508 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
1509 numFramesPlayed = ts.mPosition;
1510 numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
1511 const int64_t timestampAge = nowUs - numFramesPlayedAt;
1512 if (timestampAge > kStaleTimestamp100ms) {
1513 // This is an audio FIXME.
1514 // getTimestamp returns a timestamp which may come from audio mixing threads.
1515 // After pausing, the MixerThread may go idle, thus the mTime estimate may
1516 // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms,
1517 // the max latency should be about 25ms with an average around 12ms (to be verified).
1518 // For safety we use 100ms.
1519 ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)",
1520 (long long)nowUs, (long long)numFramesPlayedAt);
1521 numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
1522 }
1523 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1524 } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
1525 numFramesPlayed = 0;
1526 numFramesPlayedAt = nowUs;
1527 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
1528 // numFramesPlayed, (long long)numFramesPlayedAt);
1529 } else { // case 3: transitory at new track or audio fast tracks.
1530 res = mTrack->getPosition(&numFramesPlayed);
1531 CHECK_EQ(res, (status_t)OK);
1532 numFramesPlayedAt = nowUs;
1533 numFramesPlayedAt += 1000LL * mTrack->latency() / 2; /* XXX */
1534 //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1535 }
1536
1537 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
1538 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1539 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
1540 + nowUs - numFramesPlayedAt;
1541 if (durationUs < 0) {
1542 // Occurs when numFramesPlayed position is very small and the following:
1543 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
1544 // numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed.
1545 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
1546 // numFramesPlayedAt, by a time amount greater than numFramesPlayed.
1547 //
1548 // Both of these are transitory conditions.
1549 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
1550 durationUs = 0;
1551 }
1552 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
1553 (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt);
1554 return durationUs;
1555}
1556
Marco Nelissen4110c102012-03-29 09:31:28 -07001557status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1558{
Andy Hungd1c74342015-07-07 16:54:23 -07001559 Mutex::Autolock lock(mLock);
Marco Nelissen4110c102012-03-29 09:31:28 -07001560 if (mTrack == 0) return NO_INIT;
Andy Hung2f6e73d2016-04-08 12:12:58 -07001561 ExtendedTimestamp ets;
1562 status_t status = mTrack->getTimestamp(&ets);
1563 if (status == OK || status == WOULD_BLOCK) {
1564 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
1565 }
1566 return status;
Marco Nelissen4110c102012-03-29 09:31:28 -07001567}
1568
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001569status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
1570{
Andy Hungd1c74342015-07-07 16:54:23 -07001571 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001572 if (mTrack == 0) return NO_INIT;
1573 return mTrack->setParameters(keyValuePairs);
1574}
1575
1576String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
1577{
Andy Hungd1c74342015-07-07 16:54:23 -07001578 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001579 if (mTrack == 0) return String8::empty();
1580 return mTrack->getParameters(keys);
1581}
1582
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001583void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
Andy Hungd1c74342015-07-07 16:54:23 -07001584 Mutex::Autolock lock(mLock);
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001585 if (attributes == NULL) {
1586 free(mAttributes);
1587 mAttributes = NULL;
1588 } else {
1589 if (mAttributes == NULL) {
1590 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1591 }
1592 memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
Eric Laurent43562692015-07-15 16:49:07 -07001593 mStreamType = audio_attributes_to_stream_type(attributes);
1594 }
1595}
1596
1597void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
1598{
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001599 Mutex::Autolock lock(mLock);
Eric Laurent43562692015-07-15 16:49:07 -07001600 // do not allow direct stream type modification if attributes have been set
1601 if (mAttributes == NULL) {
1602 mStreamType = streamType;
1603 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001604}
1605
Andy Hungd1c74342015-07-07 16:54:23 -07001606void MediaPlayerService::AudioOutput::deleteRecycledTrack_l()
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001607{
Andy Hungd1c74342015-07-07 16:54:23 -07001608 ALOGV("deleteRecycledTrack_l");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001609 if (mRecycledTrack != 0) {
1610
1611 if (mCallbackData != NULL) {
1612 mCallbackData->setOutput(NULL);
1613 mCallbackData->endTrackSwitch();
1614 }
1615
1616 if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
Andy Hunge13f8a62016-03-30 14:20:42 -07001617 int32_t msec = 0;
1618 if (!mRecycledTrack->stopped()) { // check if active
1619 (void)mRecycledTrack->pendingDuration(&msec);
1620 }
1621 mRecycledTrack->stop(); // ensure full data drain
1622 ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
1623 if (msec > 0) {
1624 static const int32_t WAIT_LIMIT_MS = 3000;
1625 if (msec > WAIT_LIMIT_MS) {
1626 msec = WAIT_LIMIT_MS;
1627 }
1628 usleep(msec * 1000LL);
1629 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001630 }
1631 // An offloaded track isn't flushed because the STREAM_END is reported
1632 // slightly prematurely to allow time for the gapless track switch
1633 // but this means that if we decide not to recycle the track there
1634 // could be a small amount of residual data still playing. We leave
1635 // AudioFlinger to drain the track.
1636
1637 mRecycledTrack.clear();
Andy Hungd1c74342015-07-07 16:54:23 -07001638 close_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001639 delete mCallbackData;
1640 mCallbackData = NULL;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001641 }
1642}
1643
Andy Hungd1c74342015-07-07 16:54:23 -07001644void MediaPlayerService::AudioOutput::close_l()
1645{
1646 mTrack.clear();
1647}
1648
Andreas Huber20111aa2009-07-14 16:56:47 -07001649status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001650 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1651 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001652 AudioCallback cb, void *cookie,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001653 audio_output_flags_t flags,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001654 const audio_offload_info_t *offloadInfo,
Andy Hung179652e2015-05-31 22:49:46 -07001655 bool doNotReconnect,
1656 uint32_t suggestedFrameCount)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001657{
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001658 ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
1659 format, bufferCount, mSessionId, flags);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001660
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001661 // offloading is only supported in callback mode for now.
1662 // offloadInfo must be present if offload flag is set
1663 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
1664 ((cb == NULL) || (offloadInfo == NULL))) {
1665 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001666 }
1667
Andy Hung179652e2015-05-31 22:49:46 -07001668 // compute frame count for the AudioTrack internal buffer
1669 size_t frameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001670 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1671 frameCount = 0; // AudioTrack will get frame count from AudioFlinger
1672 } else {
Andy Hung179652e2015-05-31 22:49:46 -07001673 // try to estimate the buffer processing fetch size from AudioFlinger.
1674 // framesPerBuffer is approximate and generally correct, except when it's not :-).
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001675 uint32_t afSampleRate;
1676 size_t afFrameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001677 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1678 return NO_INIT;
1679 }
1680 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1681 return NO_INIT;
1682 }
Andy Hung179652e2015-05-31 22:49:46 -07001683 const size_t framesPerBuffer =
1684 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001685
Andy Hung179652e2015-05-31 22:49:46 -07001686 if (bufferCount == 0) {
1687 // use suggestedFrameCount
1688 bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
1689 }
1690 // Check argument bufferCount against the mininum buffer count
1691 if (bufferCount != 0 && bufferCount < mMinBufferCount) {
1692 ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
1693 bufferCount = mMinBufferCount;
1694 }
1695 // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
1696 // which will be the minimum size permitted.
1697 frameCount = bufferCount * framesPerBuffer;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001698 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001699
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001700 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001701 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001702 if (0 == channelMask) {
1703 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1704 return NO_INIT;
1705 }
1706 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001707
Andy Hungd1c74342015-07-07 16:54:23 -07001708 Mutex::Autolock lock(mLock);
Andy Hung179652e2015-05-31 22:49:46 -07001709 mCallback = cb;
1710 mCallbackCookie = cookie;
1711
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001712 // Check whether we can recycle the track
1713 bool reuse = false;
1714 bool bothOffloaded = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001715
Glenn Kasten2799d742013-05-30 14:33:29 -07001716 if (mRecycledTrack != 0) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001717 // check whether we are switching between two offloaded tracks
1718 bothOffloaded = (flags & mRecycledTrack->getFlags()
1719 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
Marco Nelissen67295b52012-06-11 14:52:53 -07001720
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001721 // check if the existing track can be reused as-is, or if a new track needs to be created.
1722 reuse = true;
1723
Marco Nelissen67295b52012-06-11 14:52:53 -07001724 if ((mCallbackData == NULL && mCallback != NULL) ||
1725 (mCallbackData != NULL && mCallback == NULL)) {
1726 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1727 ALOGV("can't chain callback and write");
1728 reuse = false;
1729 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001730 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
1731 ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
Marco Nelissen67295b52012-06-11 14:52:53 -07001732 mRecycledTrack->getSampleRate(), sampleRate,
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001733 mRecycledTrack->channelCount(), channelCount);
Marco Nelissen67295b52012-06-11 14:52:53 -07001734 reuse = false;
1735 } else if (flags != mFlags) {
1736 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1737 reuse = false;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001738 } else if (mRecycledTrack->format() != format) {
1739 reuse = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001740 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001741 } else {
1742 ALOGV("no track available to recycle");
1743 }
1744
1745 ALOGV_IF(bothOffloaded, "both tracks offloaded");
1746
1747 // If we can't recycle and both tracks are offloaded
1748 // we must close the previous output before opening a new one
1749 if (bothOffloaded && !reuse) {
1750 ALOGV("both offloaded and not recycling");
Andy Hungd1c74342015-07-07 16:54:23 -07001751 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001752 }
1753
1754 sp<AudioTrack> t;
1755 CallbackData *newcbd = NULL;
1756
1757 // We don't attempt to create a new track if we are recycling an
1758 // offloaded track. But, if we are recycling a non-offloaded or we
1759 // are switching where one is offloaded and one isn't then we create
1760 // the new track in advance so that we can read additional stream info
1761
1762 if (!(reuse && bothOffloaded)) {
1763 ALOGV("creating new AudioTrack");
1764
1765 if (mCallback != NULL) {
1766 newcbd = new CallbackData(this);
1767 t = new AudioTrack(
1768 mStreamType,
1769 sampleRate,
1770 format,
1771 channelMask,
1772 frameCount,
1773 flags,
1774 CallbackWrapper,
1775 newcbd,
1776 0, // notification frames
1777 mSessionId,
1778 AudioTrack::TRANSFER_CALLBACK,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001779 offloadInfo,
Marco Nelissend457c972014-02-11 08:47:07 -08001780 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001781 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001782 mAttributes,
1783 doNotReconnect);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001784 } else {
Andy Hungff874dc2016-04-11 16:49:09 -07001785 // TODO: Due to buffer memory concerns, we use a max target playback speed
1786 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
1787 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
1788 const float targetSpeed =
1789 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
1790 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
1791 "track target speed:%f clamped from playback speed:%f",
1792 targetSpeed, mPlaybackRate.mSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001793 t = new AudioTrack(
1794 mStreamType,
1795 sampleRate,
1796 format,
1797 channelMask,
1798 frameCount,
1799 flags,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001800 NULL, // callback
1801 NULL, // user data
1802 0, // notification frames
1803 mSessionId,
1804 AudioTrack::TRANSFER_DEFAULT,
1805 NULL, // offload info
Marco Nelissend457c972014-02-11 08:47:07 -08001806 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001807 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001808 mAttributes,
Andy Hungff874dc2016-04-11 16:49:09 -07001809 doNotReconnect,
1810 targetSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001811 }
1812
1813 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1814 ALOGE("Unable to create audio track");
1815 delete newcbd;
Glenn Kasten3e98ecd2015-05-18 13:13:24 -07001816 // t goes out of scope, so reference count drops to zero
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001817 return NO_INIT;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001818 } else {
1819 // successful AudioTrack initialization implies a legacy stream type was generated
1820 // from the audio attributes
1821 mStreamType = t->streamType();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001822 }
1823 }
1824
1825 if (reuse) {
1826 CHECK(mRecycledTrack != NULL);
1827
1828 if (!bothOffloaded) {
1829 if (mRecycledTrack->frameCount() != t->frameCount()) {
Andy Hung833b4752016-04-04 17:15:48 -07001830 ALOGV("framecount differs: %zu/%zu frames",
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001831 mRecycledTrack->frameCount(), t->frameCount());
1832 reuse = false;
1833 }
1834 }
1835
Marco Nelissen67295b52012-06-11 14:52:53 -07001836 if (reuse) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001837 ALOGV("chaining to next output and recycling track");
Andy Hungd1c74342015-07-07 16:54:23 -07001838 close_l();
Marco Nelissen67295b52012-06-11 14:52:53 -07001839 mTrack = mRecycledTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001840 mRecycledTrack.clear();
Marco Nelissen67295b52012-06-11 14:52:53 -07001841 if (mCallbackData != NULL) {
1842 mCallbackData->setOutput(this);
1843 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001844 delete newcbd;
1845 return OK;
1846 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001847 }
1848
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001849 // we're not going to reuse the track, unblock and flush it
1850 // this was done earlier if both tracks are offloaded
1851 if (!bothOffloaded) {
Andy Hungd1c74342015-07-07 16:54:23 -07001852 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001853 }
1854
1855 CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
1856
Marco Nelissen67295b52012-06-11 14:52:53 -07001857 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001858 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001859 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001860
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001861 mSampleRateHz = sampleRate;
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001862 mFlags = flags;
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001863 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Andy Hungd1c74342015-07-07 16:54:23 -07001864 mFrameSize = t->frameSize();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001865 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001866
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001867 status_t res = NO_ERROR;
Wei Jia0162d002015-06-09 11:59:33 -07001868 // Note some output devices may give us a direct track even though we don't specify it.
1869 // Example: Line application b/17459982.
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001870 if ((t->getFlags() & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001871 res = t->setPlaybackRate(mPlaybackRate);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001872 if (res == NO_ERROR) {
1873 t->setAuxEffectSendLevel(mSendLevel);
1874 res = t->attachAuxEffect(mAuxEffectId);
1875 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001876 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001877 ALOGV("open() DONE status %d", res);
1878 return res;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001879}
1880
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001881status_t MediaPlayerService::AudioOutput::start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001882{
Steve Block3856b092011-10-20 11:56:00 +01001883 ALOGV("start");
Andy Hungd1c74342015-07-07 16:54:23 -07001884 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001885 if (mCallbackData != NULL) {
1886 mCallbackData->endTrackSwitch();
1887 }
Glenn Kasten2799d742013-05-30 14:33:29 -07001888 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001889 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001890 mTrack->setAuxEffectSendLevel(mSendLevel);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001891 return mTrack->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001892 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001893 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001894}
1895
Marco Nelissen6b74d672012-02-28 16:07:44 -08001896void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
Andy Hungd1c74342015-07-07 16:54:23 -07001897 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001898 mNextOutput = nextOutput;
1899}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001900
Marco Nelissen6b74d672012-02-28 16:07:44 -08001901void MediaPlayerService::AudioOutput::switchToNextOutput() {
1902 ALOGV("switchToNextOutput");
Andy Hungd1c74342015-07-07 16:54:23 -07001903
1904 // Try to acquire the callback lock before moving track (without incurring deadlock).
1905 const unsigned kMaxSwitchTries = 100;
1906 Mutex::Autolock lock(mLock);
1907 for (unsigned tries = 0;;) {
1908 if (mTrack == 0) {
1909 return;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001910 }
Andy Hungd1c74342015-07-07 16:54:23 -07001911 if (mNextOutput != NULL && mNextOutput != this) {
1912 if (mCallbackData != NULL) {
1913 // two alternative approaches
1914#if 1
1915 CallbackData *callbackData = mCallbackData;
1916 mLock.unlock();
1917 // proper acquisition sequence
1918 callbackData->lock();
1919 mLock.lock();
1920 // Caution: it is unlikely that someone deleted our callback or changed our target
1921 if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
1922 // fatal if we are starved out.
1923 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1924 "switchToNextOutput() cannot obtain correct lock sequence");
1925 callbackData->unlock();
1926 continue;
1927 }
1928 callbackData->mSwitching = true; // begin track switch
1929#else
1930 // tryBeginTrackSwitch() returns false if the callback has the lock.
1931 if (!mCallbackData->tryBeginTrackSwitch()) {
1932 // fatal if we are starved out.
1933 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1934 "switchToNextOutput() cannot obtain callback lock");
1935 mLock.unlock();
1936 usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
1937 mLock.lock();
1938 continue;
1939 }
1940#endif
1941 }
1942
1943 Mutex::Autolock nextLock(mNextOutput->mLock);
1944
1945 // If the next output track is not NULL, then it has been
1946 // opened already for playback.
1947 // This is possible even without the next player being started,
1948 // for example, the next player could be prepared and seeked.
1949 //
1950 // Presuming it isn't advisable to force the track over.
1951 if (mNextOutput->mTrack == NULL) {
1952 ALOGD("Recycling track for gapless playback");
1953 delete mNextOutput->mCallbackData;
1954 mNextOutput->mCallbackData = mCallbackData;
1955 mNextOutput->mRecycledTrack = mTrack;
1956 mNextOutput->mSampleRateHz = mSampleRateHz;
1957 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
Andy Hungd1c74342015-07-07 16:54:23 -07001958 mNextOutput->mFlags = mFlags;
1959 mNextOutput->mFrameSize = mFrameSize;
1960 close_l();
1961 mCallbackData = NULL; // destruction handled by mNextOutput
1962 } else {
1963 ALOGW("Ignoring gapless playback because next player has already started");
1964 // remove track in case resource needed for future players.
1965 if (mCallbackData != NULL) {
1966 mCallbackData->endTrackSwitch(); // release lock for callbacks before close.
1967 }
1968 close_l();
1969 }
1970 }
1971 break;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001972 }
1973}
1974
Wei Jia7d3f4df2015-03-03 15:28:00 -08001975ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001976{
Andy Hungd1c74342015-07-07 16:54:23 -07001977 Mutex::Autolock lock(mLock);
Glenn Kastenadad3d72014-02-21 14:51:43 -08001978 LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
Andreas Huber20111aa2009-07-14 16:56:47 -07001979
Steve Block3856b092011-10-20 11:56:00 +01001980 //ALOGV("write(%p, %u)", buffer, size);
Glenn Kasten2799d742013-05-30 14:33:29 -07001981 if (mTrack != 0) {
Andy Hung2f6e73d2016-04-08 12:12:58 -07001982 return mTrack->write(buffer, size, blocking);
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001983 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001984 return NO_INIT;
1985}
1986
1987void MediaPlayerService::AudioOutput::stop()
1988{
Steve Block3856b092011-10-20 11:56:00 +01001989 ALOGV("stop");
Andy Hungd1c74342015-07-07 16:54:23 -07001990 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001991 if (mTrack != 0) mTrack->stop();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001992}
1993
1994void MediaPlayerService::AudioOutput::flush()
1995{
Steve Block3856b092011-10-20 11:56:00 +01001996 ALOGV("flush");
Andy Hungd1c74342015-07-07 16:54:23 -07001997 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001998 if (mTrack != 0) mTrack->flush();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001999}
2000
2001void MediaPlayerService::AudioOutput::pause()
2002{
Steve Block3856b092011-10-20 11:56:00 +01002003 ALOGV("pause");
Andy Hungd1c74342015-07-07 16:54:23 -07002004 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07002005 if (mTrack != 0) mTrack->pause();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002006}
2007
2008void MediaPlayerService::AudioOutput::close()
2009{
Steve Block3856b092011-10-20 11:56:00 +01002010 ALOGV("close");
Erik Wolsheimer7845a1f2015-10-30 12:07:52 -07002011 sp<AudioTrack> track;
2012 {
2013 Mutex::Autolock lock(mLock);
2014 track = mTrack;
2015 close_l(); // clears mTrack
2016 }
2017 // destruction of the track occurs outside of mutex.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002018}
2019
2020void MediaPlayerService::AudioOutput::setVolume(float left, float right)
2021{
Steve Block3856b092011-10-20 11:56:00 +01002022 ALOGV("setVolume(%f, %f)", left, right);
Andy Hungd1c74342015-07-07 16:54:23 -07002023 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002024 mLeftVolume = left;
2025 mRightVolume = right;
Glenn Kasten2799d742013-05-30 14:33:29 -07002026 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002027 mTrack->setVolume(left, right);
2028 }
2029}
2030
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002031status_t MediaPlayerService::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002032{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002033 ALOGV("setPlaybackRate(%f %f %d %d)",
2034 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Andy Hungd1c74342015-07-07 16:54:23 -07002035 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002036 if (mTrack == 0) {
2037 // remember rate so that we can set it when the track is opened
2038 mPlaybackRate = rate;
2039 return OK;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002040 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002041 status_t res = mTrack->setPlaybackRate(rate);
2042 if (res != NO_ERROR) {
2043 return res;
2044 }
2045 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
2046 CHECK_GT(rate.mSpeed, 0.f);
2047 mPlaybackRate = rate;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002048 if (mSampleRateHz != 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002049 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002050 }
2051 return res;
2052}
2053
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002054status_t MediaPlayerService::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
2055{
2056 ALOGV("setPlaybackRate");
Andy Hungd1c74342015-07-07 16:54:23 -07002057 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002058 if (mTrack == 0) {
2059 return NO_INIT;
2060 }
2061 *rate = mTrack->getPlaybackRate();
2062 return NO_ERROR;
2063}
2064
Eric Laurent2beeb502010-07-16 07:43:46 -07002065status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
2066{
Steve Block3856b092011-10-20 11:56:00 +01002067 ALOGV("setAuxEffectSendLevel(%f)", level);
Andy Hungd1c74342015-07-07 16:54:23 -07002068 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002069 mSendLevel = level;
Glenn Kasten2799d742013-05-30 14:33:29 -07002070 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002071 return mTrack->setAuxEffectSendLevel(level);
2072 }
2073 return NO_ERROR;
2074}
2075
2076status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
2077{
Steve Block3856b092011-10-20 11:56:00 +01002078 ALOGV("attachAuxEffect(%d)", effectId);
Andy Hungd1c74342015-07-07 16:54:23 -07002079 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002080 mAuxEffectId = effectId;
Glenn Kasten2799d742013-05-30 14:33:29 -07002081 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002082 return mTrack->attachAuxEffect(effectId);
2083 }
2084 return NO_ERROR;
2085}
2086
Andreas Huber20111aa2009-07-14 16:56:47 -07002087// static
2088void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07002089 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01002090 //ALOGV("callbackwrapper");
Marco Nelissen6b74d672012-02-28 16:07:44 -08002091 CallbackData *data = (CallbackData*)cookie;
Andy Hungd1c74342015-07-07 16:54:23 -07002092 // lock to ensure we aren't caught in the middle of a track switch.
Marco Nelissen6b74d672012-02-28 16:07:44 -08002093 data->lock();
2094 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07002095 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08002096 if (me == NULL) {
2097 // no output set, likely because the track was scheduled to be reused
2098 // by another player, but the format turned out to be incompatible.
2099 data->unlock();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002100 if (buffer != NULL) {
2101 buffer->size = 0;
2102 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08002103 return;
2104 }
Andreas Huber20111aa2009-07-14 16:56:47 -07002105
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002106 switch(event) {
2107 case AudioTrack::EVENT_MORE_DATA: {
2108 size_t actualSize = (*me->mCallback)(
2109 me, buffer->raw, buffer->size, me->mCallbackCookie,
2110 CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002111
Andy Hung719b46b2015-05-31 22:18:25 -07002112 // Log when no data is returned from the callback.
2113 // (1) We may have no data (especially with network streaming sources).
2114 // (2) We may have reached the EOS and the audio track is not stopped yet.
2115 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
2116 // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill).
2117 //
2118 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
2119 // nevertheless for power reasons, we don't want to see too many of these.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08002120
Andy Hung719b46b2015-05-31 22:18:25 -07002121 ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002122
2123 buffer->size = actualSize;
2124 } break;
2125
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002126 case AudioTrack::EVENT_STREAM_END:
Andy Hung719b46b2015-05-31 22:18:25 -07002127 // currently only occurs for offloaded callbacks
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002128 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
2129 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2130 me->mCallbackCookie, CB_EVENT_STREAM_END);
2131 break;
2132
2133 case AudioTrack::EVENT_NEW_IAUDIOTRACK :
2134 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
2135 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2136 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
2137 break;
2138
Glenn Kasten421743b2015-06-01 08:18:08 -07002139 case AudioTrack::EVENT_UNDERRUN:
Andy Hung719b46b2015-05-31 22:18:25 -07002140 // This occurs when there is no data available, typically
Glenn Kasten421743b2015-06-01 08:18:08 -07002141 // when there is a failure to supply data to the AudioTrack. It can also
2142 // occur in non-offloaded mode when the audio device comes out of standby.
2143 //
Andy Hung719b46b2015-05-31 22:18:25 -07002144 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
2145 // it may sound like an audible pop or glitch.
2146 //
2147 // The underrun event is sent once per track underrun; the condition is reset
2148 // when more data is sent to the AudioTrack.
Eric Laurente93cc032016-05-05 10:15:10 -07002149 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
Glenn Kasten421743b2015-06-01 08:18:08 -07002150 break;
2151
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002152 default:
2153 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
Andreas Huber51c1e0e2011-04-04 11:43:40 -07002154 }
2155
Marco Nelissen6b74d672012-02-28 16:07:44 -08002156 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07002157}
2158
Glenn Kastend848eb42016-03-08 13:42:11 -08002159audio_session_t MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07002160{
Andy Hungd1c74342015-07-07 16:54:23 -07002161 Mutex::Autolock lock(mLock);
Eric Laurent8c563ed2010-10-07 18:23:03 -07002162 return mSessionId;
2163}
2164
Eric Laurent6f59db12013-07-26 17:16:50 -07002165uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
2166{
Andy Hungd1c74342015-07-07 16:54:23 -07002167 Mutex::Autolock lock(mLock);
Eric Laurent6f59db12013-07-26 17:16:50 -07002168 if (mTrack == 0) return 0;
2169 return mTrack->getSampleRate();
2170}
2171
Andy Hungf2c87b32016-04-07 19:49:29 -07002172int64_t MediaPlayerService::AudioOutput::getBufferDurationInUs() const
2173{
2174 Mutex::Autolock lock(mLock);
2175 if (mTrack == 0) {
2176 return 0;
2177 }
2178 int64_t duration;
2179 if (mTrack->getBufferDurationInUs(&duration) != OK) {
2180 return 0;
2181 }
2182 return duration;
2183}
2184
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002185////////////////////////////////////////////////////////////////////////////////
2186
2187struct CallbackThread : public Thread {
2188 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
2189 MediaPlayerBase::AudioSink::AudioCallback cb,
2190 void *cookie);
2191
2192protected:
2193 virtual ~CallbackThread();
2194
2195 virtual bool threadLoop();
2196
2197private:
2198 wp<MediaPlayerBase::AudioSink> mSink;
2199 MediaPlayerBase::AudioSink::AudioCallback mCallback;
2200 void *mCookie;
2201 void *mBuffer;
2202 size_t mBufferSize;
2203
2204 CallbackThread(const CallbackThread &);
2205 CallbackThread &operator=(const CallbackThread &);
2206};
2207
2208CallbackThread::CallbackThread(
2209 const wp<MediaPlayerBase::AudioSink> &sink,
2210 MediaPlayerBase::AudioSink::AudioCallback cb,
2211 void *cookie)
2212 : mSink(sink),
2213 mCallback(cb),
2214 mCookie(cookie),
2215 mBuffer(NULL),
2216 mBufferSize(0) {
2217}
2218
2219CallbackThread::~CallbackThread() {
2220 if (mBuffer) {
2221 free(mBuffer);
2222 mBuffer = NULL;
2223 }
2224}
2225
2226bool CallbackThread::threadLoop() {
2227 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
2228 if (sink == NULL) {
2229 return false;
2230 }
2231
2232 if (mBuffer == NULL) {
2233 mBufferSize = sink->bufferSize();
2234 mBuffer = malloc(mBufferSize);
2235 }
2236
2237 size_t actualSize =
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00002238 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
2239 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002240
2241 if (actualSize > 0) {
2242 sink->write(mBuffer, actualSize);
Andy Hunga31335a2014-08-20 17:37:59 -07002243 // Could return false on sink->write() error or short count.
2244 // Not necessarily appropriate but would work for AudioCache behavior.
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002245 }
2246
2247 return true;
2248}
2249
2250////////////////////////////////////////////////////////////////////////////////
2251
Gloria Wang7cf180c2011-02-19 18:37:57 -08002252void MediaPlayerService::addBatteryData(uint32_t params)
2253{
2254 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002255
2256 int32_t time = systemTime() / 1000000L;
2257
2258 // change audio output devices. This notification comes from AudioFlinger
2259 if ((params & kBatteryDataSpeakerOn)
2260 || (params & kBatteryDataOtherAudioDeviceOn)) {
2261
2262 int deviceOn[NUM_AUDIO_DEVICES];
2263 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2264 deviceOn[i] = 0;
2265 }
2266
2267 if ((params & kBatteryDataSpeakerOn)
2268 && (params & kBatteryDataOtherAudioDeviceOn)) {
2269 deviceOn[SPEAKER_AND_OTHER] = 1;
2270 } else if (params & kBatteryDataSpeakerOn) {
2271 deviceOn[SPEAKER] = 1;
2272 } else {
2273 deviceOn[OTHER_AUDIO_DEVICE] = 1;
2274 }
2275
2276 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2277 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2278
2279 if (mBatteryAudio.refCount > 0) { // if playing audio
2280 if (!deviceOn[i]) {
2281 mBatteryAudio.lastTime[i] += time;
2282 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2283 mBatteryAudio.lastTime[i] = 0;
2284 } else {
2285 mBatteryAudio.lastTime[i] = 0 - time;
2286 }
2287 }
2288
2289 mBatteryAudio.deviceOn[i] = deviceOn[i];
2290 }
2291 }
2292 return;
2293 }
2294
Marco Nelissenb7848f12014-12-04 08:57:56 -08002295 // an audio stream is started
Gloria Wang9ee159b2011-02-24 14:51:45 -08002296 if (params & kBatteryDataAudioFlingerStart) {
2297 // record the start time only if currently no other audio
2298 // is being played
2299 if (mBatteryAudio.refCount == 0) {
2300 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2301 if (mBatteryAudio.deviceOn[i]) {
2302 mBatteryAudio.lastTime[i] -= time;
2303 }
2304 }
2305 }
2306
2307 mBatteryAudio.refCount ++;
2308 return;
2309
2310 } else if (params & kBatteryDataAudioFlingerStop) {
2311 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002312 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002313 return;
2314 }
2315
2316 // record the stop time only if currently this is the only
2317 // audio being played
2318 if (mBatteryAudio.refCount == 1) {
2319 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2320 if (mBatteryAudio.deviceOn[i]) {
2321 mBatteryAudio.lastTime[i] += time;
2322 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2323 mBatteryAudio.lastTime[i] = 0;
2324 }
2325 }
2326 }
2327
2328 mBatteryAudio.refCount --;
2329 return;
2330 }
2331
Gloria Wang7cf180c2011-02-19 18:37:57 -08002332 int uid = IPCThreadState::self()->getCallingUid();
2333 if (uid == AID_MEDIA) {
2334 return;
2335 }
2336 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08002337
2338 if (index < 0) { // create a new entry for this UID
2339 BatteryUsageInfo info;
2340 info.audioTotalTime = 0;
2341 info.videoTotalTime = 0;
2342 info.audioLastTime = 0;
2343 info.videoLastTime = 0;
2344 info.refCount = 0;
2345
Gloria Wang9ee159b2011-02-24 14:51:45 -08002346 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00002347 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002348 return;
2349 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08002350 }
2351
2352 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2353
2354 if (params & kBatteryDataCodecStarted) {
2355 if (params & kBatteryDataTrackAudio) {
2356 info.audioLastTime -= time;
2357 info.refCount ++;
2358 }
2359 if (params & kBatteryDataTrackVideo) {
2360 info.videoLastTime -= time;
2361 info.refCount ++;
2362 }
2363 } else {
2364 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002365 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002366 return;
2367 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00002368 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002369 mBatteryData.removeItem(uid);
2370 return;
2371 }
2372
2373 if (params & kBatteryDataTrackAudio) {
2374 info.audioLastTime += time;
2375 info.refCount --;
2376 }
2377 if (params & kBatteryDataTrackVideo) {
2378 info.videoLastTime += time;
2379 info.refCount --;
2380 }
2381
2382 // no stream is being played by this UID
2383 if (info.refCount == 0) {
2384 info.audioTotalTime += info.audioLastTime;
2385 info.audioLastTime = 0;
2386 info.videoTotalTime += info.videoLastTime;
2387 info.videoLastTime = 0;
2388 }
2389 }
2390}
2391
2392status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2393 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002394
2395 // audio output devices usage
2396 int32_t time = systemTime() / 1000000L; //in ms
2397 int32_t totalTime;
2398
2399 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2400 totalTime = mBatteryAudio.totalTime[i];
2401
2402 if (mBatteryAudio.deviceOn[i]
2403 && (mBatteryAudio.lastTime[i] != 0)) {
2404 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2405 totalTime += tmpTime;
2406 }
2407
2408 reply->writeInt32(totalTime);
2409 // reset the total time
2410 mBatteryAudio.totalTime[i] = 0;
2411 }
2412
2413 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002414 BatteryUsageInfo info;
2415 int size = mBatteryData.size();
2416
2417 reply->writeInt32(size);
2418 int i = 0;
2419
2420 while (i < size) {
2421 info = mBatteryData.valueAt(i);
2422
2423 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2424 reply->writeInt32(info.audioTotalTime);
2425 reply->writeInt32(info.videoTotalTime);
2426
2427 info.audioTotalTime = 0;
2428 info.videoTotalTime = 0;
2429
2430 // remove the UID entry where no stream is being played
2431 if (info.refCount <= 0) {
2432 mBatteryData.removeItemsAt(i);
2433 size --;
2434 i --;
2435 }
2436 i++;
2437 }
2438 return NO_ERROR;
2439}
nikoa64c8c72009-07-20 15:07:26 -07002440} // namespace android