blob: cd91e7214a1c7fafd2d436b0a3392591edbc869d [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
685 binder = sm->getService(String16("media.audio_flinger"));
686 mAudioDeathListener = new ServiceDeathNotifier(binder, p, AUDIO_PROCESS_DEATH);
687 binder->linkToDeath(mAudioDeathListener);
688
John Grossmanc795b642012-02-22 15:38:35 -0800689 if (!p->hardwareOutput()) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -0700690 Mutex::Autolock l(mLock);
Marco Nelissend457c972014-02-11 08:47:07 -0800691 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700692 mPid, mAudioAttributes);
John Grossmanc795b642012-02-22 15:38:35 -0800693 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
694 }
695
696 return p;
697}
698
699void MediaPlayerService::Client::setDataSource_post(
700 const sp<MediaPlayerBase>& p,
701 status_t status)
702{
703 ALOGV(" setDataSource");
704 mStatus = status;
705 if (mStatus != OK) {
706 ALOGE(" error: %d", mStatus);
707 return;
708 }
709
710 // Set the re-transmission endpoint if one was chosen.
711 if (mRetransmitEndpointValid) {
712 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
713 if (mStatus != NO_ERROR) {
714 ALOGE("setRetransmitEndpoint error: %d", mStatus);
715 }
716 }
717
718 if (mStatus == OK) {
719 mPlayer = p;
720 }
721}
722
Andreas Huber2db84552010-01-28 11:19:57 -0800723status_t MediaPlayerService::Client::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800724 const sp<IMediaHTTPService> &httpService,
725 const char *url,
726 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800727{
Steve Block3856b092011-10-20 11:56:00 +0100728 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800729 if (url == NULL)
730 return UNKNOWN_ERROR;
731
Dave Burked681bbb2011-08-30 14:39:17 +0100732 if ((strncmp(url, "http://", 7) == 0) ||
733 (strncmp(url, "https://", 8) == 0) ||
734 (strncmp(url, "rtsp://", 7) == 0)) {
735 if (!checkPermission("android.permission.INTERNET")) {
736 return PERMISSION_DENIED;
737 }
738 }
739
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800740 if (strncmp(url, "content://", 10) == 0) {
741 // get a filedescriptor for the content Uri and
742 // pass it to the setDataSource(fd) method
743
744 String16 url16(url);
745 int fd = android::openContentProviderFile(url16);
746 if (fd < 0)
747 {
Steve Block29357bc2012-01-06 19:20:56 +0000748 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800749 return UNKNOWN_ERROR;
750 }
751 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
752 close(fd);
753 return mStatus;
754 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700755 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800756 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
757 if (p == NULL) {
758 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800759 }
760
Andreas Huber1b86fe02014-01-29 11:13:26 -0800761 setDataSource_post(p, p->setDataSource(httpService, url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800762 return mStatus;
763 }
764}
765
766status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
767{
Marco Nelissen83b0fd92015-09-16 13:48:07 -0700768 ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
769 fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800770 struct stat sb;
771 int ret = fstat(fd, &sb);
772 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000773 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800774 return UNKNOWN_ERROR;
775 }
776
Andy Hung833b4752016-04-04 17:15:48 -0700777 ALOGV("st_dev = %llu", static_cast<unsigned long long>(sb.st_dev));
Steve Block3856b092011-10-20 11:56:00 +0100778 ALOGV("st_mode = %u", sb.st_mode);
Mark Salyzyn77342f72014-06-18 16:31:32 -0700779 ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
780 ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
Andy Hung833b4752016-04-04 17:15:48 -0700781 ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800782
783 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000784 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800785 return UNKNOWN_ERROR;
786 }
787 if (offset + length > sb.st_size) {
788 length = sb.st_size - offset;
Andy Hung833b4752016-04-04 17:15:48 -0700789 ALOGV("calculated length = %lld", (long long)length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800790 }
791
John Grossman44a7e422012-06-21 17:29:24 -0700792 player_type playerType = MediaPlayerFactory::getPlayerType(this,
793 fd,
794 offset,
795 length);
John Grossmanc795b642012-02-22 15:38:35 -0800796 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
797 if (p == NULL) {
798 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800799 }
800
801 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800802 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800803 return mStatus;
804}
805
Andreas Hubere2b10282010-11-23 11:41:34 -0800806status_t MediaPlayerService::Client::setDataSource(
807 const sp<IStreamSource> &source) {
808 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700809 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800810 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800811 if (p == NULL) {
812 return NO_INIT;
813 }
814
Andreas Hubere2b10282010-11-23 11:41:34 -0800815 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800816 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800817 return mStatus;
818}
819
Chris Watkins99f31602015-03-20 13:06:33 -0700820status_t MediaPlayerService::Client::setDataSource(
821 const sp<IDataSource> &source) {
822 sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source);
823 player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource);
824 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
825 if (p == NULL) {
826 return NO_INIT;
827 }
828 // now set data source
829 setDataSource_post(p, p->setDataSource(dataSource));
830 return mStatus;
831}
832
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700833void MediaPlayerService::Client::disconnectNativeWindow() {
834 if (mConnectedWindow != NULL) {
835 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
836 NATIVE_WINDOW_API_MEDIA);
837
838 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000839 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700840 strerror(-err), err);
841 }
842 }
843 mConnectedWindow.clear();
844}
845
Glenn Kasten11731182011-02-08 17:26:17 -0800846status_t MediaPlayerService::Client::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800847 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800848{
Andy McFadden484566c2012-12-18 09:46:54 -0800849 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800850 sp<MediaPlayerBase> p = getPlayer();
851 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700852
Marco Nelissenf8880202014-11-14 07:58:25 -0800853 sp<IBinder> binder(IInterface::asBinder(bufferProducer));
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700854 if (mConnectedWindowBinder == binder) {
855 return OK;
856 }
857
858 sp<ANativeWindow> anw;
Andy McFadden484566c2012-12-18 09:46:54 -0800859 if (bufferProducer != NULL) {
Marco Nelissenee08f7e2013-09-16 13:30:01 -0700860 anw = new Surface(bufferProducer, true /* controlledByApp */);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700861 status_t err = native_window_api_connect(anw.get(),
862 NATIVE_WINDOW_API_MEDIA);
863
864 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000865 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700866 // Note that we must do the reset before disconnecting from the ANW.
867 // Otherwise queue/dequeue calls could be made on the disconnected
868 // ANW, which may result in errors.
869 reset();
870
871 disconnectNativeWindow();
872
873 return err;
874 }
875 }
876
Andy McFadden484566c2012-12-18 09:46:54 -0800877 // Note that we must set the player's new GraphicBufferProducer before
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700878 // disconnecting the old one. Otherwise queue/dequeue calls could be made
879 // on the disconnected ANW, which may result in errors.
Andy McFadden484566c2012-12-18 09:46:54 -0800880 status_t err = p->setVideoSurfaceTexture(bufferProducer);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700881
882 disconnectNativeWindow();
883
884 mConnectedWindow = anw;
885
886 if (err == OK) {
887 mConnectedWindowBinder = binder;
888 } else {
889 disconnectNativeWindow();
890 }
891
892 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800893}
894
Nicolas Catania1d187f12009-05-12 23:25:55 -0700895status_t MediaPlayerService::Client::invoke(const Parcel& request,
896 Parcel *reply)
897{
898 sp<MediaPlayerBase> p = getPlayer();
899 if (p == NULL) return UNKNOWN_ERROR;
900 return p->invoke(request, reply);
901}
902
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700903// This call doesn't need to access the native player.
904status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
905{
906 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700907 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700908
Nicolas Catania48290382009-07-10 13:53:06 -0700909 if (unmarshallFilter(filter, &allow, &status) &&
910 unmarshallFilter(filter, &drop, &status)) {
911 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700912
913 mMetadataAllow = allow;
914 mMetadataDrop = drop;
915 }
916 return status;
917}
918
Nicolas Catania48290382009-07-10 13:53:06 -0700919status_t MediaPlayerService::Client::getMetadata(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700920 bool update_only, bool /*apply_filter*/, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700921{
nikoa64c8c72009-07-20 15:07:26 -0700922 sp<MediaPlayerBase> player = getPlayer();
923 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700924
nikod608a812009-07-16 16:39:53 -0700925 status_t status;
926 // Placeholder for the return code, updated by the caller.
927 reply->writeInt32(-1);
928
nikoa64c8c72009-07-20 15:07:26 -0700929 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700930
931 // We don't block notifications while we fetch the data. We clear
932 // mMetadataUpdated first so we don't lose notifications happening
933 // during the rest of this call.
934 {
935 Mutex::Autolock lock(mLock);
936 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700937 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700938 }
939 mMetadataUpdated.clear();
940 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700941
nikoa64c8c72009-07-20 15:07:26 -0700942 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700943
nikoa64c8c72009-07-20 15:07:26 -0700944 metadata.appendHeader();
945 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700946
947 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700948 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000949 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700950 return status;
951 }
952
953 // FIXME: Implement filtering on the result. Not critical since
954 // filtering takes place on the update notifications already. This
955 // would be when all the metadata are fetch and a filter is set.
956
nikod608a812009-07-16 16:39:53 -0700957 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700958 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700959 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700960}
961
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800962status_t MediaPlayerService::Client::prepareAsync()
963{
Steve Block3856b092011-10-20 11:56:00 +0100964 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800965 sp<MediaPlayerBase> p = getPlayer();
966 if (p == 0) return UNKNOWN_ERROR;
967 status_t ret = p->prepareAsync();
968#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000969 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800970 if (ret == NO_ERROR) mAntagonizer->start();
971#endif
972 return ret;
973}
974
975status_t MediaPlayerService::Client::start()
976{
Steve Block3856b092011-10-20 11:56:00 +0100977 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800978 sp<MediaPlayerBase> p = getPlayer();
979 if (p == 0) return UNKNOWN_ERROR;
980 p->setLooping(mLoop);
981 return p->start();
982}
983
984status_t MediaPlayerService::Client::stop()
985{
Steve Block3856b092011-10-20 11:56:00 +0100986 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800987 sp<MediaPlayerBase> p = getPlayer();
988 if (p == 0) return UNKNOWN_ERROR;
989 return p->stop();
990}
991
992status_t MediaPlayerService::Client::pause()
993{
Steve Block3856b092011-10-20 11:56:00 +0100994 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800995 sp<MediaPlayerBase> p = getPlayer();
996 if (p == 0) return UNKNOWN_ERROR;
997 return p->pause();
998}
999
1000status_t MediaPlayerService::Client::isPlaying(bool* state)
1001{
1002 *state = false;
1003 sp<MediaPlayerBase> p = getPlayer();
1004 if (p == 0) return UNKNOWN_ERROR;
1005 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +01001006 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001007 return NO_ERROR;
1008}
1009
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001010status_t MediaPlayerService::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -08001011{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001012 ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
1013 mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Wei Jia98160162015-02-04 17:01:11 -08001014 sp<MediaPlayerBase> p = getPlayer();
1015 if (p == 0) return UNKNOWN_ERROR;
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001016 return p->setPlaybackSettings(rate);
1017}
1018
1019status_t MediaPlayerService::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
1020{
1021 sp<MediaPlayerBase> p = getPlayer();
1022 if (p == 0) return UNKNOWN_ERROR;
1023 status_t ret = p->getPlaybackSettings(rate);
1024 if (ret == NO_ERROR) {
1025 ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
1026 mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
1027 } else {
1028 ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
1029 }
1030 return ret;
1031}
1032
1033status_t MediaPlayerService::Client::setSyncSettings(
1034 const AVSyncSettings& sync, float videoFpsHint)
1035{
1036 ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
1037 mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
1038 sp<MediaPlayerBase> p = getPlayer();
1039 if (p == 0) return UNKNOWN_ERROR;
1040 return p->setSyncSettings(sync, videoFpsHint);
1041}
1042
1043status_t MediaPlayerService::Client::getSyncSettings(
1044 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
1045{
1046 sp<MediaPlayerBase> p = getPlayer();
1047 if (p == 0) return UNKNOWN_ERROR;
1048 status_t ret = p->getSyncSettings(sync, videoFps);
1049 if (ret == NO_ERROR) {
1050 ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
1051 mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
1052 } else {
1053 ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
1054 }
1055 return ret;
Wei Jia98160162015-02-04 17:01:11 -08001056}
1057
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001058status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
1059{
Steve Block3856b092011-10-20 11:56:00 +01001060 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001061 sp<MediaPlayerBase> p = getPlayer();
1062 if (p == 0) return UNKNOWN_ERROR;
1063 status_t ret = p->getCurrentPosition(msec);
1064 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001065 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001066 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001067 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001068 }
1069 return ret;
1070}
1071
1072status_t MediaPlayerService::Client::getDuration(int *msec)
1073{
Steve Block3856b092011-10-20 11:56:00 +01001074 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001075 sp<MediaPlayerBase> p = getPlayer();
1076 if (p == 0) return UNKNOWN_ERROR;
1077 status_t ret = p->getDuration(msec);
1078 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001079 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001080 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001081 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001082 }
1083 return ret;
1084}
1085
Marco Nelissen6b74d672012-02-28 16:07:44 -08001086status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
1087 ALOGV("setNextPlayer");
1088 Mutex::Autolock l(mLock);
1089 sp<Client> c = static_cast<Client*>(player.get());
1090 mNextClient = c;
John Grossman5f7e55e2012-08-24 14:47:25 -07001091
1092 if (c != NULL) {
1093 if (mAudioOutput != NULL) {
1094 mAudioOutput->setNextOutput(c->mAudioOutput);
1095 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
1096 ALOGE("no current audio output");
1097 }
1098
1099 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
1100 mPlayer->setNextPlayer(mNextClient->getPlayer());
1101 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001102 }
John Grossman5f7e55e2012-08-24 14:47:25 -07001103
Marco Nelissen6b74d672012-02-28 16:07:44 -08001104 return OK;
1105}
1106
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001107status_t MediaPlayerService::Client::seekTo(int msec)
1108{
Steve Block3856b092011-10-20 11:56:00 +01001109 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001110 sp<MediaPlayerBase> p = getPlayer();
1111 if (p == 0) return UNKNOWN_ERROR;
1112 return p->seekTo(msec);
1113}
1114
1115status_t MediaPlayerService::Client::reset()
1116{
Steve Block3856b092011-10-20 11:56:00 +01001117 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -08001118 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001119 sp<MediaPlayerBase> p = getPlayer();
1120 if (p == 0) return UNKNOWN_ERROR;
1121 return p->reset();
1122}
1123
Glenn Kastenfff6d712012-01-12 16:38:12 -08001124status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001125{
Steve Block3856b092011-10-20 11:56:00 +01001126 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001127 // TODO: for hardware output, call player instead
1128 Mutex::Autolock l(mLock);
1129 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1130 return NO_ERROR;
1131}
1132
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001133status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
1134{
1135 if (mAudioAttributes != NULL) { free(mAudioAttributes); }
1136 mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001137 if (mAudioAttributes == NULL) {
1138 return NO_MEMORY;
1139 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001140 unmarshallAudioAttributes(parcel, mAudioAttributes);
1141
1142 ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
1143 mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
1144 mAudioAttributes->tags);
1145
1146 if (mAudioOutput != 0) {
1147 mAudioOutput->setAudioAttributes(mAudioAttributes);
1148 }
1149 return NO_ERROR;
1150}
1151
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001152status_t MediaPlayerService::Client::setLooping(int loop)
1153{
Steve Block3856b092011-10-20 11:56:00 +01001154 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001155 mLoop = loop;
1156 sp<MediaPlayerBase> p = getPlayer();
1157 if (p != 0) return p->setLooping(loop);
1158 return NO_ERROR;
1159}
1160
1161status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1162{
Steve Block3856b092011-10-20 11:56:00 +01001163 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -08001164
1165 // for hardware output, call player instead
1166 sp<MediaPlayerBase> p = getPlayer();
1167 {
1168 Mutex::Autolock l(mLock);
1169 if (p != 0 && p->hardwareOutput()) {
1170 MediaPlayerHWInterface* hwp =
1171 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1172 return hwp->setVolume(leftVolume, rightVolume);
1173 } else {
1174 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1175 return NO_ERROR;
1176 }
1177 }
1178
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001179 return NO_ERROR;
1180}
1181
Eric Laurent2beeb502010-07-16 07:43:46 -07001182status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1183{
Steve Block3856b092011-10-20 11:56:00 +01001184 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001185 Mutex::Autolock l(mLock);
1186 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1187 return NO_ERROR;
1188}
1189
1190status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1191{
Steve Block3856b092011-10-20 11:56:00 +01001192 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001193 Mutex::Autolock l(mLock);
1194 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1195 return NO_ERROR;
1196}
Nicolas Catania48290382009-07-10 13:53:06 -07001197
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001198status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001199 ALOGV("[%d] setParameter(%d)", mConnId, key);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001200 switch (key) {
1201 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
1202 {
1203 Mutex::Autolock l(mLock);
1204 return setAudioAttributes_l(request);
1205 }
1206 default:
1207 sp<MediaPlayerBase> p = getPlayer();
1208 if (p == 0) { return UNKNOWN_ERROR; }
1209 return p->setParameter(key, request);
1210 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001211}
1212
1213status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001214 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001215 sp<MediaPlayerBase> p = getPlayer();
1216 if (p == 0) return UNKNOWN_ERROR;
1217 return p->getParameter(key, reply);
1218}
1219
John Grossmanc795b642012-02-22 15:38:35 -08001220status_t MediaPlayerService::Client::setRetransmitEndpoint(
1221 const struct sockaddr_in* endpoint) {
1222
1223 if (NULL != endpoint) {
1224 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1225 uint16_t p = ntohs(endpoint->sin_port);
1226 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1227 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1228 } else {
1229 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1230 }
1231
1232 sp<MediaPlayerBase> p = getPlayer();
1233
1234 // Right now, the only valid time to set a retransmit endpoint is before
1235 // player selection has been made (since the presence or absence of a
1236 // retransmit endpoint is going to determine which player is selected during
1237 // setDataSource).
1238 if (p != 0) return INVALID_OPERATION;
1239
1240 if (NULL != endpoint) {
1241 mRetransmitEndpoint = *endpoint;
1242 mRetransmitEndpointValid = true;
1243 } else {
1244 mRetransmitEndpointValid = false;
1245 }
1246
1247 return NO_ERROR;
1248}
1249
John Grossman44a7e422012-06-21 17:29:24 -07001250status_t MediaPlayerService::Client::getRetransmitEndpoint(
1251 struct sockaddr_in* endpoint)
1252{
1253 if (NULL == endpoint)
1254 return BAD_VALUE;
1255
1256 sp<MediaPlayerBase> p = getPlayer();
1257
1258 if (p != NULL)
1259 return p->getRetransmitEndpoint(endpoint);
1260
1261 if (!mRetransmitEndpointValid)
1262 return NO_INIT;
1263
1264 *endpoint = mRetransmitEndpoint;
1265
1266 return NO_ERROR;
1267}
1268
Gloria Wangb483c472011-04-11 17:23:27 -07001269void MediaPlayerService::Client::notify(
1270 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001271{
1272 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001273 if (client == NULL) {
1274 return;
1275 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001276
James Dongb8a98252012-08-26 16:13:03 -07001277 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001278 {
1279 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001280 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001281 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001282 if (client->mAudioOutput != NULL)
1283 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001284 client->mNextClient->start();
Wei Jia2afac0c2016-01-07 12:13:07 -08001285 if (client->mNextClient->mClient != NULL) {
1286 client->mNextClient->mClient->notify(
1287 MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1288 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001289 }
1290 }
1291
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001292 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001293 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001294 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001295
1296 if(client->shouldDropMetadata(metadata_type)) {
1297 return;
1298 }
1299
1300 // Update the list of metadata that have changed. getMetadata
1301 // also access mMetadataUpdated and clears it.
1302 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001303 }
James Dongb8a98252012-08-26 16:13:03 -07001304
1305 if (c != NULL) {
1306 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1307 c->notify(msg, ext1, ext2, obj);
1308 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001309}
1310
Nicolas Catania48290382009-07-10 13:53:06 -07001311
nikoa64c8c72009-07-20 15:07:26 -07001312bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001313{
Nicolas Catania48290382009-07-10 13:53:06 -07001314 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001315
Nicolas Catania48290382009-07-10 13:53:06 -07001316 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001317 return true;
1318 }
1319
Nicolas Catania48290382009-07-10 13:53:06 -07001320 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001321 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001322 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001323 return true;
1324 }
1325}
1326
Nicolas Catania48290382009-07-10 13:53:06 -07001327
nikoa64c8c72009-07-20 15:07:26 -07001328void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001329 Mutex::Autolock lock(mLock);
1330 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1331 mMetadataUpdated.add(metadata_type);
1332 }
1333}
1334
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001335#if CALLBACK_ANTAGONIZER
1336const int Antagonizer::interval = 10000; // 10 msecs
1337
1338Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1339 mExit(false), mActive(false), mClient(client), mCb(cb)
1340{
1341 createThread(callbackThread, this);
1342}
1343
1344void Antagonizer::kill()
1345{
1346 Mutex::Autolock _l(mLock);
1347 mActive = false;
1348 mExit = true;
1349 mCondition.wait(mLock);
1350}
1351
1352int Antagonizer::callbackThread(void* user)
1353{
Steve Blockb8a80522011-12-20 16:23:08 +00001354 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001355 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1356 while (!p->mExit) {
1357 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001358 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001359 p->mCb(p->mClient, 0, 0, 0);
1360 }
1361 usleep(interval);
1362 }
1363 Mutex::Autolock _l(p->mLock);
1364 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001365 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001366 return 0;
1367}
1368#endif
1369
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001370#undef LOG_TAG
1371#define LOG_TAG "AudioSink"
Glenn Kastend848eb42016-03-08 13:42:11 -08001372MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, int uid, int pid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001373 const audio_attributes_t* attr)
Andreas Huber20111aa2009-07-14 16:56:47 -07001374 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001375 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001376 mCallbackData(NULL),
Andy Hungd1c74342015-07-07 16:54:23 -07001377 mStreamType(AUDIO_STREAM_MUSIC),
Andy Hungd1c74342015-07-07 16:54:23 -07001378 mLeftVolume(1.0),
1379 mRightVolume(1.0),
1380 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
1381 mSampleRateHz(0),
1382 mMsecsPerFrame(0),
1383 mFrameSize(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001384 mSessionId(sessionId),
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001385 mUid(uid),
Marco Nelissend457c972014-02-11 08:47:07 -08001386 mPid(pid),
Andy Hungd1c74342015-07-07 16:54:23 -07001387 mSendLevel(0.0),
1388 mAuxEffectId(0),
1389 mFlags(AUDIO_OUTPUT_FLAG_NONE)
1390{
Steve Block3856b092011-10-20 11:56:00 +01001391 ALOGV("AudioOutput(%d)", sessionId);
Eric Laurent43562692015-07-15 16:49:07 -07001392 if (attr != NULL) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001393 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1394 if (mAttributes != NULL) {
1395 memcpy(mAttributes, attr, sizeof(audio_attributes_t));
1396 mStreamType = audio_attributes_to_stream_type(attr);
1397 }
1398 } else {
1399 mAttributes = NULL;
Eric Laurent43562692015-07-15 16:49:07 -07001400 }
1401
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001402 setMinBufferCount();
1403}
1404
1405MediaPlayerService::AudioOutput::~AudioOutput()
1406{
1407 close();
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001408 free(mAttributes);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001409 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001410}
1411
Andy Hungd1c74342015-07-07 16:54:23 -07001412//static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001413void MediaPlayerService::AudioOutput::setMinBufferCount()
1414{
1415 char value[PROPERTY_VALUE_MAX];
1416 if (property_get("ro.kernel.qemu", value, 0)) {
1417 mIsOnEmulator = true;
1418 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1419 }
1420}
1421
Andy Hungd1c74342015-07-07 16:54:23 -07001422// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001423bool MediaPlayerService::AudioOutput::isOnEmulator()
1424{
Andy Hungd1c74342015-07-07 16:54:23 -07001425 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001426 return mIsOnEmulator;
1427}
1428
Andy Hungd1c74342015-07-07 16:54:23 -07001429// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001430int MediaPlayerService::AudioOutput::getMinBufferCount()
1431{
Andy Hungd1c74342015-07-07 16:54:23 -07001432 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001433 return mMinBufferCount;
1434}
1435
1436ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1437{
Andy Hungd1c74342015-07-07 16:54:23 -07001438 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001439 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001440 return mTrack->frameCount() * mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001441}
1442
1443ssize_t MediaPlayerService::AudioOutput::frameCount() const
1444{
Andy Hungd1c74342015-07-07 16:54:23 -07001445 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001446 if (mTrack == 0) return NO_INIT;
1447 return mTrack->frameCount();
1448}
1449
1450ssize_t MediaPlayerService::AudioOutput::channelCount() const
1451{
Andy Hungd1c74342015-07-07 16:54:23 -07001452 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001453 if (mTrack == 0) return NO_INIT;
1454 return mTrack->channelCount();
1455}
1456
1457ssize_t MediaPlayerService::AudioOutput::frameSize() const
1458{
Andy Hungd1c74342015-07-07 16:54:23 -07001459 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001460 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001461 return mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001462}
1463
1464uint32_t MediaPlayerService::AudioOutput::latency () const
1465{
Andy Hungd1c74342015-07-07 16:54:23 -07001466 Mutex::Autolock lock(mLock);
Eric Laurentdb354e52012-03-05 17:27:11 -08001467 if (mTrack == 0) return 0;
1468 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001469}
1470
1471float MediaPlayerService::AudioOutput::msecsPerFrame() const
1472{
Andy Hungd1c74342015-07-07 16:54:23 -07001473 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001474 return mMsecsPerFrame;
1475}
1476
Marco Nelissen4110c102012-03-29 09:31:28 -07001477status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001478{
Andy Hungd1c74342015-07-07 16:54:23 -07001479 Mutex::Autolock lock(mLock);
Eric Laurent342e9cf2010-01-19 17:37:09 -08001480 if (mTrack == 0) return NO_INIT;
1481 return mTrack->getPosition(position);
1482}
1483
Lajos Molnar06ad1522014-08-28 07:27:44 -07001484status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const
1485{
Andy Hungd1c74342015-07-07 16:54:23 -07001486 Mutex::Autolock lock(mLock);
Lajos Molnar06ad1522014-08-28 07:27:44 -07001487 if (mTrack == 0) return NO_INIT;
1488 return mTrack->getTimestamp(ts);
1489}
1490
Wei Jiac4ac8172015-10-21 10:35:48 -07001491// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
1492// as it acquires locks and may query the audio driver.
1493//
1494// Some calls could conceivably retrieve extrapolated data instead of
1495// accessing getTimestamp() or getPosition() every time a data buffer with
1496// a media time is received.
1497//
1498// Calculate duration of played samples if played at normal rate (i.e., 1.0).
1499int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const
1500{
1501 Mutex::Autolock lock(mLock);
1502 if (mTrack == 0 || mSampleRateHz == 0) {
Wei Jia213f4902015-10-22 08:55:25 -07001503 return 0;
Wei Jiac4ac8172015-10-21 10:35:48 -07001504 }
1505
1506 uint32_t numFramesPlayed;
1507 int64_t numFramesPlayedAt;
1508 AudioTimestamp ts;
1509 static const int64_t kStaleTimestamp100ms = 100000;
1510
1511 status_t res = mTrack->getTimestamp(ts);
1512 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
1513 numFramesPlayed = ts.mPosition;
1514 numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
1515 const int64_t timestampAge = nowUs - numFramesPlayedAt;
1516 if (timestampAge > kStaleTimestamp100ms) {
1517 // This is an audio FIXME.
1518 // getTimestamp returns a timestamp which may come from audio mixing threads.
1519 // After pausing, the MixerThread may go idle, thus the mTime estimate may
1520 // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms,
1521 // the max latency should be about 25ms with an average around 12ms (to be verified).
1522 // For safety we use 100ms.
1523 ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)",
1524 (long long)nowUs, (long long)numFramesPlayedAt);
1525 numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
1526 }
1527 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1528 } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
1529 numFramesPlayed = 0;
1530 numFramesPlayedAt = nowUs;
1531 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
1532 // numFramesPlayed, (long long)numFramesPlayedAt);
1533 } else { // case 3: transitory at new track or audio fast tracks.
1534 res = mTrack->getPosition(&numFramesPlayed);
1535 CHECK_EQ(res, (status_t)OK);
1536 numFramesPlayedAt = nowUs;
1537 numFramesPlayedAt += 1000LL * mTrack->latency() / 2; /* XXX */
1538 //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1539 }
1540
1541 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
1542 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1543 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
1544 + nowUs - numFramesPlayedAt;
1545 if (durationUs < 0) {
1546 // Occurs when numFramesPlayed position is very small and the following:
1547 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
1548 // numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed.
1549 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
1550 // numFramesPlayedAt, by a time amount greater than numFramesPlayed.
1551 //
1552 // Both of these are transitory conditions.
1553 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
1554 durationUs = 0;
1555 }
1556 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
1557 (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt);
1558 return durationUs;
1559}
1560
Marco Nelissen4110c102012-03-29 09:31:28 -07001561status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1562{
Andy Hungd1c74342015-07-07 16:54:23 -07001563 Mutex::Autolock lock(mLock);
Marco Nelissen4110c102012-03-29 09:31:28 -07001564 if (mTrack == 0) return NO_INIT;
Andy Hung2f6e73d2016-04-08 12:12:58 -07001565 ExtendedTimestamp ets;
1566 status_t status = mTrack->getTimestamp(&ets);
1567 if (status == OK || status == WOULD_BLOCK) {
1568 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
1569 }
1570 return status;
Marco Nelissen4110c102012-03-29 09:31:28 -07001571}
1572
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001573status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
1574{
Andy Hungd1c74342015-07-07 16:54:23 -07001575 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001576 if (mTrack == 0) return NO_INIT;
1577 return mTrack->setParameters(keyValuePairs);
1578}
1579
1580String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
1581{
Andy Hungd1c74342015-07-07 16:54:23 -07001582 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001583 if (mTrack == 0) return String8::empty();
1584 return mTrack->getParameters(keys);
1585}
1586
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001587void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
Andy Hungd1c74342015-07-07 16:54:23 -07001588 Mutex::Autolock lock(mLock);
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001589 if (attributes == NULL) {
1590 free(mAttributes);
1591 mAttributes = NULL;
1592 } else {
1593 if (mAttributes == NULL) {
1594 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1595 }
1596 memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
Eric Laurent43562692015-07-15 16:49:07 -07001597 mStreamType = audio_attributes_to_stream_type(attributes);
1598 }
1599}
1600
1601void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
1602{
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001603 Mutex::Autolock lock(mLock);
Eric Laurent43562692015-07-15 16:49:07 -07001604 // do not allow direct stream type modification if attributes have been set
1605 if (mAttributes == NULL) {
1606 mStreamType = streamType;
1607 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001608}
1609
Andy Hungd1c74342015-07-07 16:54:23 -07001610void MediaPlayerService::AudioOutput::deleteRecycledTrack_l()
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001611{
Andy Hungd1c74342015-07-07 16:54:23 -07001612 ALOGV("deleteRecycledTrack_l");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001613 if (mRecycledTrack != 0) {
1614
1615 if (mCallbackData != NULL) {
1616 mCallbackData->setOutput(NULL);
1617 mCallbackData->endTrackSwitch();
1618 }
1619
1620 if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
Andy Hunge13f8a62016-03-30 14:20:42 -07001621 int32_t msec = 0;
1622 if (!mRecycledTrack->stopped()) { // check if active
1623 (void)mRecycledTrack->pendingDuration(&msec);
1624 }
1625 mRecycledTrack->stop(); // ensure full data drain
1626 ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
1627 if (msec > 0) {
1628 static const int32_t WAIT_LIMIT_MS = 3000;
1629 if (msec > WAIT_LIMIT_MS) {
1630 msec = WAIT_LIMIT_MS;
1631 }
1632 usleep(msec * 1000LL);
1633 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001634 }
1635 // An offloaded track isn't flushed because the STREAM_END is reported
1636 // slightly prematurely to allow time for the gapless track switch
1637 // but this means that if we decide not to recycle the track there
1638 // could be a small amount of residual data still playing. We leave
1639 // AudioFlinger to drain the track.
1640
1641 mRecycledTrack.clear();
Andy Hungd1c74342015-07-07 16:54:23 -07001642 close_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001643 delete mCallbackData;
1644 mCallbackData = NULL;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001645 }
1646}
1647
Andy Hungd1c74342015-07-07 16:54:23 -07001648void MediaPlayerService::AudioOutput::close_l()
1649{
1650 mTrack.clear();
1651}
1652
Andreas Huber20111aa2009-07-14 16:56:47 -07001653status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001654 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1655 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001656 AudioCallback cb, void *cookie,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001657 audio_output_flags_t flags,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001658 const audio_offload_info_t *offloadInfo,
Andy Hung179652e2015-05-31 22:49:46 -07001659 bool doNotReconnect,
1660 uint32_t suggestedFrameCount)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001661{
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001662 ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
1663 format, bufferCount, mSessionId, flags);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001664
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001665 // offloading is only supported in callback mode for now.
1666 // offloadInfo must be present if offload flag is set
1667 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
1668 ((cb == NULL) || (offloadInfo == NULL))) {
1669 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001670 }
1671
Andy Hung179652e2015-05-31 22:49:46 -07001672 // compute frame count for the AudioTrack internal buffer
1673 size_t frameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001674 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1675 frameCount = 0; // AudioTrack will get frame count from AudioFlinger
1676 } else {
Andy Hung179652e2015-05-31 22:49:46 -07001677 // try to estimate the buffer processing fetch size from AudioFlinger.
1678 // framesPerBuffer is approximate and generally correct, except when it's not :-).
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001679 uint32_t afSampleRate;
1680 size_t afFrameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001681 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1682 return NO_INIT;
1683 }
1684 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1685 return NO_INIT;
1686 }
Andy Hung179652e2015-05-31 22:49:46 -07001687 const size_t framesPerBuffer =
1688 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001689
Andy Hung179652e2015-05-31 22:49:46 -07001690 if (bufferCount == 0) {
1691 // use suggestedFrameCount
1692 bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
1693 }
1694 // Check argument bufferCount against the mininum buffer count
1695 if (bufferCount != 0 && bufferCount < mMinBufferCount) {
1696 ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
1697 bufferCount = mMinBufferCount;
1698 }
1699 // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
1700 // which will be the minimum size permitted.
1701 frameCount = bufferCount * framesPerBuffer;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001702 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001703
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001704 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001705 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001706 if (0 == channelMask) {
1707 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1708 return NO_INIT;
1709 }
1710 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001711
Andy Hungd1c74342015-07-07 16:54:23 -07001712 Mutex::Autolock lock(mLock);
Andy Hung179652e2015-05-31 22:49:46 -07001713 mCallback = cb;
1714 mCallbackCookie = cookie;
1715
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001716 // Check whether we can recycle the track
1717 bool reuse = false;
1718 bool bothOffloaded = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001719
Glenn Kasten2799d742013-05-30 14:33:29 -07001720 if (mRecycledTrack != 0) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001721 // check whether we are switching between two offloaded tracks
1722 bothOffloaded = (flags & mRecycledTrack->getFlags()
1723 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
Marco Nelissen67295b52012-06-11 14:52:53 -07001724
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001725 // check if the existing track can be reused as-is, or if a new track needs to be created.
1726 reuse = true;
1727
Marco Nelissen67295b52012-06-11 14:52:53 -07001728 if ((mCallbackData == NULL && mCallback != NULL) ||
1729 (mCallbackData != NULL && mCallback == NULL)) {
1730 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1731 ALOGV("can't chain callback and write");
1732 reuse = false;
1733 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001734 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
1735 ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
Marco Nelissen67295b52012-06-11 14:52:53 -07001736 mRecycledTrack->getSampleRate(), sampleRate,
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001737 mRecycledTrack->channelCount(), channelCount);
Marco Nelissen67295b52012-06-11 14:52:53 -07001738 reuse = false;
1739 } else if (flags != mFlags) {
1740 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1741 reuse = false;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001742 } else if (mRecycledTrack->format() != format) {
1743 reuse = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001744 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001745 } else {
1746 ALOGV("no track available to recycle");
1747 }
1748
1749 ALOGV_IF(bothOffloaded, "both tracks offloaded");
1750
1751 // If we can't recycle and both tracks are offloaded
1752 // we must close the previous output before opening a new one
1753 if (bothOffloaded && !reuse) {
1754 ALOGV("both offloaded and not recycling");
Andy Hungd1c74342015-07-07 16:54:23 -07001755 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001756 }
1757
1758 sp<AudioTrack> t;
1759 CallbackData *newcbd = NULL;
1760
1761 // We don't attempt to create a new track if we are recycling an
1762 // offloaded track. But, if we are recycling a non-offloaded or we
1763 // are switching where one is offloaded and one isn't then we create
1764 // the new track in advance so that we can read additional stream info
1765
1766 if (!(reuse && bothOffloaded)) {
1767 ALOGV("creating new AudioTrack");
1768
1769 if (mCallback != NULL) {
1770 newcbd = new CallbackData(this);
1771 t = new AudioTrack(
1772 mStreamType,
1773 sampleRate,
1774 format,
1775 channelMask,
1776 frameCount,
1777 flags,
1778 CallbackWrapper,
1779 newcbd,
1780 0, // notification frames
1781 mSessionId,
1782 AudioTrack::TRANSFER_CALLBACK,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001783 offloadInfo,
Marco Nelissend457c972014-02-11 08:47:07 -08001784 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001785 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001786 mAttributes,
1787 doNotReconnect);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001788 } else {
Andy Hungff874dc2016-04-11 16:49:09 -07001789 // TODO: Due to buffer memory concerns, we use a max target playback speed
1790 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
1791 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
1792 const float targetSpeed =
1793 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
1794 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
1795 "track target speed:%f clamped from playback speed:%f",
1796 targetSpeed, mPlaybackRate.mSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001797 t = new AudioTrack(
1798 mStreamType,
1799 sampleRate,
1800 format,
1801 channelMask,
1802 frameCount,
1803 flags,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001804 NULL, // callback
1805 NULL, // user data
1806 0, // notification frames
1807 mSessionId,
1808 AudioTrack::TRANSFER_DEFAULT,
1809 NULL, // offload info
Marco Nelissend457c972014-02-11 08:47:07 -08001810 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001811 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001812 mAttributes,
Andy Hungff874dc2016-04-11 16:49:09 -07001813 doNotReconnect,
1814 targetSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001815 }
1816
1817 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1818 ALOGE("Unable to create audio track");
1819 delete newcbd;
Glenn Kasten3e98ecd2015-05-18 13:13:24 -07001820 // t goes out of scope, so reference count drops to zero
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001821 return NO_INIT;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001822 } else {
1823 // successful AudioTrack initialization implies a legacy stream type was generated
1824 // from the audio attributes
1825 mStreamType = t->streamType();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001826 }
1827 }
1828
1829 if (reuse) {
1830 CHECK(mRecycledTrack != NULL);
1831
1832 if (!bothOffloaded) {
1833 if (mRecycledTrack->frameCount() != t->frameCount()) {
Andy Hung833b4752016-04-04 17:15:48 -07001834 ALOGV("framecount differs: %zu/%zu frames",
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001835 mRecycledTrack->frameCount(), t->frameCount());
1836 reuse = false;
1837 }
1838 }
1839
Marco Nelissen67295b52012-06-11 14:52:53 -07001840 if (reuse) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001841 ALOGV("chaining to next output and recycling track");
Andy Hungd1c74342015-07-07 16:54:23 -07001842 close_l();
Marco Nelissen67295b52012-06-11 14:52:53 -07001843 mTrack = mRecycledTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001844 mRecycledTrack.clear();
Marco Nelissen67295b52012-06-11 14:52:53 -07001845 if (mCallbackData != NULL) {
1846 mCallbackData->setOutput(this);
1847 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001848 delete newcbd;
1849 return OK;
1850 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001851 }
1852
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001853 // we're not going to reuse the track, unblock and flush it
1854 // this was done earlier if both tracks are offloaded
1855 if (!bothOffloaded) {
Andy Hungd1c74342015-07-07 16:54:23 -07001856 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001857 }
1858
1859 CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
1860
Marco Nelissen67295b52012-06-11 14:52:53 -07001861 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001862 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001863 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001864
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001865 mSampleRateHz = sampleRate;
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001866 mFlags = flags;
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001867 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Andy Hungd1c74342015-07-07 16:54:23 -07001868 mFrameSize = t->frameSize();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001869 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001870
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001871 status_t res = NO_ERROR;
Wei Jia0162d002015-06-09 11:59:33 -07001872 // Note some output devices may give us a direct track even though we don't specify it.
1873 // Example: Line application b/17459982.
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001874 if ((t->getFlags() & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001875 res = t->setPlaybackRate(mPlaybackRate);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001876 if (res == NO_ERROR) {
1877 t->setAuxEffectSendLevel(mSendLevel);
1878 res = t->attachAuxEffect(mAuxEffectId);
1879 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001880 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001881 ALOGV("open() DONE status %d", res);
1882 return res;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001883}
1884
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001885status_t MediaPlayerService::AudioOutput::start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001886{
Steve Block3856b092011-10-20 11:56:00 +01001887 ALOGV("start");
Andy Hungd1c74342015-07-07 16:54:23 -07001888 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001889 if (mCallbackData != NULL) {
1890 mCallbackData->endTrackSwitch();
1891 }
Glenn Kasten2799d742013-05-30 14:33:29 -07001892 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001893 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001894 mTrack->setAuxEffectSendLevel(mSendLevel);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001895 return mTrack->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001896 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001897 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001898}
1899
Marco Nelissen6b74d672012-02-28 16:07:44 -08001900void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
Andy Hungd1c74342015-07-07 16:54:23 -07001901 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001902 mNextOutput = nextOutput;
1903}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001904
Marco Nelissen6b74d672012-02-28 16:07:44 -08001905void MediaPlayerService::AudioOutput::switchToNextOutput() {
1906 ALOGV("switchToNextOutput");
Andy Hungd1c74342015-07-07 16:54:23 -07001907
1908 // Try to acquire the callback lock before moving track (without incurring deadlock).
1909 const unsigned kMaxSwitchTries = 100;
1910 Mutex::Autolock lock(mLock);
1911 for (unsigned tries = 0;;) {
1912 if (mTrack == 0) {
1913 return;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001914 }
Andy Hungd1c74342015-07-07 16:54:23 -07001915 if (mNextOutput != NULL && mNextOutput != this) {
1916 if (mCallbackData != NULL) {
1917 // two alternative approaches
1918#if 1
1919 CallbackData *callbackData = mCallbackData;
1920 mLock.unlock();
1921 // proper acquisition sequence
1922 callbackData->lock();
1923 mLock.lock();
1924 // Caution: it is unlikely that someone deleted our callback or changed our target
1925 if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
1926 // fatal if we are starved out.
1927 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1928 "switchToNextOutput() cannot obtain correct lock sequence");
1929 callbackData->unlock();
1930 continue;
1931 }
1932 callbackData->mSwitching = true; // begin track switch
1933#else
1934 // tryBeginTrackSwitch() returns false if the callback has the lock.
1935 if (!mCallbackData->tryBeginTrackSwitch()) {
1936 // fatal if we are starved out.
1937 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1938 "switchToNextOutput() cannot obtain callback lock");
1939 mLock.unlock();
1940 usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
1941 mLock.lock();
1942 continue;
1943 }
1944#endif
1945 }
1946
1947 Mutex::Autolock nextLock(mNextOutput->mLock);
1948
1949 // If the next output track is not NULL, then it has been
1950 // opened already for playback.
1951 // This is possible even without the next player being started,
1952 // for example, the next player could be prepared and seeked.
1953 //
1954 // Presuming it isn't advisable to force the track over.
1955 if (mNextOutput->mTrack == NULL) {
1956 ALOGD("Recycling track for gapless playback");
1957 delete mNextOutput->mCallbackData;
1958 mNextOutput->mCallbackData = mCallbackData;
1959 mNextOutput->mRecycledTrack = mTrack;
1960 mNextOutput->mSampleRateHz = mSampleRateHz;
1961 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
Andy Hungd1c74342015-07-07 16:54:23 -07001962 mNextOutput->mFlags = mFlags;
1963 mNextOutput->mFrameSize = mFrameSize;
1964 close_l();
1965 mCallbackData = NULL; // destruction handled by mNextOutput
1966 } else {
1967 ALOGW("Ignoring gapless playback because next player has already started");
1968 // remove track in case resource needed for future players.
1969 if (mCallbackData != NULL) {
1970 mCallbackData->endTrackSwitch(); // release lock for callbacks before close.
1971 }
1972 close_l();
1973 }
1974 }
1975 break;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001976 }
1977}
1978
Wei Jia7d3f4df2015-03-03 15:28:00 -08001979ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001980{
Andy Hungd1c74342015-07-07 16:54:23 -07001981 Mutex::Autolock lock(mLock);
Glenn Kastenadad3d72014-02-21 14:51:43 -08001982 LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
Andreas Huber20111aa2009-07-14 16:56:47 -07001983
Steve Block3856b092011-10-20 11:56:00 +01001984 //ALOGV("write(%p, %u)", buffer, size);
Glenn Kasten2799d742013-05-30 14:33:29 -07001985 if (mTrack != 0) {
Andy Hung2f6e73d2016-04-08 12:12:58 -07001986 return mTrack->write(buffer, size, blocking);
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001987 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001988 return NO_INIT;
1989}
1990
1991void MediaPlayerService::AudioOutput::stop()
1992{
Steve Block3856b092011-10-20 11:56:00 +01001993 ALOGV("stop");
Andy Hungd1c74342015-07-07 16:54:23 -07001994 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001995 if (mTrack != 0) mTrack->stop();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001996}
1997
1998void MediaPlayerService::AudioOutput::flush()
1999{
Steve Block3856b092011-10-20 11:56:00 +01002000 ALOGV("flush");
Andy Hungd1c74342015-07-07 16:54:23 -07002001 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07002002 if (mTrack != 0) mTrack->flush();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002003}
2004
2005void MediaPlayerService::AudioOutput::pause()
2006{
Steve Block3856b092011-10-20 11:56:00 +01002007 ALOGV("pause");
Andy Hungd1c74342015-07-07 16:54:23 -07002008 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07002009 if (mTrack != 0) mTrack->pause();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002010}
2011
2012void MediaPlayerService::AudioOutput::close()
2013{
Steve Block3856b092011-10-20 11:56:00 +01002014 ALOGV("close");
Erik Wolsheimer7845a1f2015-10-30 12:07:52 -07002015 sp<AudioTrack> track;
2016 {
2017 Mutex::Autolock lock(mLock);
2018 track = mTrack;
2019 close_l(); // clears mTrack
2020 }
2021 // destruction of the track occurs outside of mutex.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002022}
2023
2024void MediaPlayerService::AudioOutput::setVolume(float left, float right)
2025{
Steve Block3856b092011-10-20 11:56:00 +01002026 ALOGV("setVolume(%f, %f)", left, right);
Andy Hungd1c74342015-07-07 16:54:23 -07002027 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002028 mLeftVolume = left;
2029 mRightVolume = right;
Glenn Kasten2799d742013-05-30 14:33:29 -07002030 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002031 mTrack->setVolume(left, right);
2032 }
2033}
2034
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002035status_t MediaPlayerService::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002036{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002037 ALOGV("setPlaybackRate(%f %f %d %d)",
2038 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Andy Hungd1c74342015-07-07 16:54:23 -07002039 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002040 if (mTrack == 0) {
2041 // remember rate so that we can set it when the track is opened
2042 mPlaybackRate = rate;
2043 return OK;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002044 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002045 status_t res = mTrack->setPlaybackRate(rate);
2046 if (res != NO_ERROR) {
2047 return res;
2048 }
2049 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
2050 CHECK_GT(rate.mSpeed, 0.f);
2051 mPlaybackRate = rate;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002052 if (mSampleRateHz != 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002053 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002054 }
2055 return res;
2056}
2057
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002058status_t MediaPlayerService::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
2059{
2060 ALOGV("setPlaybackRate");
Andy Hungd1c74342015-07-07 16:54:23 -07002061 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002062 if (mTrack == 0) {
2063 return NO_INIT;
2064 }
2065 *rate = mTrack->getPlaybackRate();
2066 return NO_ERROR;
2067}
2068
Eric Laurent2beeb502010-07-16 07:43:46 -07002069status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
2070{
Steve Block3856b092011-10-20 11:56:00 +01002071 ALOGV("setAuxEffectSendLevel(%f)", level);
Andy Hungd1c74342015-07-07 16:54:23 -07002072 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002073 mSendLevel = level;
Glenn Kasten2799d742013-05-30 14:33:29 -07002074 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002075 return mTrack->setAuxEffectSendLevel(level);
2076 }
2077 return NO_ERROR;
2078}
2079
2080status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
2081{
Steve Block3856b092011-10-20 11:56:00 +01002082 ALOGV("attachAuxEffect(%d)", effectId);
Andy Hungd1c74342015-07-07 16:54:23 -07002083 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002084 mAuxEffectId = effectId;
Glenn Kasten2799d742013-05-30 14:33:29 -07002085 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002086 return mTrack->attachAuxEffect(effectId);
2087 }
2088 return NO_ERROR;
2089}
2090
Andreas Huber20111aa2009-07-14 16:56:47 -07002091// static
2092void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07002093 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01002094 //ALOGV("callbackwrapper");
Marco Nelissen6b74d672012-02-28 16:07:44 -08002095 CallbackData *data = (CallbackData*)cookie;
Andy Hungd1c74342015-07-07 16:54:23 -07002096 // lock to ensure we aren't caught in the middle of a track switch.
Marco Nelissen6b74d672012-02-28 16:07:44 -08002097 data->lock();
2098 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07002099 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08002100 if (me == NULL) {
2101 // no output set, likely because the track was scheduled to be reused
2102 // by another player, but the format turned out to be incompatible.
2103 data->unlock();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002104 if (buffer != NULL) {
2105 buffer->size = 0;
2106 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08002107 return;
2108 }
Andreas Huber20111aa2009-07-14 16:56:47 -07002109
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002110 switch(event) {
2111 case AudioTrack::EVENT_MORE_DATA: {
2112 size_t actualSize = (*me->mCallback)(
2113 me, buffer->raw, buffer->size, me->mCallbackCookie,
2114 CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002115
Andy Hung719b46b2015-05-31 22:18:25 -07002116 // Log when no data is returned from the callback.
2117 // (1) We may have no data (especially with network streaming sources).
2118 // (2) We may have reached the EOS and the audio track is not stopped yet.
2119 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
2120 // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill).
2121 //
2122 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
2123 // nevertheless for power reasons, we don't want to see too many of these.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08002124
Andy Hung719b46b2015-05-31 22:18:25 -07002125 ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002126
2127 buffer->size = actualSize;
2128 } break;
2129
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002130 case AudioTrack::EVENT_STREAM_END:
Andy Hung719b46b2015-05-31 22:18:25 -07002131 // currently only occurs for offloaded callbacks
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002132 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
2133 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2134 me->mCallbackCookie, CB_EVENT_STREAM_END);
2135 break;
2136
2137 case AudioTrack::EVENT_NEW_IAUDIOTRACK :
2138 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
2139 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2140 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
2141 break;
2142
Glenn Kasten421743b2015-06-01 08:18:08 -07002143 case AudioTrack::EVENT_UNDERRUN:
Andy Hung719b46b2015-05-31 22:18:25 -07002144 // This occurs when there is no data available, typically
Glenn Kasten421743b2015-06-01 08:18:08 -07002145 // when there is a failure to supply data to the AudioTrack. It can also
2146 // occur in non-offloaded mode when the audio device comes out of standby.
2147 //
Andy Hung719b46b2015-05-31 22:18:25 -07002148 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
2149 // it may sound like an audible pop or glitch.
2150 //
2151 // The underrun event is sent once per track underrun; the condition is reset
2152 // when more data is sent to the AudioTrack.
Eric Laurente93cc032016-05-05 10:15:10 -07002153 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
Glenn Kasten421743b2015-06-01 08:18:08 -07002154 break;
2155
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002156 default:
2157 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
Andreas Huber51c1e0e2011-04-04 11:43:40 -07002158 }
2159
Marco Nelissen6b74d672012-02-28 16:07:44 -08002160 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07002161}
2162
Glenn Kastend848eb42016-03-08 13:42:11 -08002163audio_session_t MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07002164{
Andy Hungd1c74342015-07-07 16:54:23 -07002165 Mutex::Autolock lock(mLock);
Eric Laurent8c563ed2010-10-07 18:23:03 -07002166 return mSessionId;
2167}
2168
Eric Laurent6f59db12013-07-26 17:16:50 -07002169uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
2170{
Andy Hungd1c74342015-07-07 16:54:23 -07002171 Mutex::Autolock lock(mLock);
Eric Laurent6f59db12013-07-26 17:16:50 -07002172 if (mTrack == 0) return 0;
2173 return mTrack->getSampleRate();
2174}
2175
Andy Hungf2c87b32016-04-07 19:49:29 -07002176int64_t MediaPlayerService::AudioOutput::getBufferDurationInUs() const
2177{
2178 Mutex::Autolock lock(mLock);
2179 if (mTrack == 0) {
2180 return 0;
2181 }
2182 int64_t duration;
2183 if (mTrack->getBufferDurationInUs(&duration) != OK) {
2184 return 0;
2185 }
2186 return duration;
2187}
2188
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002189////////////////////////////////////////////////////////////////////////////////
2190
2191struct CallbackThread : public Thread {
2192 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
2193 MediaPlayerBase::AudioSink::AudioCallback cb,
2194 void *cookie);
2195
2196protected:
2197 virtual ~CallbackThread();
2198
2199 virtual bool threadLoop();
2200
2201private:
2202 wp<MediaPlayerBase::AudioSink> mSink;
2203 MediaPlayerBase::AudioSink::AudioCallback mCallback;
2204 void *mCookie;
2205 void *mBuffer;
2206 size_t mBufferSize;
2207
2208 CallbackThread(const CallbackThread &);
2209 CallbackThread &operator=(const CallbackThread &);
2210};
2211
2212CallbackThread::CallbackThread(
2213 const wp<MediaPlayerBase::AudioSink> &sink,
2214 MediaPlayerBase::AudioSink::AudioCallback cb,
2215 void *cookie)
2216 : mSink(sink),
2217 mCallback(cb),
2218 mCookie(cookie),
2219 mBuffer(NULL),
2220 mBufferSize(0) {
2221}
2222
2223CallbackThread::~CallbackThread() {
2224 if (mBuffer) {
2225 free(mBuffer);
2226 mBuffer = NULL;
2227 }
2228}
2229
2230bool CallbackThread::threadLoop() {
2231 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
2232 if (sink == NULL) {
2233 return false;
2234 }
2235
2236 if (mBuffer == NULL) {
2237 mBufferSize = sink->bufferSize();
2238 mBuffer = malloc(mBufferSize);
2239 }
2240
2241 size_t actualSize =
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00002242 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
2243 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002244
2245 if (actualSize > 0) {
2246 sink->write(mBuffer, actualSize);
Andy Hunga31335a2014-08-20 17:37:59 -07002247 // Could return false on sink->write() error or short count.
2248 // Not necessarily appropriate but would work for AudioCache behavior.
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002249 }
2250
2251 return true;
2252}
2253
2254////////////////////////////////////////////////////////////////////////////////
2255
Gloria Wang7cf180c2011-02-19 18:37:57 -08002256void MediaPlayerService::addBatteryData(uint32_t params)
2257{
2258 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002259
2260 int32_t time = systemTime() / 1000000L;
2261
2262 // change audio output devices. This notification comes from AudioFlinger
2263 if ((params & kBatteryDataSpeakerOn)
2264 || (params & kBatteryDataOtherAudioDeviceOn)) {
2265
2266 int deviceOn[NUM_AUDIO_DEVICES];
2267 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2268 deviceOn[i] = 0;
2269 }
2270
2271 if ((params & kBatteryDataSpeakerOn)
2272 && (params & kBatteryDataOtherAudioDeviceOn)) {
2273 deviceOn[SPEAKER_AND_OTHER] = 1;
2274 } else if (params & kBatteryDataSpeakerOn) {
2275 deviceOn[SPEAKER] = 1;
2276 } else {
2277 deviceOn[OTHER_AUDIO_DEVICE] = 1;
2278 }
2279
2280 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2281 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2282
2283 if (mBatteryAudio.refCount > 0) { // if playing audio
2284 if (!deviceOn[i]) {
2285 mBatteryAudio.lastTime[i] += time;
2286 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2287 mBatteryAudio.lastTime[i] = 0;
2288 } else {
2289 mBatteryAudio.lastTime[i] = 0 - time;
2290 }
2291 }
2292
2293 mBatteryAudio.deviceOn[i] = deviceOn[i];
2294 }
2295 }
2296 return;
2297 }
2298
Marco Nelissenb7848f12014-12-04 08:57:56 -08002299 // an audio stream is started
Gloria Wang9ee159b2011-02-24 14:51:45 -08002300 if (params & kBatteryDataAudioFlingerStart) {
2301 // record the start time only if currently no other audio
2302 // is being played
2303 if (mBatteryAudio.refCount == 0) {
2304 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2305 if (mBatteryAudio.deviceOn[i]) {
2306 mBatteryAudio.lastTime[i] -= time;
2307 }
2308 }
2309 }
2310
2311 mBatteryAudio.refCount ++;
2312 return;
2313
2314 } else if (params & kBatteryDataAudioFlingerStop) {
2315 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002316 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002317 return;
2318 }
2319
2320 // record the stop time only if currently this is the only
2321 // audio being played
2322 if (mBatteryAudio.refCount == 1) {
2323 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2324 if (mBatteryAudio.deviceOn[i]) {
2325 mBatteryAudio.lastTime[i] += time;
2326 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2327 mBatteryAudio.lastTime[i] = 0;
2328 }
2329 }
2330 }
2331
2332 mBatteryAudio.refCount --;
2333 return;
2334 }
2335
Gloria Wang7cf180c2011-02-19 18:37:57 -08002336 int uid = IPCThreadState::self()->getCallingUid();
2337 if (uid == AID_MEDIA) {
2338 return;
2339 }
2340 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08002341
2342 if (index < 0) { // create a new entry for this UID
2343 BatteryUsageInfo info;
2344 info.audioTotalTime = 0;
2345 info.videoTotalTime = 0;
2346 info.audioLastTime = 0;
2347 info.videoLastTime = 0;
2348 info.refCount = 0;
2349
Gloria Wang9ee159b2011-02-24 14:51:45 -08002350 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00002351 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002352 return;
2353 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08002354 }
2355
2356 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2357
2358 if (params & kBatteryDataCodecStarted) {
2359 if (params & kBatteryDataTrackAudio) {
2360 info.audioLastTime -= time;
2361 info.refCount ++;
2362 }
2363 if (params & kBatteryDataTrackVideo) {
2364 info.videoLastTime -= time;
2365 info.refCount ++;
2366 }
2367 } else {
2368 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002369 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002370 return;
2371 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00002372 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002373 mBatteryData.removeItem(uid);
2374 return;
2375 }
2376
2377 if (params & kBatteryDataTrackAudio) {
2378 info.audioLastTime += time;
2379 info.refCount --;
2380 }
2381 if (params & kBatteryDataTrackVideo) {
2382 info.videoLastTime += time;
2383 info.refCount --;
2384 }
2385
2386 // no stream is being played by this UID
2387 if (info.refCount == 0) {
2388 info.audioTotalTime += info.audioLastTime;
2389 info.audioLastTime = 0;
2390 info.videoTotalTime += info.videoLastTime;
2391 info.videoLastTime = 0;
2392 }
2393 }
2394}
2395
2396status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2397 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002398
2399 // audio output devices usage
2400 int32_t time = systemTime() / 1000000L; //in ms
2401 int32_t totalTime;
2402
2403 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2404 totalTime = mBatteryAudio.totalTime[i];
2405
2406 if (mBatteryAudio.deviceOn[i]
2407 && (mBatteryAudio.lastTime[i] != 0)) {
2408 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2409 totalTime += tmpTime;
2410 }
2411
2412 reply->writeInt32(totalTime);
2413 // reset the total time
2414 mBatteryAudio.totalTime[i] = 0;
2415 }
2416
2417 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002418 BatteryUsageInfo info;
2419 int size = mBatteryData.size();
2420
2421 reply->writeInt32(size);
2422 int i = 0;
2423
2424 while (i < size) {
2425 info = mBatteryData.valueAt(i);
2426
2427 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2428 reply->writeInt32(info.audioTotalTime);
2429 reply->writeInt32(info.videoTotalTime);
2430
2431 info.audioTotalTime = 0;
2432 info.videoTotalTime = 0;
2433
2434 // remove the UID entry where no stream is being played
2435 if (info.refCount <= 0) {
2436 mBatteryData.removeItemsAt(i);
2437 size --;
2438 i --;
2439 }
2440 i++;
2441 }
2442 return NO_ERROR;
2443}
nikoa64c8c72009-07-20 15:07:26 -07002444} // namespace android