blob: 2afbdb4def75eae3e8d4cba06d50afce771669a1 [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
Dima Zavin64760242011-05-11 14:15:23 -070065#include <system/audio.h>
Dima Zavinfce7a472011-04-19 22:30:36 -070066
Gloria Wang7cf180c2011-02-19 18:37:57 -080067#include <private/android_filesystem_config.h>
68
James Dong559bf282012-03-28 10:29:14 -070069#include "ActivityManager.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080070#include "MediaRecorderClient.h"
71#include "MediaPlayerService.h"
72#include "MetadataRetrieverClient.h"
John Grossman44a7e422012-06-21 17:29:24 -070073#include "MediaPlayerFactory.h"
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080074
Nicolas Catania14d27472009-07-13 14:37:49 -070075#include "TestPlayerStub.h"
Andreas Huberf9334412010-12-15 15:17:42 -080076#include "nuplayer/NuPlayerDriver.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070077
Andreas Huber20111aa2009-07-14 16:56:47 -070078#include <OMX.h>
Nicolas Catania14d27472009-07-13 14:37:49 -070079
Andreas Hubered3e3e02012-03-26 11:13:27 -070080#include "Crypto.h"
Jeff Tinkercc82dc62013-02-08 10:18:35 -080081#include "Drm.h"
Andreas Huber59451f82012-09-18 10:36:32 -070082#include "HDCP.h"
Andreas Huberb7319a72013-05-29 14:20:52 -070083#include "HTTPBase.h"
Andreas Huber35213f12012-08-29 11:41:50 -070084#include "RemoteDisplay.h"
Andreas Hubered3e3e02012-03-26 11:13:27 -070085
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070086namespace {
nikoa64c8c72009-07-20 15:07:26 -070087using android::media::Metadata;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070088using android::status_t;
89using android::OK;
90using android::BAD_VALUE;
91using android::NOT_ENOUGH_DATA;
92using android::Parcel;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070093
94// Max number of entries in the filter.
95const int kMaxFilterSize = 64; // I pulled that out of thin air.
96
Andy Hungff874dc2016-04-11 16:49:09 -070097const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
98
nikoa64c8c72009-07-20 15:07:26 -070099// FIXME: Move all the metadata related function in the Metadata.cpp
nikod608a812009-07-16 16:39:53 -0700100
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700101
102// Unmarshall a filter from a Parcel.
103// Filter format in a parcel:
104//
105// 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
106// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107// | number of entries (n) |
108// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109// | metadata type 1 |
110// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111// | metadata type 2 |
112// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113// ....
114// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115// | metadata type n |
116// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117//
118// @param p Parcel that should start with a filter.
119// @param[out] filter On exit contains the list of metadata type to be
120// filtered.
121// @param[out] status On exit contains the status code to be returned.
122// @return true if the parcel starts with a valid filter.
123bool unmarshallFilter(const Parcel& p,
nikoa64c8c72009-07-20 15:07:26 -0700124 Metadata::Filter *filter,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700125 status_t *status)
126{
Nicolas Catania48290382009-07-10 13:53:06 -0700127 int32_t val;
128 if (p.readInt32(&val) != OK)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700129 {
Steve Block29357bc2012-01-06 19:20:56 +0000130 ALOGE("Failed to read filter's length");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700131 *status = NOT_ENOUGH_DATA;
132 return false;
133 }
134
Nicolas Catania48290382009-07-10 13:53:06 -0700135 if( val > kMaxFilterSize || val < 0)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700136 {
Steve Block29357bc2012-01-06 19:20:56 +0000137 ALOGE("Invalid filter len %d", val);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700138 *status = BAD_VALUE;
139 return false;
140 }
141
Nicolas Catania48290382009-07-10 13:53:06 -0700142 const size_t num = val;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700143
144 filter->clear();
Nicolas Catania48290382009-07-10 13:53:06 -0700145 filter->setCapacity(num);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700146
nikoa64c8c72009-07-20 15:07:26 -0700147 size_t size = num * sizeof(Metadata::Type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700148
Nicolas Catania48290382009-07-10 13:53:06 -0700149
150 if (p.dataAvail() < size)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700151 {
Andy Hung833b4752016-04-04 17:15:48 -0700152 ALOGE("Filter too short expected %zu but got %zu", size, p.dataAvail());
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700153 *status = NOT_ENOUGH_DATA;
154 return false;
155 }
156
nikoa64c8c72009-07-20 15:07:26 -0700157 const Metadata::Type *data =
158 static_cast<const Metadata::Type*>(p.readInplace(size));
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700159
Nicolas Catania48290382009-07-10 13:53:06 -0700160 if (NULL == data)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700161 {
Steve Block29357bc2012-01-06 19:20:56 +0000162 ALOGE("Filter had no data");
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700163 *status = BAD_VALUE;
164 return false;
165 }
166
167 // TODO: The stl impl of vector would be more efficient here
168 // because it degenerates into a memcpy on pod types. Try to
169 // replace later or use stl::set.
Nicolas Catania48290382009-07-10 13:53:06 -0700170 for (size_t i = 0; i < num; ++i)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700171 {
Nicolas Catania48290382009-07-10 13:53:06 -0700172 filter->add(*data);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700173 ++data;
174 }
175 *status = OK;
176 return true;
177}
178
Nicolas Catania48290382009-07-10 13:53:06 -0700179// @param filter Of metadata type.
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700180// @param val To be searched.
181// @return true if a match was found.
nikoa64c8c72009-07-20 15:07:26 -0700182bool findMetadata(const Metadata::Filter& filter, const int32_t val)
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700183{
184 // Deal with empty and ANY right away
185 if (filter.isEmpty()) return false;
nikoa64c8c72009-07-20 15:07:26 -0700186 if (filter[0] == Metadata::kAny) return true;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700187
Nicolas Catania48290382009-07-10 13:53:06 -0700188 return filter.indexOf(val) >= 0;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700189}
190
191} // anonymous namespace
192
193
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700194namespace {
195using android::Parcel;
196using android::String16;
197
198// marshalling tag indicating flattened utf16 tags
199// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
200const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
201
202// Audio attributes format in a parcel:
203//
204// 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
205// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206// | usage |
207// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208// | content_type |
209// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Hyejin Kim4f418f92014-09-05 15:50:03 +0900210// | source |
211// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700212// | flags |
213// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214// | kAudioAttributesMarshallTagFlattenTags | // ignore tags if not found
215// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216// | flattened tags in UTF16 |
217// | ... |
218// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219//
220// @param p Parcel that contains audio attributes.
221// @param[out] attributes On exit points to an initialized audio_attributes_t structure
222// @param[out] status On exit contains the status code to be returned.
223void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes)
224{
225 attributes->usage = (audio_usage_t) parcel.readInt32();
226 attributes->content_type = (audio_content_type_t) parcel.readInt32();
Hyejin Kim4f418f92014-09-05 15:50:03 +0900227 attributes->source = (audio_source_t) parcel.readInt32();
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700228 attributes->flags = (audio_flags_mask_t) parcel.readInt32();
229 const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
230 if (hasFlattenedTag) {
231 // the tags are UTF16, convert to UTF8
232 String16 tags = parcel.readString16();
233 ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
234 if (realTagSize <= 0) {
235 strcpy(attributes->tags, "");
236 } else {
237 // copy the flattened string into the attributes as the destination for the conversion:
238 // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
239 size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
240 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
241 utf16_to_utf8(tags.string(), tagSize, attributes->tags);
242 }
243 } else {
244 ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
245 strcpy(attributes->tags, "");
246 }
247}
248} // anonymous namespace
249
250
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251namespace android {
252
Marco Nelissenf09611f2015-02-13 14:12:42 -0800253extern ALooperRoster gLooperRoster;
254
255
Dave Burked681bbb2011-08-30 14:39:17 +0100256static bool checkPermission(const char* permissionString) {
Dave Burked681bbb2011-08-30 14:39:17 +0100257 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
258 bool ok = checkCallingPermission(String16(permissionString));
Steve Block29357bc2012-01-06 19:20:56 +0000259 if (!ok) ALOGE("Request requires %s", permissionString);
Dave Burked681bbb2011-08-30 14:39:17 +0100260 return ok;
261}
262
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800263// 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 -0800264/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
265/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
266
267void MediaPlayerService::instantiate() {
268 defaultServiceManager()->addService(
269 String16("media.player"), new MediaPlayerService());
270}
271
272MediaPlayerService::MediaPlayerService()
273{
Steve Block3856b092011-10-20 11:56:00 +0100274 ALOGV("MediaPlayerService created");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800275 mNextConnId = 1;
Gloria Wang9ee159b2011-02-24 14:51:45 -0800276
277 mBatteryAudio.refCount = 0;
278 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
279 mBatteryAudio.deviceOn[i] = 0;
280 mBatteryAudio.lastTime[i] = 0;
281 mBatteryAudio.totalTime[i] = 0;
282 }
283 // speaker is on by default
284 mBatteryAudio.deviceOn[SPEAKER] = 1;
John Grossman44a7e422012-06-21 17:29:24 -0700285
Chong Zhang0b30fd42014-07-23 14:46:05 -0700286 // reset battery stats
287 // if the mediaserver has crashed, battery stats could be left
288 // in bad state, reset the state upon service start.
Wei Jia3f273d12015-11-24 09:06:49 -0800289 BatteryNotifier::getInstance().noteResetVideo();
Chong Zhang0b30fd42014-07-23 14:46:05 -0700290
John Grossman44a7e422012-06-21 17:29:24 -0700291 MediaPlayerFactory::registerBuiltinFactories();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800292}
293
294MediaPlayerService::~MediaPlayerService()
295{
Steve Block3856b092011-10-20 11:56:00 +0100296 ALOGV("MediaPlayerService destroyed");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800297}
298
Svet Ganovbe71aa22015-04-28 12:06:02 -0700299sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(const String16 &opPackageName)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800300{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800301 pid_t pid = IPCThreadState::self()->getCallingPid();
Svet Ganovbe71aa22015-04-28 12:06:02 -0700302 sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid, opPackageName);
Gloria Wangdac6a312009-10-29 15:46:37 -0700303 wp<MediaRecorderClient> w = recorder;
304 Mutex::Autolock lock(mLock);
305 mMediaRecorderClients.add(w);
Steve Block3856b092011-10-20 11:56:00 +0100306 ALOGV("Create new media recorder client from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800307 return recorder;
308}
309
Gloria Wangdac6a312009-10-29 15:46:37 -0700310void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
311{
312 Mutex::Autolock lock(mLock);
313 mMediaRecorderClients.remove(client);
Steve Block3856b092011-10-20 11:56:00 +0100314 ALOGV("Delete media recorder client");
Gloria Wangdac6a312009-10-29 15:46:37 -0700315}
316
Glenn Kastenf37971f2012-02-03 11:06:53 -0800317sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800318{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800319 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800320 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
Steve Block3856b092011-10-20 11:56:00 +0100321 ALOGV("Create new media retriever from pid %d", pid);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800322 return retriever;
323}
324
Glenn Kastenf37971f2012-02-03 11:06:53 -0800325sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
Glenn Kastend848eb42016-03-08 13:42:11 -0800326 audio_session_t audioSessionId)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800327{
Glenn Kastenf37971f2012-02-03 11:06:53 -0800328 pid_t pid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800329 int32_t connId = android_atomic_inc(&mNextConnId);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700330
331 sp<Client> c = new Client(
332 this, pid, connId, client, audioSessionId,
333 IPCThreadState::self()->getCallingUid());
334
Steve Block3856b092011-10-20 11:56:00 +0100335 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
Dave Burked681bbb2011-08-30 14:39:17 +0100336 IPCThreadState::self()->getCallingUid());
337
338 wp<Client> w = c;
339 {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800340 Mutex::Autolock lock(mLock);
341 mClients.add(w);
342 }
Andreas Hubere2b10282010-11-23 11:41:34 -0800343 return c;
344}
345
Lajos Molnar1381d4b2014-08-07 15:18:35 -0700346sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
347 return MediaCodecList::getLocalInstance();
348}
349
Marco Nelissen260e56c2016-01-28 21:41:25 +0000350sp<IOMX> MediaPlayerService::getOMX() {
Marco Nelissen1900e772016-02-02 16:12:16 -0800351 ALOGI("MediaPlayerService::getOMX");
Marco Nelissen260e56c2016-01-28 21:41:25 +0000352 Mutex::Autolock autoLock(mLock);
353
354 if (mOMX.get() == NULL) {
355 mOMX = new OMX;
356 }
357
358 return mOMX;
359}
360
Andreas Hubered3e3e02012-03-26 11:13:27 -0700361sp<ICrypto> MediaPlayerService::makeCrypto() {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700362 return new Crypto;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700363}
364
Jeff Tinkercc82dc62013-02-08 10:18:35 -0800365sp<IDrm> MediaPlayerService::makeDrm() {
366 return new Drm;
367}
368
Andreas Huber279dcd82013-01-30 10:41:25 -0800369sp<IHDCP> MediaPlayerService::makeHDCP(bool createEncryptionModule) {
370 return new HDCP(createEncryptionModule);
Andreas Huber59451f82012-09-18 10:36:32 -0700371}
372
Jeff Brown2013a542012-09-04 21:38:42 -0700373sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
Svet Ganovbe71aa22015-04-28 12:06:02 -0700374 const String16 &opPackageName,
Jeff Brown2013a542012-09-04 21:38:42 -0700375 const sp<IRemoteDisplayClient>& client, const String8& iface) {
Jeff Brownaba33d52012-09-07 17:38:58 -0700376 if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
377 return NULL;
378 }
379
Svet Ganovbe71aa22015-04-28 12:06:02 -0700380 return new RemoteDisplay(opPackageName, client, iface.string());
Jeff Brown2013a542012-09-04 21:38:42 -0700381}
382
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800383status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
384{
385 const size_t SIZE = 256;
386 char buffer[SIZE];
387 String8 result;
388
389 result.append(" AudioOutput\n");
390 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
391 mStreamType, mLeftVolume, mRightVolume);
392 result.append(buffer);
393 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Eric Laurentdb354e52012-03-05 17:27:11 -0800394 mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800395 result.append(buffer);
Eric Laurent2beeb502010-07-16 07:43:46 -0700396 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
397 mAuxEffectId, mSendLevel);
398 result.append(buffer);
399
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800400 ::write(fd, result.string(), result.size());
401 if (mTrack != 0) {
402 mTrack->dump(fd, args);
403 }
404 return NO_ERROR;
405}
406
Lajos Molnar6d339f12015-04-17 16:15:53 -0700407status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800408{
409 const size_t SIZE = 256;
410 char buffer[SIZE];
411 String8 result;
412 result.append(" Client\n");
413 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
414 mPid, mConnId, mStatus, mLoop?"true": "false");
415 result.append(buffer);
416 write(fd, result.string(), result.size());
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700417 if (mPlayer != NULL) {
418 mPlayer->dump(fd, args);
419 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800420 if (mAudioOutput != 0) {
421 mAudioOutput->dump(fd, args);
422 }
423 write(fd, "\n", 1);
424 return NO_ERROR;
425}
426
Marco Nelissenf09611f2015-02-13 14:12:42 -0800427/**
428 * The only arguments this understands right now are -c, -von and -voff,
429 * which are parsed by ALooperRoster::dump()
430 */
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800431status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
432{
433 const size_t SIZE = 256;
434 char buffer[SIZE];
435 String8 result;
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530436 SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
437 SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
438
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800439 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
440 snprintf(buffer, SIZE, "Permission Denial: "
441 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
442 IPCThreadState::self()->getCallingPid(),
443 IPCThreadState::self()->getCallingUid());
444 result.append(buffer);
445 } else {
446 Mutex::Autolock lock(mLock);
447 for (int i = 0, n = mClients.size(); i < n; ++i) {
448 sp<Client> c = mClients[i].promote();
449 if (c != 0) c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530450 clients.add(c);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800451 }
James Dongb9141222010-07-08 11:16:11 -0700452 if (mMediaRecorderClients.size() == 0) {
453 result.append(" No media recorder client\n\n");
454 } else {
455 for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
456 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
James Donge579e282011-10-18 22:29:20 -0700457 if (c != 0) {
458 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
459 result.append(buffer);
460 write(fd, result.string(), result.size());
461 result = "\n";
462 c->dump(fd, args);
Ravi Kumar Alamanda330c8e32014-12-22 10:05:29 +0530463 mediaRecorderClients.add(c);
James Donge579e282011-10-18 22:29:20 -0700464 }
James Dongb9141222010-07-08 11:16:11 -0700465 }
Gloria Wangdac6a312009-10-29 15:46:37 -0700466 }
467
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800468 result.append(" Files opened and/or mapped:\n");
Marco Nelissenf09611f2015-02-13 14:12:42 -0800469 snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800470 FILE *f = fopen(buffer, "r");
471 if (f) {
472 while (!feof(f)) {
473 fgets(buffer, SIZE, f);
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700474 if (strstr(buffer, " /storage/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800475 strstr(buffer, " /system/sounds/") ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700476 strstr(buffer, " /data/") ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800477 strstr(buffer, " /system/media/")) {
478 result.append(" ");
479 result.append(buffer);
480 }
481 }
482 fclose(f);
483 } else {
484 result.append("couldn't open ");
485 result.append(buffer);
486 result.append("\n");
487 }
488
Marco Nelissenf09611f2015-02-13 14:12:42 -0800489 snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800490 DIR *d = opendir(buffer);
491 if (d) {
492 struct dirent *ent;
493 while((ent = readdir(d)) != NULL) {
494 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
Marco Nelissenf09611f2015-02-13 14:12:42 -0800495 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800496 struct stat s;
497 if (lstat(buffer, &s) == 0) {
498 if ((s.st_mode & S_IFMT) == S_IFLNK) {
499 char linkto[256];
500 int len = readlink(buffer, linkto, sizeof(linkto));
501 if(len > 0) {
502 if(len > 255) {
503 linkto[252] = '.';
504 linkto[253] = '.';
505 linkto[254] = '.';
506 linkto[255] = 0;
507 } else {
508 linkto[len] = 0;
509 }
Marco Nelissen73ac1ee2012-05-07 15:36:32 -0700510 if (strstr(linkto, "/storage/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800511 strstr(linkto, "/system/sounds/") == linkto ||
Dave Sparks02fa8342010-09-27 16:55:18 -0700512 strstr(linkto, "/data/") == linkto ||
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800513 strstr(linkto, "/system/media/") == linkto) {
514 result.append(" ");
515 result.append(buffer);
516 result.append(" -> ");
517 result.append(linkto);
518 result.append("\n");
519 }
520 }
521 } else {
522 result.append(" unexpected type for ");
523 result.append(buffer);
524 result.append("\n");
525 }
526 }
527 }
528 }
529 closedir(d);
530 } else {
531 result.append("couldn't open ");
532 result.append(buffer);
533 result.append("\n");
534 }
535
Marco Nelissenf09611f2015-02-13 14:12:42 -0800536 gLooperRoster.dump(fd, args);
537
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800538 bool dumpMem = false;
539 for (size_t i = 0; i < args.size(); i++) {
540 if (args[i] == String16("-m")) {
541 dumpMem = true;
542 }
543 }
544 if (dumpMem) {
James Dong8635b7b2011-03-14 17:01:38 -0700545 dumpMemoryAddresses(fd);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800546 }
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
John Grossmanc795b642012-02-22 15:38:35 -0800643sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
644 player_type playerType)
645{
646 ALOGV("player type = %d", playerType);
647
648 // create the right type of player
649 sp<MediaPlayerBase> p = createPlayer(playerType);
650 if (p == NULL) {
651 return p;
652 }
653
654 if (!p->hardwareOutput()) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -0700655 Mutex::Autolock l(mLock);
Marco Nelissend457c972014-02-11 08:47:07 -0800656 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -0700657 mPid, mAudioAttributes);
John Grossmanc795b642012-02-22 15:38:35 -0800658 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
659 }
660
661 return p;
662}
663
664void MediaPlayerService::Client::setDataSource_post(
665 const sp<MediaPlayerBase>& p,
666 status_t status)
667{
668 ALOGV(" setDataSource");
669 mStatus = status;
670 if (mStatus != OK) {
671 ALOGE(" error: %d", mStatus);
672 return;
673 }
674
675 // Set the re-transmission endpoint if one was chosen.
676 if (mRetransmitEndpointValid) {
677 mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
678 if (mStatus != NO_ERROR) {
679 ALOGE("setRetransmitEndpoint error: %d", mStatus);
680 }
681 }
682
683 if (mStatus == OK) {
684 mPlayer = p;
685 }
686}
687
Andreas Huber2db84552010-01-28 11:19:57 -0800688status_t MediaPlayerService::Client::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800689 const sp<IMediaHTTPService> &httpService,
690 const char *url,
691 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800692{
Steve Block3856b092011-10-20 11:56:00 +0100693 ALOGV("setDataSource(%s)", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800694 if (url == NULL)
695 return UNKNOWN_ERROR;
696
Dave Burked681bbb2011-08-30 14:39:17 +0100697 if ((strncmp(url, "http://", 7) == 0) ||
698 (strncmp(url, "https://", 8) == 0) ||
699 (strncmp(url, "rtsp://", 7) == 0)) {
700 if (!checkPermission("android.permission.INTERNET")) {
701 return PERMISSION_DENIED;
702 }
703 }
704
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800705 if (strncmp(url, "content://", 10) == 0) {
706 // get a filedescriptor for the content Uri and
707 // pass it to the setDataSource(fd) method
708
709 String16 url16(url);
710 int fd = android::openContentProviderFile(url16);
711 if (fd < 0)
712 {
Steve Block29357bc2012-01-06 19:20:56 +0000713 ALOGE("Couldn't open fd for %s", url);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800714 return UNKNOWN_ERROR;
715 }
716 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
717 close(fd);
718 return mStatus;
719 } else {
John Grossman44a7e422012-06-21 17:29:24 -0700720 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
John Grossmanc795b642012-02-22 15:38:35 -0800721 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
722 if (p == NULL) {
723 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800724 }
725
Andreas Huber1b86fe02014-01-29 11:13:26 -0800726 setDataSource_post(p, p->setDataSource(httpService, url, headers));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800727 return mStatus;
728 }
729}
730
731status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
732{
Marco Nelissen83b0fd92015-09-16 13:48:07 -0700733 ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
734 fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800735 struct stat sb;
736 int ret = fstat(fd, &sb);
737 if (ret != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000738 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800739 return UNKNOWN_ERROR;
740 }
741
Andy Hung833b4752016-04-04 17:15:48 -0700742 ALOGV("st_dev = %llu", static_cast<unsigned long long>(sb.st_dev));
Steve Block3856b092011-10-20 11:56:00 +0100743 ALOGV("st_mode = %u", sb.st_mode);
Mark Salyzyn77342f72014-06-18 16:31:32 -0700744 ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
745 ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
Andy Hung833b4752016-04-04 17:15:48 -0700746 ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800747
748 if (offset >= sb.st_size) {
Steve Block29357bc2012-01-06 19:20:56 +0000749 ALOGE("offset error");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800750 return UNKNOWN_ERROR;
751 }
752 if (offset + length > sb.st_size) {
753 length = sb.st_size - offset;
Andy Hung833b4752016-04-04 17:15:48 -0700754 ALOGV("calculated length = %lld", (long long)length);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800755 }
756
John Grossman44a7e422012-06-21 17:29:24 -0700757 player_type playerType = MediaPlayerFactory::getPlayerType(this,
758 fd,
759 offset,
760 length);
John Grossmanc795b642012-02-22 15:38:35 -0800761 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
762 if (p == NULL) {
763 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800764 }
765
766 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800767 setDataSource_post(p, p->setDataSource(fd, offset, length));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800768 return mStatus;
769}
770
Andreas Hubere2b10282010-11-23 11:41:34 -0800771status_t MediaPlayerService::Client::setDataSource(
772 const sp<IStreamSource> &source) {
773 // create the right type of player
John Grossman44a7e422012-06-21 17:29:24 -0700774 player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
John Grossmanc795b642012-02-22 15:38:35 -0800775 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
Andreas Hubere2b10282010-11-23 11:41:34 -0800776 if (p == NULL) {
777 return NO_INIT;
778 }
779
Andreas Hubere2b10282010-11-23 11:41:34 -0800780 // now set data source
John Grossmanc795b642012-02-22 15:38:35 -0800781 setDataSource_post(p, p->setDataSource(source));
Andreas Hubere2b10282010-11-23 11:41:34 -0800782 return mStatus;
783}
784
Chris Watkins99f31602015-03-20 13:06:33 -0700785status_t MediaPlayerService::Client::setDataSource(
786 const sp<IDataSource> &source) {
787 sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source);
788 player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource);
789 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
790 if (p == NULL) {
791 return NO_INIT;
792 }
793 // now set data source
794 setDataSource_post(p, p->setDataSource(dataSource));
795 return mStatus;
796}
797
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700798void MediaPlayerService::Client::disconnectNativeWindow() {
799 if (mConnectedWindow != NULL) {
800 status_t err = native_window_api_disconnect(mConnectedWindow.get(),
801 NATIVE_WINDOW_API_MEDIA);
802
803 if (err != OK) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000804 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700805 strerror(-err), err);
806 }
807 }
808 mConnectedWindow.clear();
809}
810
Glenn Kasten11731182011-02-08 17:26:17 -0800811status_t MediaPlayerService::Client::setVideoSurfaceTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800812 const sp<IGraphicBufferProducer>& bufferProducer)
Glenn Kasten11731182011-02-08 17:26:17 -0800813{
Andy McFadden484566c2012-12-18 09:46:54 -0800814 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
Glenn Kasten11731182011-02-08 17:26:17 -0800815 sp<MediaPlayerBase> p = getPlayer();
816 if (p == 0) return UNKNOWN_ERROR;
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700817
Marco Nelissenf8880202014-11-14 07:58:25 -0800818 sp<IBinder> binder(IInterface::asBinder(bufferProducer));
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700819 if (mConnectedWindowBinder == binder) {
820 return OK;
821 }
822
823 sp<ANativeWindow> anw;
Andy McFadden484566c2012-12-18 09:46:54 -0800824 if (bufferProducer != NULL) {
Marco Nelissenee08f7e2013-09-16 13:30:01 -0700825 anw = new Surface(bufferProducer, true /* controlledByApp */);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700826 status_t err = native_window_api_connect(anw.get(),
827 NATIVE_WINDOW_API_MEDIA);
828
829 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000830 ALOGE("setVideoSurfaceTexture failed: %d", err);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700831 // Note that we must do the reset before disconnecting from the ANW.
832 // Otherwise queue/dequeue calls could be made on the disconnected
833 // ANW, which may result in errors.
834 reset();
835
836 disconnectNativeWindow();
837
838 return err;
839 }
840 }
841
Andy McFadden484566c2012-12-18 09:46:54 -0800842 // Note that we must set the player's new GraphicBufferProducer before
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700843 // disconnecting the old one. Otherwise queue/dequeue calls could be made
844 // on the disconnected ANW, which may result in errors.
Andy McFadden484566c2012-12-18 09:46:54 -0800845 status_t err = p->setVideoSurfaceTexture(bufferProducer);
Jamie Gennis7dae00b2011-10-26 18:36:31 -0700846
847 disconnectNativeWindow();
848
849 mConnectedWindow = anw;
850
851 if (err == OK) {
852 mConnectedWindowBinder = binder;
853 } else {
854 disconnectNativeWindow();
855 }
856
857 return err;
Glenn Kasten11731182011-02-08 17:26:17 -0800858}
859
Nicolas Catania1d187f12009-05-12 23:25:55 -0700860status_t MediaPlayerService::Client::invoke(const Parcel& request,
861 Parcel *reply)
862{
863 sp<MediaPlayerBase> p = getPlayer();
864 if (p == NULL) return UNKNOWN_ERROR;
865 return p->invoke(request, reply);
866}
867
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700868// This call doesn't need to access the native player.
869status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
870{
871 status_t status;
nikoa64c8c72009-07-20 15:07:26 -0700872 media::Metadata::Filter allow, drop;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700873
Nicolas Catania48290382009-07-10 13:53:06 -0700874 if (unmarshallFilter(filter, &allow, &status) &&
875 unmarshallFilter(filter, &drop, &status)) {
876 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700877
878 mMetadataAllow = allow;
879 mMetadataDrop = drop;
880 }
881 return status;
882}
883
Nicolas Catania48290382009-07-10 13:53:06 -0700884status_t MediaPlayerService::Client::getMetadata(
Mark Salyzyn77342f72014-06-18 16:31:32 -0700885 bool update_only, bool /*apply_filter*/, Parcel *reply)
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700886{
nikoa64c8c72009-07-20 15:07:26 -0700887 sp<MediaPlayerBase> player = getPlayer();
888 if (player == 0) return UNKNOWN_ERROR;
Nicolas Catania48290382009-07-10 13:53:06 -0700889
nikod608a812009-07-16 16:39:53 -0700890 status_t status;
891 // Placeholder for the return code, updated by the caller.
892 reply->writeInt32(-1);
893
nikoa64c8c72009-07-20 15:07:26 -0700894 media::Metadata::Filter ids;
Nicolas Catania48290382009-07-10 13:53:06 -0700895
896 // We don't block notifications while we fetch the data. We clear
897 // mMetadataUpdated first so we don't lose notifications happening
898 // during the rest of this call.
899 {
900 Mutex::Autolock lock(mLock);
901 if (update_only) {
nikod608a812009-07-16 16:39:53 -0700902 ids = mMetadataUpdated;
Nicolas Catania48290382009-07-10 13:53:06 -0700903 }
904 mMetadataUpdated.clear();
905 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700906
nikoa64c8c72009-07-20 15:07:26 -0700907 media::Metadata metadata(reply);
Nicolas Catania48290382009-07-10 13:53:06 -0700908
nikoa64c8c72009-07-20 15:07:26 -0700909 metadata.appendHeader();
910 status = player->getMetadata(ids, reply);
nikod608a812009-07-16 16:39:53 -0700911
912 if (status != OK) {
nikoa64c8c72009-07-20 15:07:26 -0700913 metadata.resetParcel();
Steve Block29357bc2012-01-06 19:20:56 +0000914 ALOGE("getMetadata failed %d", status);
nikod608a812009-07-16 16:39:53 -0700915 return status;
916 }
917
918 // FIXME: Implement filtering on the result. Not critical since
919 // filtering takes place on the update notifications already. This
920 // would be when all the metadata are fetch and a filter is set.
921
nikod608a812009-07-16 16:39:53 -0700922 // Everything is fine, update the metadata length.
nikoa64c8c72009-07-20 15:07:26 -0700923 metadata.updateLength();
nikod608a812009-07-16 16:39:53 -0700924 return OK;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700925}
926
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800927status_t MediaPlayerService::Client::prepareAsync()
928{
Steve Block3856b092011-10-20 11:56:00 +0100929 ALOGV("[%d] prepareAsync", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800930 sp<MediaPlayerBase> p = getPlayer();
931 if (p == 0) return UNKNOWN_ERROR;
932 status_t ret = p->prepareAsync();
933#if CALLBACK_ANTAGONIZER
Steve Blockb8a80522011-12-20 16:23:08 +0000934 ALOGD("start Antagonizer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800935 if (ret == NO_ERROR) mAntagonizer->start();
936#endif
937 return ret;
938}
939
940status_t MediaPlayerService::Client::start()
941{
Steve Block3856b092011-10-20 11:56:00 +0100942 ALOGV("[%d] start", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800943 sp<MediaPlayerBase> p = getPlayer();
944 if (p == 0) return UNKNOWN_ERROR;
945 p->setLooping(mLoop);
946 return p->start();
947}
948
949status_t MediaPlayerService::Client::stop()
950{
Steve Block3856b092011-10-20 11:56:00 +0100951 ALOGV("[%d] stop", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800952 sp<MediaPlayerBase> p = getPlayer();
953 if (p == 0) return UNKNOWN_ERROR;
954 return p->stop();
955}
956
957status_t MediaPlayerService::Client::pause()
958{
Steve Block3856b092011-10-20 11:56:00 +0100959 ALOGV("[%d] pause", mConnId);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800960 sp<MediaPlayerBase> p = getPlayer();
961 if (p == 0) return UNKNOWN_ERROR;
962 return p->pause();
963}
964
965status_t MediaPlayerService::Client::isPlaying(bool* state)
966{
967 *state = false;
968 sp<MediaPlayerBase> p = getPlayer();
969 if (p == 0) return UNKNOWN_ERROR;
970 *state = p->isPlaying();
Steve Block3856b092011-10-20 11:56:00 +0100971 ALOGV("[%d] isPlaying: %d", mConnId, *state);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800972 return NO_ERROR;
973}
974
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700975status_t MediaPlayerService::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
Wei Jia98160162015-02-04 17:01:11 -0800976{
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700977 ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
978 mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Wei Jia98160162015-02-04 17:01:11 -0800979 sp<MediaPlayerBase> p = getPlayer();
980 if (p == 0) return UNKNOWN_ERROR;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700981 return p->setPlaybackSettings(rate);
982}
983
984status_t MediaPlayerService::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
985{
986 sp<MediaPlayerBase> p = getPlayer();
987 if (p == 0) return UNKNOWN_ERROR;
988 status_t ret = p->getPlaybackSettings(rate);
989 if (ret == NO_ERROR) {
990 ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
991 mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
992 } else {
993 ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
994 }
995 return ret;
996}
997
998status_t MediaPlayerService::Client::setSyncSettings(
999 const AVSyncSettings& sync, float videoFpsHint)
1000{
1001 ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
1002 mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
1003 sp<MediaPlayerBase> p = getPlayer();
1004 if (p == 0) return UNKNOWN_ERROR;
1005 return p->setSyncSettings(sync, videoFpsHint);
1006}
1007
1008status_t MediaPlayerService::Client::getSyncSettings(
1009 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
1010{
1011 sp<MediaPlayerBase> p = getPlayer();
1012 if (p == 0) return UNKNOWN_ERROR;
1013 status_t ret = p->getSyncSettings(sync, videoFps);
1014 if (ret == NO_ERROR) {
1015 ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
1016 mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
1017 } else {
1018 ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
1019 }
1020 return ret;
Wei Jia98160162015-02-04 17:01:11 -08001021}
1022
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001023status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
1024{
Steve Block3856b092011-10-20 11:56:00 +01001025 ALOGV("getCurrentPosition");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001026 sp<MediaPlayerBase> p = getPlayer();
1027 if (p == 0) return UNKNOWN_ERROR;
1028 status_t ret = p->getCurrentPosition(msec);
1029 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001030 ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001031 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001032 ALOGE("getCurrentPosition returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001033 }
1034 return ret;
1035}
1036
1037status_t MediaPlayerService::Client::getDuration(int *msec)
1038{
Steve Block3856b092011-10-20 11:56:00 +01001039 ALOGV("getDuration");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001040 sp<MediaPlayerBase> p = getPlayer();
1041 if (p == 0) return UNKNOWN_ERROR;
1042 status_t ret = p->getDuration(msec);
1043 if (ret == NO_ERROR) {
Steve Block3856b092011-10-20 11:56:00 +01001044 ALOGV("[%d] getDuration = %d", mConnId, *msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001045 } else {
Steve Block29357bc2012-01-06 19:20:56 +00001046 ALOGE("getDuration returned %d", ret);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001047 }
1048 return ret;
1049}
1050
Marco Nelissen6b74d672012-02-28 16:07:44 -08001051status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
1052 ALOGV("setNextPlayer");
1053 Mutex::Autolock l(mLock);
1054 sp<Client> c = static_cast<Client*>(player.get());
1055 mNextClient = c;
John Grossman5f7e55e2012-08-24 14:47:25 -07001056
1057 if (c != NULL) {
1058 if (mAudioOutput != NULL) {
1059 mAudioOutput->setNextOutput(c->mAudioOutput);
1060 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
1061 ALOGE("no current audio output");
1062 }
1063
1064 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
1065 mPlayer->setNextPlayer(mNextClient->getPlayer());
1066 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001067 }
John Grossman5f7e55e2012-08-24 14:47:25 -07001068
Marco Nelissen6b74d672012-02-28 16:07:44 -08001069 return OK;
1070}
1071
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001072status_t MediaPlayerService::Client::seekTo(int msec)
1073{
Steve Block3856b092011-10-20 11:56:00 +01001074 ALOGV("[%d] seekTo(%d)", mConnId, msec);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001075 sp<MediaPlayerBase> p = getPlayer();
1076 if (p == 0) return UNKNOWN_ERROR;
1077 return p->seekTo(msec);
1078}
1079
1080status_t MediaPlayerService::Client::reset()
1081{
Steve Block3856b092011-10-20 11:56:00 +01001082 ALOGV("[%d] reset", mConnId);
John Grossmanc795b642012-02-22 15:38:35 -08001083 mRetransmitEndpointValid = false;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001084 sp<MediaPlayerBase> p = getPlayer();
1085 if (p == 0) return UNKNOWN_ERROR;
1086 return p->reset();
1087}
1088
Glenn Kastenfff6d712012-01-12 16:38:12 -08001089status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001090{
Steve Block3856b092011-10-20 11:56:00 +01001091 ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001092 // TODO: for hardware output, call player instead
1093 Mutex::Autolock l(mLock);
1094 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1095 return NO_ERROR;
1096}
1097
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001098status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
1099{
1100 if (mAudioAttributes != NULL) { free(mAudioAttributes); }
1101 mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001102 if (mAudioAttributes == NULL) {
1103 return NO_MEMORY;
1104 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001105 unmarshallAudioAttributes(parcel, mAudioAttributes);
1106
1107 ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
1108 mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
1109 mAudioAttributes->tags);
1110
1111 if (mAudioOutput != 0) {
1112 mAudioOutput->setAudioAttributes(mAudioAttributes);
1113 }
1114 return NO_ERROR;
1115}
1116
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001117status_t MediaPlayerService::Client::setLooping(int loop)
1118{
Steve Block3856b092011-10-20 11:56:00 +01001119 ALOGV("[%d] setLooping(%d)", mConnId, loop);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001120 mLoop = loop;
1121 sp<MediaPlayerBase> p = getPlayer();
1122 if (p != 0) return p->setLooping(loop);
1123 return NO_ERROR;
1124}
1125
1126status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1127{
Steve Block3856b092011-10-20 11:56:00 +01001128 ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
John Grossman761defc2012-02-09 15:09:05 -08001129
1130 // for hardware output, call player instead
1131 sp<MediaPlayerBase> p = getPlayer();
1132 {
1133 Mutex::Autolock l(mLock);
1134 if (p != 0 && p->hardwareOutput()) {
1135 MediaPlayerHWInterface* hwp =
1136 reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1137 return hwp->setVolume(leftVolume, rightVolume);
1138 } else {
1139 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1140 return NO_ERROR;
1141 }
1142 }
1143
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001144 return NO_ERROR;
1145}
1146
Eric Laurent2beeb502010-07-16 07:43:46 -07001147status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1148{
Steve Block3856b092011-10-20 11:56:00 +01001149 ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
Eric Laurent2beeb502010-07-16 07:43:46 -07001150 Mutex::Autolock l(mLock);
1151 if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1152 return NO_ERROR;
1153}
1154
1155status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1156{
Steve Block3856b092011-10-20 11:56:00 +01001157 ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
Eric Laurent2beeb502010-07-16 07:43:46 -07001158 Mutex::Autolock l(mLock);
1159 if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1160 return NO_ERROR;
1161}
Nicolas Catania48290382009-07-10 13:53:06 -07001162
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001163status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
Steve Block3856b092011-10-20 11:56:00 +01001164 ALOGV("[%d] setParameter(%d)", mConnId, key);
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001165 switch (key) {
1166 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
1167 {
1168 Mutex::Autolock l(mLock);
1169 return setAudioAttributes_l(request);
1170 }
1171 default:
1172 sp<MediaPlayerBase> p = getPlayer();
1173 if (p == 0) { return UNKNOWN_ERROR; }
1174 return p->setParameter(key, request);
1175 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001176}
1177
1178status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
Steve Block3856b092011-10-20 11:56:00 +01001179 ALOGV("[%d] getParameter(%d)", mConnId, key);
Gloria Wang4f9e47f2011-04-25 17:28:22 -07001180 sp<MediaPlayerBase> p = getPlayer();
1181 if (p == 0) return UNKNOWN_ERROR;
1182 return p->getParameter(key, reply);
1183}
1184
John Grossmanc795b642012-02-22 15:38:35 -08001185status_t MediaPlayerService::Client::setRetransmitEndpoint(
1186 const struct sockaddr_in* endpoint) {
1187
1188 if (NULL != endpoint) {
1189 uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1190 uint16_t p = ntohs(endpoint->sin_port);
1191 ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1192 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1193 } else {
1194 ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1195 }
1196
1197 sp<MediaPlayerBase> p = getPlayer();
1198
1199 // Right now, the only valid time to set a retransmit endpoint is before
1200 // player selection has been made (since the presence or absence of a
1201 // retransmit endpoint is going to determine which player is selected during
1202 // setDataSource).
1203 if (p != 0) return INVALID_OPERATION;
1204
1205 if (NULL != endpoint) {
1206 mRetransmitEndpoint = *endpoint;
1207 mRetransmitEndpointValid = true;
1208 } else {
1209 mRetransmitEndpointValid = false;
1210 }
1211
1212 return NO_ERROR;
1213}
1214
John Grossman44a7e422012-06-21 17:29:24 -07001215status_t MediaPlayerService::Client::getRetransmitEndpoint(
1216 struct sockaddr_in* endpoint)
1217{
1218 if (NULL == endpoint)
1219 return BAD_VALUE;
1220
1221 sp<MediaPlayerBase> p = getPlayer();
1222
1223 if (p != NULL)
1224 return p->getRetransmitEndpoint(endpoint);
1225
1226 if (!mRetransmitEndpointValid)
1227 return NO_INIT;
1228
1229 *endpoint = mRetransmitEndpoint;
1230
1231 return NO_ERROR;
1232}
1233
Gloria Wangb483c472011-04-11 17:23:27 -07001234void MediaPlayerService::Client::notify(
1235 void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001236{
1237 Client* client = static_cast<Client*>(cookie);
James Dongb8a98252012-08-26 16:13:03 -07001238 if (client == NULL) {
1239 return;
1240 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001241
James Dongb8a98252012-08-26 16:13:03 -07001242 sp<IMediaPlayerClient> c;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001243 {
1244 Mutex::Autolock l(client->mLock);
James Dongb8a98252012-08-26 16:13:03 -07001245 c = client->mClient;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001246 if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
John Grossmancb0b7552012-08-23 17:47:31 -07001247 if (client->mAudioOutput != NULL)
1248 client->mAudioOutput->switchToNextOutput();
Marco Nelissen6b74d672012-02-28 16:07:44 -08001249 client->mNextClient->start();
Wei Jia2afac0c2016-01-07 12:13:07 -08001250 if (client->mNextClient->mClient != NULL) {
1251 client->mNextClient->mClient->notify(
1252 MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1253 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08001254 }
1255 }
1256
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001257 if (MEDIA_INFO == msg &&
Nicolas Catania48290382009-07-10 13:53:06 -07001258 MEDIA_INFO_METADATA_UPDATE == ext1) {
nikoa64c8c72009-07-20 15:07:26 -07001259 const media::Metadata::Type metadata_type = ext2;
Nicolas Catania48290382009-07-10 13:53:06 -07001260
1261 if(client->shouldDropMetadata(metadata_type)) {
1262 return;
1263 }
1264
1265 // Update the list of metadata that have changed. getMetadata
1266 // also access mMetadataUpdated and clears it.
1267 client->addNewMetadataUpdate(metadata_type);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001268 }
James Dongb8a98252012-08-26 16:13:03 -07001269
1270 if (c != NULL) {
1271 ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1272 c->notify(msg, ext1, ext2, obj);
1273 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001274}
1275
Nicolas Catania48290382009-07-10 13:53:06 -07001276
nikoa64c8c72009-07-20 15:07:26 -07001277bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001278{
Nicolas Catania48290382009-07-10 13:53:06 -07001279 Mutex::Autolock lock(mLock);
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001280
Nicolas Catania48290382009-07-10 13:53:06 -07001281 if (findMetadata(mMetadataDrop, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001282 return true;
1283 }
1284
Nicolas Catania48290382009-07-10 13:53:06 -07001285 if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001286 return false;
Nicolas Catania48290382009-07-10 13:53:06 -07001287 } else {
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -07001288 return true;
1289 }
1290}
1291
Nicolas Catania48290382009-07-10 13:53:06 -07001292
nikoa64c8c72009-07-20 15:07:26 -07001293void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Nicolas Catania48290382009-07-10 13:53:06 -07001294 Mutex::Autolock lock(mLock);
1295 if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1296 mMetadataUpdated.add(metadata_type);
1297 }
1298}
1299
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001300#if CALLBACK_ANTAGONIZER
1301const int Antagonizer::interval = 10000; // 10 msecs
1302
1303Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1304 mExit(false), mActive(false), mClient(client), mCb(cb)
1305{
1306 createThread(callbackThread, this);
1307}
1308
1309void Antagonizer::kill()
1310{
1311 Mutex::Autolock _l(mLock);
1312 mActive = false;
1313 mExit = true;
1314 mCondition.wait(mLock);
1315}
1316
1317int Antagonizer::callbackThread(void* user)
1318{
Steve Blockb8a80522011-12-20 16:23:08 +00001319 ALOGD("Antagonizer started");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001320 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1321 while (!p->mExit) {
1322 if (p->mActive) {
Steve Block3856b092011-10-20 11:56:00 +01001323 ALOGV("send event");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001324 p->mCb(p->mClient, 0, 0, 0);
1325 }
1326 usleep(interval);
1327 }
1328 Mutex::Autolock _l(p->mLock);
1329 p->mCondition.signal();
Steve Blockb8a80522011-12-20 16:23:08 +00001330 ALOGD("Antagonizer stopped");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001331 return 0;
1332}
1333#endif
1334
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001335#undef LOG_TAG
1336#define LOG_TAG "AudioSink"
Glenn Kastend848eb42016-03-08 13:42:11 -08001337MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, int uid, int pid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001338 const audio_attributes_t* attr)
Andreas Huber20111aa2009-07-14 16:56:47 -07001339 : mCallback(NULL),
Eric Laurenta514bdb2010-06-21 09:27:30 -07001340 mCallbackCookie(NULL),
Marco Nelissen6b74d672012-02-28 16:07:44 -08001341 mCallbackData(NULL),
Andy Hungd1c74342015-07-07 16:54:23 -07001342 mStreamType(AUDIO_STREAM_MUSIC),
Andy Hungd1c74342015-07-07 16:54:23 -07001343 mLeftVolume(1.0),
1344 mRightVolume(1.0),
1345 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
1346 mSampleRateHz(0),
1347 mMsecsPerFrame(0),
1348 mFrameSize(0),
Eric Laurent1948eb32012-04-13 16:50:19 -07001349 mSessionId(sessionId),
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001350 mUid(uid),
Marco Nelissend457c972014-02-11 08:47:07 -08001351 mPid(pid),
Andy Hungd1c74342015-07-07 16:54:23 -07001352 mSendLevel(0.0),
1353 mAuxEffectId(0),
1354 mFlags(AUDIO_OUTPUT_FLAG_NONE)
1355{
Steve Block3856b092011-10-20 11:56:00 +01001356 ALOGV("AudioOutput(%d)", sessionId);
Eric Laurent43562692015-07-15 16:49:07 -07001357 if (attr != NULL) {
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001358 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1359 if (mAttributes != NULL) {
1360 memcpy(mAttributes, attr, sizeof(audio_attributes_t));
1361 mStreamType = audio_attributes_to_stream_type(attr);
1362 }
1363 } else {
1364 mAttributes = NULL;
Eric Laurent43562692015-07-15 16:49:07 -07001365 }
1366
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001367 setMinBufferCount();
1368}
1369
1370MediaPlayerService::AudioOutput::~AudioOutput()
1371{
1372 close();
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001373 free(mAttributes);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001374 delete mCallbackData;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001375}
1376
Andy Hungd1c74342015-07-07 16:54:23 -07001377//static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001378void MediaPlayerService::AudioOutput::setMinBufferCount()
1379{
1380 char value[PROPERTY_VALUE_MAX];
1381 if (property_get("ro.kernel.qemu", value, 0)) {
1382 mIsOnEmulator = true;
1383 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
1384 }
1385}
1386
Andy Hungd1c74342015-07-07 16:54:23 -07001387// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001388bool MediaPlayerService::AudioOutput::isOnEmulator()
1389{
Andy Hungd1c74342015-07-07 16:54:23 -07001390 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001391 return mIsOnEmulator;
1392}
1393
Andy Hungd1c74342015-07-07 16:54:23 -07001394// static
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001395int MediaPlayerService::AudioOutput::getMinBufferCount()
1396{
Andy Hungd1c74342015-07-07 16:54:23 -07001397 setMinBufferCount(); // benign race wrt other threads
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001398 return mMinBufferCount;
1399}
1400
1401ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1402{
Andy Hungd1c74342015-07-07 16:54:23 -07001403 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001404 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001405 return mTrack->frameCount() * mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001406}
1407
1408ssize_t MediaPlayerService::AudioOutput::frameCount() const
1409{
Andy Hungd1c74342015-07-07 16:54:23 -07001410 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001411 if (mTrack == 0) return NO_INIT;
1412 return mTrack->frameCount();
1413}
1414
1415ssize_t MediaPlayerService::AudioOutput::channelCount() const
1416{
Andy Hungd1c74342015-07-07 16:54:23 -07001417 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001418 if (mTrack == 0) return NO_INIT;
1419 return mTrack->channelCount();
1420}
1421
1422ssize_t MediaPlayerService::AudioOutput::frameSize() const
1423{
Andy Hungd1c74342015-07-07 16:54:23 -07001424 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001425 if (mTrack == 0) return NO_INIT;
Andy Hungd1c74342015-07-07 16:54:23 -07001426 return mFrameSize;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001427}
1428
1429uint32_t MediaPlayerService::AudioOutput::latency () const
1430{
Andy Hungd1c74342015-07-07 16:54:23 -07001431 Mutex::Autolock lock(mLock);
Eric Laurentdb354e52012-03-05 17:27:11 -08001432 if (mTrack == 0) return 0;
1433 return mTrack->latency();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001434}
1435
1436float MediaPlayerService::AudioOutput::msecsPerFrame() 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 return mMsecsPerFrame;
1440}
1441
Marco Nelissen4110c102012-03-29 09:31:28 -07001442status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
Eric Laurent342e9cf2010-01-19 17:37:09 -08001443{
Andy Hungd1c74342015-07-07 16:54:23 -07001444 Mutex::Autolock lock(mLock);
Eric Laurent342e9cf2010-01-19 17:37:09 -08001445 if (mTrack == 0) return NO_INIT;
1446 return mTrack->getPosition(position);
1447}
1448
Lajos Molnar06ad1522014-08-28 07:27:44 -07001449status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const
1450{
Andy Hungd1c74342015-07-07 16:54:23 -07001451 Mutex::Autolock lock(mLock);
Lajos Molnar06ad1522014-08-28 07:27:44 -07001452 if (mTrack == 0) return NO_INIT;
1453 return mTrack->getTimestamp(ts);
1454}
1455
Wei Jiac4ac8172015-10-21 10:35:48 -07001456// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
1457// as it acquires locks and may query the audio driver.
1458//
1459// Some calls could conceivably retrieve extrapolated data instead of
1460// accessing getTimestamp() or getPosition() every time a data buffer with
1461// a media time is received.
1462//
1463// Calculate duration of played samples if played at normal rate (i.e., 1.0).
1464int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const
1465{
1466 Mutex::Autolock lock(mLock);
1467 if (mTrack == 0 || mSampleRateHz == 0) {
Wei Jia213f4902015-10-22 08:55:25 -07001468 return 0;
Wei Jiac4ac8172015-10-21 10:35:48 -07001469 }
1470
1471 uint32_t numFramesPlayed;
1472 int64_t numFramesPlayedAt;
1473 AudioTimestamp ts;
1474 static const int64_t kStaleTimestamp100ms = 100000;
1475
1476 status_t res = mTrack->getTimestamp(ts);
1477 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
1478 numFramesPlayed = ts.mPosition;
1479 numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
1480 const int64_t timestampAge = nowUs - numFramesPlayedAt;
1481 if (timestampAge > kStaleTimestamp100ms) {
1482 // This is an audio FIXME.
1483 // getTimestamp returns a timestamp which may come from audio mixing threads.
1484 // After pausing, the MixerThread may go idle, thus the mTime estimate may
1485 // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms,
1486 // the max latency should be about 25ms with an average around 12ms (to be verified).
1487 // For safety we use 100ms.
1488 ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)",
1489 (long long)nowUs, (long long)numFramesPlayedAt);
1490 numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
1491 }
1492 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1493 } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
1494 numFramesPlayed = 0;
1495 numFramesPlayedAt = nowUs;
1496 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
1497 // numFramesPlayed, (long long)numFramesPlayedAt);
1498 } else { // case 3: transitory at new track or audio fast tracks.
1499 res = mTrack->getPosition(&numFramesPlayed);
1500 CHECK_EQ(res, (status_t)OK);
1501 numFramesPlayedAt = nowUs;
1502 numFramesPlayedAt += 1000LL * mTrack->latency() / 2; /* XXX */
1503 //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt);
1504 }
1505
1506 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
1507 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1508 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
1509 + nowUs - numFramesPlayedAt;
1510 if (durationUs < 0) {
1511 // Occurs when numFramesPlayed position is very small and the following:
1512 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
1513 // numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed.
1514 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
1515 // numFramesPlayedAt, by a time amount greater than numFramesPlayed.
1516 //
1517 // Both of these are transitory conditions.
1518 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
1519 durationUs = 0;
1520 }
1521 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
1522 (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt);
1523 return durationUs;
1524}
1525
Marco Nelissen4110c102012-03-29 09:31:28 -07001526status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1527{
Andy Hungd1c74342015-07-07 16:54:23 -07001528 Mutex::Autolock lock(mLock);
Marco Nelissen4110c102012-03-29 09:31:28 -07001529 if (mTrack == 0) return NO_INIT;
Andy Hung2f6e73d2016-04-08 12:12:58 -07001530 ExtendedTimestamp ets;
1531 status_t status = mTrack->getTimestamp(&ets);
1532 if (status == OK || status == WOULD_BLOCK) {
1533 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
1534 }
1535 return status;
Marco Nelissen4110c102012-03-29 09:31:28 -07001536}
1537
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001538status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
1539{
Andy Hungd1c74342015-07-07 16:54:23 -07001540 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001541 if (mTrack == 0) return NO_INIT;
1542 return mTrack->setParameters(keyValuePairs);
1543}
1544
1545String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
1546{
Andy Hungd1c74342015-07-07 16:54:23 -07001547 Mutex::Autolock lock(mLock);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001548 if (mTrack == 0) return String8::empty();
1549 return mTrack->getParameters(keys);
1550}
1551
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001552void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
Andy Hungd1c74342015-07-07 16:54:23 -07001553 Mutex::Autolock lock(mLock);
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001554 if (attributes == NULL) {
1555 free(mAttributes);
1556 mAttributes = NULL;
1557 } else {
1558 if (mAttributes == NULL) {
1559 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1560 }
1561 memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
Eric Laurent43562692015-07-15 16:49:07 -07001562 mStreamType = audio_attributes_to_stream_type(attributes);
1563 }
1564}
1565
1566void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
1567{
Jean-Michel Trivi2650e962015-07-22 18:14:02 -07001568 Mutex::Autolock lock(mLock);
Eric Laurent43562692015-07-15 16:49:07 -07001569 // do not allow direct stream type modification if attributes have been set
1570 if (mAttributes == NULL) {
1571 mStreamType = streamType;
1572 }
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001573}
1574
Andy Hungd1c74342015-07-07 16:54:23 -07001575void MediaPlayerService::AudioOutput::deleteRecycledTrack_l()
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001576{
Andy Hungd1c74342015-07-07 16:54:23 -07001577 ALOGV("deleteRecycledTrack_l");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001578 if (mRecycledTrack != 0) {
1579
1580 if (mCallbackData != NULL) {
1581 mCallbackData->setOutput(NULL);
1582 mCallbackData->endTrackSwitch();
1583 }
1584
1585 if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
Andy Hunge13f8a62016-03-30 14:20:42 -07001586 int32_t msec = 0;
1587 if (!mRecycledTrack->stopped()) { // check if active
1588 (void)mRecycledTrack->pendingDuration(&msec);
1589 }
1590 mRecycledTrack->stop(); // ensure full data drain
1591 ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
1592 if (msec > 0) {
1593 static const int32_t WAIT_LIMIT_MS = 3000;
1594 if (msec > WAIT_LIMIT_MS) {
1595 msec = WAIT_LIMIT_MS;
1596 }
1597 usleep(msec * 1000LL);
1598 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001599 }
1600 // An offloaded track isn't flushed because the STREAM_END is reported
1601 // slightly prematurely to allow time for the gapless track switch
1602 // but this means that if we decide not to recycle the track there
1603 // could be a small amount of residual data still playing. We leave
1604 // AudioFlinger to drain the track.
1605
1606 mRecycledTrack.clear();
Andy Hungd1c74342015-07-07 16:54:23 -07001607 close_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001608 delete mCallbackData;
1609 mCallbackData = NULL;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001610 }
1611}
1612
Andy Hungd1c74342015-07-07 16:54:23 -07001613void MediaPlayerService::AudioOutput::close_l()
1614{
1615 mTrack.clear();
1616}
1617
Andreas Huber20111aa2009-07-14 16:56:47 -07001618status_t MediaPlayerService::AudioOutput::open(
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001619 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
1620 audio_format_t format, int bufferCount,
Eric Laurent1948eb32012-04-13 16:50:19 -07001621 AudioCallback cb, void *cookie,
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00001622 audio_output_flags_t flags,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001623 const audio_offload_info_t *offloadInfo,
Andy Hung179652e2015-05-31 22:49:46 -07001624 bool doNotReconnect,
1625 uint32_t suggestedFrameCount)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001626{
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001627 ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
1628 format, bufferCount, mSessionId, flags);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001629
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001630 // offloading is only supported in callback mode for now.
1631 // offloadInfo must be present if offload flag is set
1632 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
1633 ((cb == NULL) || (offloadInfo == NULL))) {
1634 return BAD_VALUE;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001635 }
1636
Andy Hung179652e2015-05-31 22:49:46 -07001637 // compute frame count for the AudioTrack internal buffer
1638 size_t frameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001639 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1640 frameCount = 0; // AudioTrack will get frame count from AudioFlinger
1641 } else {
Andy Hung179652e2015-05-31 22:49:46 -07001642 // try to estimate the buffer processing fetch size from AudioFlinger.
1643 // framesPerBuffer is approximate and generally correct, except when it's not :-).
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001644 uint32_t afSampleRate;
1645 size_t afFrameCount;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001646 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1647 return NO_INIT;
1648 }
1649 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1650 return NO_INIT;
1651 }
Andy Hung179652e2015-05-31 22:49:46 -07001652 const size_t framesPerBuffer =
1653 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001654
Andy Hung179652e2015-05-31 22:49:46 -07001655 if (bufferCount == 0) {
1656 // use suggestedFrameCount
1657 bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
1658 }
1659 // Check argument bufferCount against the mininum buffer count
1660 if (bufferCount != 0 && bufferCount < mMinBufferCount) {
1661 ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
1662 bufferCount = mMinBufferCount;
1663 }
1664 // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
1665 // which will be the minimum size permitted.
1666 frameCount = bufferCount * framesPerBuffer;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001667 }
Andreas Huber20111aa2009-07-14 16:56:47 -07001668
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001669 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
Glenn Kastenab334fd2012-03-14 12:56:06 -07001670 channelMask = audio_channel_out_mask_from_count(channelCount);
Jean-Michel Trivi786618f2012-03-02 14:54:07 -08001671 if (0 == channelMask) {
1672 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
1673 return NO_INIT;
1674 }
1675 }
Eric Laurent1948eb32012-04-13 16:50:19 -07001676
Andy Hungd1c74342015-07-07 16:54:23 -07001677 Mutex::Autolock lock(mLock);
Andy Hung179652e2015-05-31 22:49:46 -07001678 mCallback = cb;
1679 mCallbackCookie = cookie;
1680
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001681 // Check whether we can recycle the track
1682 bool reuse = false;
1683 bool bothOffloaded = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001684
Glenn Kasten2799d742013-05-30 14:33:29 -07001685 if (mRecycledTrack != 0) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001686 // check whether we are switching between two offloaded tracks
1687 bothOffloaded = (flags & mRecycledTrack->getFlags()
1688 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
Marco Nelissen67295b52012-06-11 14:52:53 -07001689
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001690 // check if the existing track can be reused as-is, or if a new track needs to be created.
1691 reuse = true;
1692
Marco Nelissen67295b52012-06-11 14:52:53 -07001693 if ((mCallbackData == NULL && mCallback != NULL) ||
1694 (mCallbackData != NULL && mCallback == NULL)) {
1695 // recycled track uses callbacks but the caller wants to use writes, or vice versa
1696 ALOGV("can't chain callback and write");
1697 reuse = false;
1698 } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001699 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
1700 ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
Marco Nelissen67295b52012-06-11 14:52:53 -07001701 mRecycledTrack->getSampleRate(), sampleRate,
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001702 mRecycledTrack->channelCount(), channelCount);
Marco Nelissen67295b52012-06-11 14:52:53 -07001703 reuse = false;
1704 } else if (flags != mFlags) {
1705 ALOGV("output flags differ %08x/%08x", flags, mFlags);
1706 reuse = false;
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001707 } else if (mRecycledTrack->format() != format) {
1708 reuse = false;
Marco Nelissen67295b52012-06-11 14:52:53 -07001709 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001710 } else {
1711 ALOGV("no track available to recycle");
1712 }
1713
1714 ALOGV_IF(bothOffloaded, "both tracks offloaded");
1715
1716 // If we can't recycle and both tracks are offloaded
1717 // we must close the previous output before opening a new one
1718 if (bothOffloaded && !reuse) {
1719 ALOGV("both offloaded and not recycling");
Andy Hungd1c74342015-07-07 16:54:23 -07001720 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001721 }
1722
1723 sp<AudioTrack> t;
1724 CallbackData *newcbd = NULL;
1725
1726 // We don't attempt to create a new track if we are recycling an
1727 // offloaded track. But, if we are recycling a non-offloaded or we
1728 // are switching where one is offloaded and one isn't then we create
1729 // the new track in advance so that we can read additional stream info
1730
1731 if (!(reuse && bothOffloaded)) {
1732 ALOGV("creating new AudioTrack");
1733
1734 if (mCallback != NULL) {
1735 newcbd = new CallbackData(this);
1736 t = new AudioTrack(
1737 mStreamType,
1738 sampleRate,
1739 format,
1740 channelMask,
1741 frameCount,
1742 flags,
1743 CallbackWrapper,
1744 newcbd,
1745 0, // notification frames
1746 mSessionId,
1747 AudioTrack::TRANSFER_CALLBACK,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001748 offloadInfo,
Marco Nelissend457c972014-02-11 08:47:07 -08001749 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001750 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001751 mAttributes,
1752 doNotReconnect);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001753 } else {
Andy Hungff874dc2016-04-11 16:49:09 -07001754 // TODO: Due to buffer memory concerns, we use a max target playback speed
1755 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
1756 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
1757 const float targetSpeed =
1758 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
1759 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
1760 "track target speed:%f clamped from playback speed:%f",
1761 targetSpeed, mPlaybackRate.mSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001762 t = new AudioTrack(
1763 mStreamType,
1764 sampleRate,
1765 format,
1766 channelMask,
1767 frameCount,
1768 flags,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08001769 NULL, // callback
1770 NULL, // user data
1771 0, // notification frames
1772 mSessionId,
1773 AudioTrack::TRANSFER_DEFAULT,
1774 NULL, // offload info
Marco Nelissend457c972014-02-11 08:47:07 -08001775 mUid,
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001776 mPid,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001777 mAttributes,
Andy Hungff874dc2016-04-11 16:49:09 -07001778 doNotReconnect,
1779 targetSpeed);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001780 }
1781
1782 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1783 ALOGE("Unable to create audio track");
1784 delete newcbd;
Glenn Kasten3e98ecd2015-05-18 13:13:24 -07001785 // t goes out of scope, so reference count drops to zero
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001786 return NO_INIT;
Jean-Michel Trivid9d7fa02014-06-24 08:01:46 -07001787 } else {
1788 // successful AudioTrack initialization implies a legacy stream type was generated
1789 // from the audio attributes
1790 mStreamType = t->streamType();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001791 }
1792 }
1793
1794 if (reuse) {
1795 CHECK(mRecycledTrack != NULL);
1796
1797 if (!bothOffloaded) {
1798 if (mRecycledTrack->frameCount() != t->frameCount()) {
Andy Hung833b4752016-04-04 17:15:48 -07001799 ALOGV("framecount differs: %zu/%zu frames",
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001800 mRecycledTrack->frameCount(), t->frameCount());
1801 reuse = false;
1802 }
1803 }
1804
Marco Nelissen67295b52012-06-11 14:52:53 -07001805 if (reuse) {
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001806 ALOGV("chaining to next output and recycling track");
Andy Hungd1c74342015-07-07 16:54:23 -07001807 close_l();
Marco Nelissen67295b52012-06-11 14:52:53 -07001808 mTrack = mRecycledTrack;
Glenn Kasten2799d742013-05-30 14:33:29 -07001809 mRecycledTrack.clear();
Marco Nelissen67295b52012-06-11 14:52:53 -07001810 if (mCallbackData != NULL) {
1811 mCallbackData->setOutput(this);
1812 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001813 delete newcbd;
1814 return OK;
1815 }
Marco Nelissen67295b52012-06-11 14:52:53 -07001816 }
1817
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001818 // we're not going to reuse the track, unblock and flush it
1819 // this was done earlier if both tracks are offloaded
1820 if (!bothOffloaded) {
Andy Hungd1c74342015-07-07 16:54:23 -07001821 deleteRecycledTrack_l();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001822 }
1823
1824 CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
1825
Marco Nelissen67295b52012-06-11 14:52:53 -07001826 mCallbackData = newcbd;
Steve Block3856b092011-10-20 11:56:00 +01001827 ALOGV("setVolume");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001828 t->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001829
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001830 mSampleRateHz = sampleRate;
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001831 mFlags = flags;
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001832 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Andy Hungd1c74342015-07-07 16:54:23 -07001833 mFrameSize = t->frameSize();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001834 mTrack = t;
Eric Laurent2beeb502010-07-16 07:43:46 -07001835
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001836 status_t res = NO_ERROR;
Wei Jia0162d002015-06-09 11:59:33 -07001837 // Note some output devices may give us a direct track even though we don't specify it.
1838 // Example: Line application b/17459982.
Preetam Singh Ranawat2e17eef2015-08-12 12:11:46 -07001839 if ((t->getFlags() & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001840 res = t->setPlaybackRate(mPlaybackRate);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001841 if (res == NO_ERROR) {
1842 t->setAuxEffectSendLevel(mSendLevel);
1843 res = t->attachAuxEffect(mAuxEffectId);
1844 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08001845 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001846 ALOGV("open() DONE status %d", res);
1847 return res;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001848}
1849
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001850status_t MediaPlayerService::AudioOutput::start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001851{
Steve Block3856b092011-10-20 11:56:00 +01001852 ALOGV("start");
Andy Hungd1c74342015-07-07 16:54:23 -07001853 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001854 if (mCallbackData != NULL) {
1855 mCallbackData->endTrackSwitch();
1856 }
Glenn Kasten2799d742013-05-30 14:33:29 -07001857 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001858 mTrack->setVolume(mLeftVolume, mRightVolume);
Eric Laurent2beeb502010-07-16 07:43:46 -07001859 mTrack->setAuxEffectSendLevel(mSendLevel);
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001860 return mTrack->start();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001861 }
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01001862 return NO_INIT;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001863}
1864
Marco Nelissen6b74d672012-02-28 16:07:44 -08001865void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
Andy Hungd1c74342015-07-07 16:54:23 -07001866 Mutex::Autolock lock(mLock);
Marco Nelissen6b74d672012-02-28 16:07:44 -08001867 mNextOutput = nextOutput;
1868}
Marco Nelissen7ee8ac92010-01-12 09:23:54 -08001869
Marco Nelissen6b74d672012-02-28 16:07:44 -08001870void MediaPlayerService::AudioOutput::switchToNextOutput() {
1871 ALOGV("switchToNextOutput");
Andy Hungd1c74342015-07-07 16:54:23 -07001872
1873 // Try to acquire the callback lock before moving track (without incurring deadlock).
1874 const unsigned kMaxSwitchTries = 100;
1875 Mutex::Autolock lock(mLock);
1876 for (unsigned tries = 0;;) {
1877 if (mTrack == 0) {
1878 return;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001879 }
Andy Hungd1c74342015-07-07 16:54:23 -07001880 if (mNextOutput != NULL && mNextOutput != this) {
1881 if (mCallbackData != NULL) {
1882 // two alternative approaches
1883#if 1
1884 CallbackData *callbackData = mCallbackData;
1885 mLock.unlock();
1886 // proper acquisition sequence
1887 callbackData->lock();
1888 mLock.lock();
1889 // Caution: it is unlikely that someone deleted our callback or changed our target
1890 if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
1891 // fatal if we are starved out.
1892 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1893 "switchToNextOutput() cannot obtain correct lock sequence");
1894 callbackData->unlock();
1895 continue;
1896 }
1897 callbackData->mSwitching = true; // begin track switch
1898#else
1899 // tryBeginTrackSwitch() returns false if the callback has the lock.
1900 if (!mCallbackData->tryBeginTrackSwitch()) {
1901 // fatal if we are starved out.
1902 LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
1903 "switchToNextOutput() cannot obtain callback lock");
1904 mLock.unlock();
1905 usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
1906 mLock.lock();
1907 continue;
1908 }
1909#endif
1910 }
1911
1912 Mutex::Autolock nextLock(mNextOutput->mLock);
1913
1914 // If the next output track is not NULL, then it has been
1915 // opened already for playback.
1916 // This is possible even without the next player being started,
1917 // for example, the next player could be prepared and seeked.
1918 //
1919 // Presuming it isn't advisable to force the track over.
1920 if (mNextOutput->mTrack == NULL) {
1921 ALOGD("Recycling track for gapless playback");
1922 delete mNextOutput->mCallbackData;
1923 mNextOutput->mCallbackData = mCallbackData;
1924 mNextOutput->mRecycledTrack = mTrack;
1925 mNextOutput->mSampleRateHz = mSampleRateHz;
1926 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
Andy Hungd1c74342015-07-07 16:54:23 -07001927 mNextOutput->mFlags = mFlags;
1928 mNextOutput->mFrameSize = mFrameSize;
1929 close_l();
1930 mCallbackData = NULL; // destruction handled by mNextOutput
1931 } else {
1932 ALOGW("Ignoring gapless playback because next player has already started");
1933 // remove track in case resource needed for future players.
1934 if (mCallbackData != NULL) {
1935 mCallbackData->endTrackSwitch(); // release lock for callbacks before close.
1936 }
1937 close_l();
1938 }
1939 }
1940 break;
Marco Nelissen6b74d672012-02-28 16:07:44 -08001941 }
1942}
1943
Wei Jia7d3f4df2015-03-03 15:28:00 -08001944ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001945{
Andy Hungd1c74342015-07-07 16:54:23 -07001946 Mutex::Autolock lock(mLock);
Glenn Kastenadad3d72014-02-21 14:51:43 -08001947 LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
Andreas Huber20111aa2009-07-14 16:56:47 -07001948
Steve Block3856b092011-10-20 11:56:00 +01001949 //ALOGV("write(%p, %u)", buffer, size);
Glenn Kasten2799d742013-05-30 14:33:29 -07001950 if (mTrack != 0) {
Andy Hung2f6e73d2016-04-08 12:12:58 -07001951 return mTrack->write(buffer, size, blocking);
Marco Nelissen10dbb8e2009-09-20 10:42:13 -07001952 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001953 return NO_INIT;
1954}
1955
1956void MediaPlayerService::AudioOutput::stop()
1957{
Steve Block3856b092011-10-20 11:56:00 +01001958 ALOGV("stop");
Andy Hungd1c74342015-07-07 16:54:23 -07001959 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001960 if (mTrack != 0) mTrack->stop();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001961}
1962
1963void MediaPlayerService::AudioOutput::flush()
1964{
Steve Block3856b092011-10-20 11:56:00 +01001965 ALOGV("flush");
Andy Hungd1c74342015-07-07 16:54:23 -07001966 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001967 if (mTrack != 0) mTrack->flush();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001968}
1969
1970void MediaPlayerService::AudioOutput::pause()
1971{
Steve Block3856b092011-10-20 11:56:00 +01001972 ALOGV("pause");
Andy Hungd1c74342015-07-07 16:54:23 -07001973 Mutex::Autolock lock(mLock);
Glenn Kasten2799d742013-05-30 14:33:29 -07001974 if (mTrack != 0) mTrack->pause();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001975}
1976
1977void MediaPlayerService::AudioOutput::close()
1978{
Steve Block3856b092011-10-20 11:56:00 +01001979 ALOGV("close");
Erik Wolsheimer7845a1f2015-10-30 12:07:52 -07001980 sp<AudioTrack> track;
1981 {
1982 Mutex::Autolock lock(mLock);
1983 track = mTrack;
1984 close_l(); // clears mTrack
1985 }
1986 // destruction of the track occurs outside of mutex.
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001987}
1988
1989void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1990{
Steve Block3856b092011-10-20 11:56:00 +01001991 ALOGV("setVolume(%f, %f)", left, right);
Andy Hungd1c74342015-07-07 16:54:23 -07001992 Mutex::Autolock lock(mLock);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001993 mLeftVolume = left;
1994 mRightVolume = right;
Glenn Kasten2799d742013-05-30 14:33:29 -07001995 if (mTrack != 0) {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001996 mTrack->setVolume(left, right);
1997 }
1998}
1999
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002000status_t MediaPlayerService::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002001{
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002002 ALOGV("setPlaybackRate(%f %f %d %d)",
2003 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
Andy Hungd1c74342015-07-07 16:54:23 -07002004 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002005 if (mTrack == 0) {
2006 // remember rate so that we can set it when the track is opened
2007 mPlaybackRate = rate;
2008 return OK;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002009 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002010 status_t res = mTrack->setPlaybackRate(rate);
2011 if (res != NO_ERROR) {
2012 return res;
2013 }
2014 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
2015 CHECK_GT(rate.mSpeed, 0.f);
2016 mPlaybackRate = rate;
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002017 if (mSampleRateHz != 0) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002018 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002019 }
2020 return res;
2021}
2022
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002023status_t MediaPlayerService::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
2024{
2025 ALOGV("setPlaybackRate");
Andy Hungd1c74342015-07-07 16:54:23 -07002026 Mutex::Autolock lock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002027 if (mTrack == 0) {
2028 return NO_INIT;
2029 }
2030 *rate = mTrack->getPlaybackRate();
2031 return NO_ERROR;
2032}
2033
Eric Laurent2beeb502010-07-16 07:43:46 -07002034status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
2035{
Steve Block3856b092011-10-20 11:56:00 +01002036 ALOGV("setAuxEffectSendLevel(%f)", level);
Andy Hungd1c74342015-07-07 16:54:23 -07002037 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002038 mSendLevel = level;
Glenn Kasten2799d742013-05-30 14:33:29 -07002039 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002040 return mTrack->setAuxEffectSendLevel(level);
2041 }
2042 return NO_ERROR;
2043}
2044
2045status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
2046{
Steve Block3856b092011-10-20 11:56:00 +01002047 ALOGV("attachAuxEffect(%d)", effectId);
Andy Hungd1c74342015-07-07 16:54:23 -07002048 Mutex::Autolock lock(mLock);
Eric Laurent2beeb502010-07-16 07:43:46 -07002049 mAuxEffectId = effectId;
Glenn Kasten2799d742013-05-30 14:33:29 -07002050 if (mTrack != 0) {
Eric Laurent2beeb502010-07-16 07:43:46 -07002051 return mTrack->attachAuxEffect(effectId);
2052 }
2053 return NO_ERROR;
2054}
2055
Andreas Huber20111aa2009-07-14 16:56:47 -07002056// static
2057void MediaPlayerService::AudioOutput::CallbackWrapper(
Glenn Kastend217a8c2011-06-01 15:20:35 -07002058 int event, void *cookie, void *info) {
Steve Block3856b092011-10-20 11:56:00 +01002059 //ALOGV("callbackwrapper");
Marco Nelissen6b74d672012-02-28 16:07:44 -08002060 CallbackData *data = (CallbackData*)cookie;
Andy Hungd1c74342015-07-07 16:54:23 -07002061 // lock to ensure we aren't caught in the middle of a track switch.
Marco Nelissen6b74d672012-02-28 16:07:44 -08002062 data->lock();
2063 AudioOutput *me = data->getOutput();
Andreas Huber20111aa2009-07-14 16:56:47 -07002064 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Marco Nelissen6b74d672012-02-28 16:07:44 -08002065 if (me == NULL) {
2066 // no output set, likely because the track was scheduled to be reused
2067 // by another player, but the format turned out to be incompatible.
2068 data->unlock();
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002069 if (buffer != NULL) {
2070 buffer->size = 0;
2071 }
Marco Nelissen6b74d672012-02-28 16:07:44 -08002072 return;
2073 }
Andreas Huber20111aa2009-07-14 16:56:47 -07002074
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002075 switch(event) {
2076 case AudioTrack::EVENT_MORE_DATA: {
2077 size_t actualSize = (*me->mCallback)(
2078 me, buffer->raw, buffer->size, me->mCallbackCookie,
2079 CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002080
Andy Hung719b46b2015-05-31 22:18:25 -07002081 // Log when no data is returned from the callback.
2082 // (1) We may have no data (especially with network streaming sources).
2083 // (2) We may have reached the EOS and the audio track is not stopped yet.
2084 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
2085 // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill).
2086 //
2087 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
2088 // nevertheless for power reasons, we don't want to see too many of these.
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08002089
Andy Hung719b46b2015-05-31 22:18:25 -07002090 ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002091
2092 buffer->size = actualSize;
2093 } break;
2094
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002095 case AudioTrack::EVENT_STREAM_END:
Andy Hung719b46b2015-05-31 22:18:25 -07002096 // currently only occurs for offloaded callbacks
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002097 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
2098 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2099 me->mCallbackCookie, CB_EVENT_STREAM_END);
2100 break;
2101
2102 case AudioTrack::EVENT_NEW_IAUDIOTRACK :
2103 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
2104 (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
2105 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
2106 break;
2107
Glenn Kasten421743b2015-06-01 08:18:08 -07002108 case AudioTrack::EVENT_UNDERRUN:
Andy Hung719b46b2015-05-31 22:18:25 -07002109 // This occurs when there is no data available, typically
Glenn Kasten421743b2015-06-01 08:18:08 -07002110 // when there is a failure to supply data to the AudioTrack. It can also
2111 // occur in non-offloaded mode when the audio device comes out of standby.
2112 //
Andy Hung719b46b2015-05-31 22:18:25 -07002113 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
2114 // it may sound like an audible pop or glitch.
2115 //
2116 // The underrun event is sent once per track underrun; the condition is reset
2117 // when more data is sent to the AudioTrack.
Glenn Kasten421743b2015-06-01 08:18:08 -07002118 ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
2119 break;
2120
Richard Fitzgeraldd89532e2013-05-14 13:18:21 +01002121 default:
2122 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
Andreas Huber51c1e0e2011-04-04 11:43:40 -07002123 }
2124
Marco Nelissen6b74d672012-02-28 16:07:44 -08002125 data->unlock();
Andreas Huber20111aa2009-07-14 16:56:47 -07002126}
2127
Glenn Kastend848eb42016-03-08 13:42:11 -08002128audio_session_t MediaPlayerService::AudioOutput::getSessionId() const
Eric Laurent8c563ed2010-10-07 18:23:03 -07002129{
Andy Hungd1c74342015-07-07 16:54:23 -07002130 Mutex::Autolock lock(mLock);
Eric Laurent8c563ed2010-10-07 18:23:03 -07002131 return mSessionId;
2132}
2133
Eric Laurent6f59db12013-07-26 17:16:50 -07002134uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
2135{
Andy Hungd1c74342015-07-07 16:54:23 -07002136 Mutex::Autolock lock(mLock);
Eric Laurent6f59db12013-07-26 17:16:50 -07002137 if (mTrack == 0) return 0;
2138 return mTrack->getSampleRate();
2139}
2140
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002141////////////////////////////////////////////////////////////////////////////////
2142
2143struct CallbackThread : public Thread {
2144 CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
2145 MediaPlayerBase::AudioSink::AudioCallback cb,
2146 void *cookie);
2147
2148protected:
2149 virtual ~CallbackThread();
2150
2151 virtual bool threadLoop();
2152
2153private:
2154 wp<MediaPlayerBase::AudioSink> mSink;
2155 MediaPlayerBase::AudioSink::AudioCallback mCallback;
2156 void *mCookie;
2157 void *mBuffer;
2158 size_t mBufferSize;
2159
2160 CallbackThread(const CallbackThread &);
2161 CallbackThread &operator=(const CallbackThread &);
2162};
2163
2164CallbackThread::CallbackThread(
2165 const wp<MediaPlayerBase::AudioSink> &sink,
2166 MediaPlayerBase::AudioSink::AudioCallback cb,
2167 void *cookie)
2168 : mSink(sink),
2169 mCallback(cb),
2170 mCookie(cookie),
2171 mBuffer(NULL),
2172 mBufferSize(0) {
2173}
2174
2175CallbackThread::~CallbackThread() {
2176 if (mBuffer) {
2177 free(mBuffer);
2178 mBuffer = NULL;
2179 }
2180}
2181
2182bool CallbackThread::threadLoop() {
2183 sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
2184 if (sink == NULL) {
2185 return false;
2186 }
2187
2188 if (mBuffer == NULL) {
2189 mBufferSize = sink->bufferSize();
2190 mBuffer = malloc(mBufferSize);
2191 }
2192
2193 size_t actualSize =
Richard Fitzgeraldad3af332013-03-25 16:54:37 +00002194 (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
2195 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002196
2197 if (actualSize > 0) {
2198 sink->write(mBuffer, actualSize);
Andy Hunga31335a2014-08-20 17:37:59 -07002199 // Could return false on sink->write() error or short count.
2200 // Not necessarily appropriate but would work for AudioCache behavior.
Andreas Huber7d5b8a72010-02-09 16:59:18 -08002201 }
2202
2203 return true;
2204}
2205
2206////////////////////////////////////////////////////////////////////////////////
2207
Gloria Wang7cf180c2011-02-19 18:37:57 -08002208void MediaPlayerService::addBatteryData(uint32_t params)
2209{
2210 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002211
2212 int32_t time = systemTime() / 1000000L;
2213
2214 // change audio output devices. This notification comes from AudioFlinger
2215 if ((params & kBatteryDataSpeakerOn)
2216 || (params & kBatteryDataOtherAudioDeviceOn)) {
2217
2218 int deviceOn[NUM_AUDIO_DEVICES];
2219 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2220 deviceOn[i] = 0;
2221 }
2222
2223 if ((params & kBatteryDataSpeakerOn)
2224 && (params & kBatteryDataOtherAudioDeviceOn)) {
2225 deviceOn[SPEAKER_AND_OTHER] = 1;
2226 } else if (params & kBatteryDataSpeakerOn) {
2227 deviceOn[SPEAKER] = 1;
2228 } else {
2229 deviceOn[OTHER_AUDIO_DEVICE] = 1;
2230 }
2231
2232 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2233 if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2234
2235 if (mBatteryAudio.refCount > 0) { // if playing audio
2236 if (!deviceOn[i]) {
2237 mBatteryAudio.lastTime[i] += time;
2238 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2239 mBatteryAudio.lastTime[i] = 0;
2240 } else {
2241 mBatteryAudio.lastTime[i] = 0 - time;
2242 }
2243 }
2244
2245 mBatteryAudio.deviceOn[i] = deviceOn[i];
2246 }
2247 }
2248 return;
2249 }
2250
Marco Nelissenb7848f12014-12-04 08:57:56 -08002251 // an audio stream is started
Gloria Wang9ee159b2011-02-24 14:51:45 -08002252 if (params & kBatteryDataAudioFlingerStart) {
2253 // record the start time only if currently no other audio
2254 // is being played
2255 if (mBatteryAudio.refCount == 0) {
2256 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2257 if (mBatteryAudio.deviceOn[i]) {
2258 mBatteryAudio.lastTime[i] -= time;
2259 }
2260 }
2261 }
2262
2263 mBatteryAudio.refCount ++;
2264 return;
2265
2266 } else if (params & kBatteryDataAudioFlingerStop) {
2267 if (mBatteryAudio.refCount <= 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002268 ALOGW("Battery track warning: refCount is <= 0");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002269 return;
2270 }
2271
2272 // record the stop time only if currently this is the only
2273 // audio being played
2274 if (mBatteryAudio.refCount == 1) {
2275 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2276 if (mBatteryAudio.deviceOn[i]) {
2277 mBatteryAudio.lastTime[i] += time;
2278 mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2279 mBatteryAudio.lastTime[i] = 0;
2280 }
2281 }
2282 }
2283
2284 mBatteryAudio.refCount --;
2285 return;
2286 }
2287
Gloria Wang7cf180c2011-02-19 18:37:57 -08002288 int uid = IPCThreadState::self()->getCallingUid();
2289 if (uid == AID_MEDIA) {
2290 return;
2291 }
2292 int index = mBatteryData.indexOfKey(uid);
Gloria Wang7cf180c2011-02-19 18:37:57 -08002293
2294 if (index < 0) { // create a new entry for this UID
2295 BatteryUsageInfo info;
2296 info.audioTotalTime = 0;
2297 info.videoTotalTime = 0;
2298 info.audioLastTime = 0;
2299 info.videoLastTime = 0;
2300 info.refCount = 0;
2301
Gloria Wang9ee159b2011-02-24 14:51:45 -08002302 if (mBatteryData.add(uid, info) == NO_MEMORY) {
Steve Block29357bc2012-01-06 19:20:56 +00002303 ALOGE("Battery track error: no memory for new app");
Gloria Wang9ee159b2011-02-24 14:51:45 -08002304 return;
2305 }
Gloria Wang7cf180c2011-02-19 18:37:57 -08002306 }
2307
2308 BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2309
2310 if (params & kBatteryDataCodecStarted) {
2311 if (params & kBatteryDataTrackAudio) {
2312 info.audioLastTime -= time;
2313 info.refCount ++;
2314 }
2315 if (params & kBatteryDataTrackVideo) {
2316 info.videoLastTime -= time;
2317 info.refCount ++;
2318 }
2319 } else {
2320 if (info.refCount == 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002321 ALOGW("Battery track warning: refCount is already 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002322 return;
2323 } else if (info.refCount < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00002324 ALOGE("Battery track error: refCount < 0");
Gloria Wang7cf180c2011-02-19 18:37:57 -08002325 mBatteryData.removeItem(uid);
2326 return;
2327 }
2328
2329 if (params & kBatteryDataTrackAudio) {
2330 info.audioLastTime += time;
2331 info.refCount --;
2332 }
2333 if (params & kBatteryDataTrackVideo) {
2334 info.videoLastTime += time;
2335 info.refCount --;
2336 }
2337
2338 // no stream is being played by this UID
2339 if (info.refCount == 0) {
2340 info.audioTotalTime += info.audioLastTime;
2341 info.audioLastTime = 0;
2342 info.videoTotalTime += info.videoLastTime;
2343 info.videoLastTime = 0;
2344 }
2345 }
2346}
2347
2348status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2349 Mutex::Autolock lock(mLock);
Gloria Wang9ee159b2011-02-24 14:51:45 -08002350
2351 // audio output devices usage
2352 int32_t time = systemTime() / 1000000L; //in ms
2353 int32_t totalTime;
2354
2355 for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2356 totalTime = mBatteryAudio.totalTime[i];
2357
2358 if (mBatteryAudio.deviceOn[i]
2359 && (mBatteryAudio.lastTime[i] != 0)) {
2360 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
2361 totalTime += tmpTime;
2362 }
2363
2364 reply->writeInt32(totalTime);
2365 // reset the total time
2366 mBatteryAudio.totalTime[i] = 0;
2367 }
2368
2369 // codec usage
Gloria Wang7cf180c2011-02-19 18:37:57 -08002370 BatteryUsageInfo info;
2371 int size = mBatteryData.size();
2372
2373 reply->writeInt32(size);
2374 int i = 0;
2375
2376 while (i < size) {
2377 info = mBatteryData.valueAt(i);
2378
2379 reply->writeInt32(mBatteryData.keyAt(i)); //UID
2380 reply->writeInt32(info.audioTotalTime);
2381 reply->writeInt32(info.videoTotalTime);
2382
2383 info.audioTotalTime = 0;
2384 info.videoTotalTime = 0;
2385
2386 // remove the UID entry where no stream is being played
2387 if (info.refCount <= 0) {
2388 mBatteryData.removeItemsAt(i);
2389 size --;
2390 i --;
2391 }
2392 i++;
2393 }
2394 return NO_ERROR;
2395}
nikoa64c8c72009-07-20 15:07:26 -07002396} // namespace android