blob: a692773ccb5c45355f6502524f0d73fb598e10cc [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, 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
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hung0f725b42023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hung0f725b42023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung954b9712023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung56ce2ed2024-06-12 16:03:16 -0700317void TrackBase::deferRestartIfDisabled()
318{
319 const auto thread = mThread.promote();
320 if (thread == nullptr) return;
Andy Hungc76e5032024-09-16 15:13:54 -0700321 auto weakTrack = wp<TrackBase>::fromExisting(this);
322 thread->getThreadloopExecutor().defer([weakTrack] {
323 const auto actual = weakTrack.promote();
Andy Hung56ce2ed2024-06-12 16:03:16 -0700324 if (actual) actual->restartIfDisabled();
325 });
326}
327
Andy Hung88a7afe2024-08-12 20:00:46 -0700328void TrackBase::beginBatteryAttribution() {
329 mBatteryStatsHolder.emplace(uid());
330 if (media::psh_utils::AudioPowerManager::enabled()) {
331 mTrackToken = media::psh_utils::createAudioTrackToken(uid());
332 }
333}
334
335void TrackBase::endBatteryAttribution() {
336 mBatteryStatsHolder.reset();
337 mTrackToken.reset();
338}
339
Andy Hung8d31fd22023-06-26 19:20:57 -0700340PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700341 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800342 : mProxy(proxy)
343{
344 if (timeout) {
345 setPeerTimeout(*timeout);
346 } else {
347 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700348 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
349 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800350 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
351 }
352}
353
Andy Hung8d31fd22023-06-26 19:20:57 -0700354void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800355 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
356 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
357}
358
359
Eric Laurent81784c32012-11-19 14:55:58 -0800360// ----------------------------------------------------------------------------
361// Playback
362// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700363#undef LOG_TAG
364#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800365
Andy Hunga5a7fc92023-06-23 19:27:19 -0700366class TrackHandle : public android::media::BnAudioTrack {
367public:
Andy Hungd29af632023-06-23 19:27:19 -0700368 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700369 ~TrackHandle() override;
370
371 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
372 binder::Status start(int32_t* _aidl_return) final;
373 binder::Status stop() final;
374 binder::Status flush() final;
375 binder::Status pause() final;
376 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
377 binder::Status setParameters(const std::string& keyValuePairs,
378 int32_t* _aidl_return) final;
379 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
380 int32_t* _aidl_return) final;
381 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
382 int32_t* _aidl_return) final;
383 binder::Status signal() final;
384 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
385 const media::VolumeShaperOperation& operation,
386 int32_t* _aidl_return) final;
387 binder::Status getVolumeShaperState(
388 int32_t id,
389 std::optional<media::VolumeShaperState>* _aidl_return) final;
390 binder::Status getDualMonoMode(
391 media::audio::common::AudioDualMonoMode* _aidl_return) final;
392 binder::Status setDualMonoMode(
393 media::audio::common::AudioDualMonoMode mode) final;
394 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
395 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
396 binder::Status getPlaybackRateParameters(
397 media::audio::common::AudioPlaybackRate* _aidl_return) final;
398 binder::Status setPlaybackRateParameters(
399 const media::audio::common::AudioPlaybackRate& playbackRate) final;
400
401private:
Andy Hungd29af632023-06-23 19:27:19 -0700402 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700403};
404
405/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700406sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700407 return sp<TrackHandle>::make(track);
408}
409
Andy Hungd29af632023-06-23 19:27:19 -0700410TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800411 : BnAudioTrack(),
412 mTrack(track)
413{
Andy Hung225aef62022-12-06 16:33:20 -0800414 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -0700415 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800416}
417
Andy Hunga5a7fc92023-06-23 19:27:19 -0700418TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800419 // just stop the track on deletion, associated resources
420 // will be freed from the main thread once all pending buffers have
421 // been played. Unless it's not in the active track list, in which
422 // case we free everything now...
423 mTrack->destroy();
424}
425
Andy Hunga5a7fc92023-06-23 19:27:19 -0700426Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800427 std::optional<media::SharedFileRegion>* _aidl_return) {
428 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
429 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800430}
431
Andy Hunga5a7fc92023-06-23 19:27:19 -0700432Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800433 *_aidl_return = mTrack->start();
434 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800435}
436
Andy Hunga5a7fc92023-06-23 19:27:19 -0700437Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800438 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800439 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800440}
441
Andy Hunga5a7fc92023-06-23 19:27:19 -0700442Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800443 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800444 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800445}
446
Andy Hunga5a7fc92023-06-23 19:27:19 -0700447Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800448 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800449 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800450}
451
Andy Hunga5a7fc92023-06-23 19:27:19 -0700452Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800453 int32_t* _aidl_return) {
454 *_aidl_return = mTrack->attachAuxEffect(effectId);
455 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800456}
457
Andy Hunga5a7fc92023-06-23 19:27:19 -0700458Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 int32_t* _aidl_return) {
460 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
461 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700462}
463
Andy Hunga5a7fc92023-06-23 19:27:19 -0700464Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800465 int32_t* _aidl_return) {
466 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
467 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800468}
469
Andy Hunga5a7fc92023-06-23 19:27:19 -0700470Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800471 int32_t* _aidl_return) {
472 AudioTimestamp legacy;
473 *_aidl_return = mTrack->getTimestamp(legacy);
474 if (*_aidl_return != OK) {
475 return Status::ok();
476 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000477
478 // restrict position modulo INT_MAX to avoid integer sanitization abort
479 legacy.mPosition &= INT_MAX;
480
Andy Hung973638a2020-12-08 20:47:45 -0800481 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800482 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800483}
484
Andy Hunga5a7fc92023-06-23 19:27:19 -0700485Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800486 mTrack->signal();
487 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800488}
489
Andy Hunga5a7fc92023-06-23 19:27:19 -0700490Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800491 const media::VolumeShaperConfiguration& configuration,
492 const media::VolumeShaperOperation& operation,
493 int32_t* _aidl_return) {
494 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
495 *_aidl_return = conf->readFromParcelable(configuration);
496 if (*_aidl_return != OK) {
497 return Status::ok();
498 }
499
500 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
501 *_aidl_return = op->readFromParcelable(operation);
502 if (*_aidl_return != OK) {
503 return Status::ok();
504 }
505
506 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
507 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700508}
509
Andy Hunga5a7fc92023-06-23 19:27:19 -0700510Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800511 int32_t id,
512 std::optional<media::VolumeShaperState>* _aidl_return) {
513 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
514 if (legacy == nullptr) {
515 _aidl_return->reset();
516 return Status::ok();
517 }
518 media::VolumeShaperState aidl;
519 legacy->writeToParcelable(&aidl);
520 *_aidl_return = aidl;
521 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800522}
523
Andy Hunga5a7fc92023-06-23 19:27:19 -0700524Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000525 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800526{
527 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
528 const status_t status = mTrack->getDualMonoMode(&mode)
529 ?: AudioValidator::validateDualMonoMode(mode);
530 if (status == OK) {
531 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
532 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
533 }
534 return binderStatusFromStatusT(status);
535}
536
Andy Hunga5a7fc92023-06-23 19:27:19 -0700537Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000538 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800539{
540 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
541 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
542 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
543 ?: mTrack->setDualMonoMode(localMonoMode));
544}
545
Andy Hunga5a7fc92023-06-23 19:27:19 -0700546Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800547{
548 float leveldB = -std::numeric_limits<float>::infinity();
549 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
550 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
551 if (status == OK) *_aidl_return = leveldB;
552 return binderStatusFromStatusT(status);
553}
554
Andy Hunga5a7fc92023-06-23 19:27:19 -0700555Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800556{
557 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
558 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
559}
560
Andy Hunga5a7fc92023-06-23 19:27:19 -0700561Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000562 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800563{
564 audio_playback_rate_t localPlaybackRate{};
565 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
566 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
567 if (status == NO_ERROR) {
568 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
569 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
570 }
571 return binderStatusFromStatusT(status);
572}
573
Andy Hunga5a7fc92023-06-23 19:27:19 -0700574Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000575 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800576{
577 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
578 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
579 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
580 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
581}
582
Eric Laurent81784c32012-11-19 14:55:58 -0800583// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800584// AppOp for audio playback
585// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700586
587// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700588sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700589 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000590 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700591 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800592{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700593 Vector<String16> packages;
594 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000595 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700596 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700597 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000598 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700599 uid);
600 return nullptr;
601 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800602 }
603 // stream type has been filtered by audio policy to indicate whether it can be muted
604 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700605 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700606 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800607 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700608 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
609 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
610 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
611 id, attr.flags);
612 return nullptr;
613 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700614 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700615}
616
Andy Hung87c693c2023-07-06 20:56:16 -0700617OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700618 const AttributionSourceState& attributionSource,
619 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700620 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700621 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700622 mUsage((int32_t)usage),
623 mId(id),
624 mUid(uid),
625 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
626 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800627
Andy Hung8d31fd22023-06-26 19:20:57 -0700628OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800629{
630 if (mOpCallback != 0) {
631 mAppOpsManager.stopWatchingMode(mOpCallback);
632 }
633 mOpCallback.clear();
634}
635
Andy Hung8d31fd22023-06-26 19:20:57 -0700636void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700637{
Vlad Popad5859592023-08-02 18:36:04 -0700638 // make sure not to broadcast the initial state since it is not needed and could
639 // cause a deadlock since this method can be called with the mThread->mLock held
640 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000641 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700642 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000643 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
644 } else {
645 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700646 }
647}
648
Andy Hung8d31fd22023-06-26 19:20:57 -0700649bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800650 return mHasOpPlayAudio.load();
651}
652
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700653// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800654// - not called from constructor due to check on UID,
655// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000656void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
657 const bool hasAppOps =
658 mPackageName.size() &&
659 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
660 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700661
662 bool shouldChange = !hasAppOps; // check if we need to update.
663 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000664 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000665 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700666 if (doBroadcast) {
667 auto thread = mThread.promote();
668 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
669 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700670 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700671 thread->broadcast_l();
672 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700673 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800674 }
675}
676
Andy Hung8d31fd22023-06-26 19:20:57 -0700677OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800678 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
679{ }
680
Andy Hung8d31fd22023-06-26 19:20:57 -0700681void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800682 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800683 if (op != AppOpsManager::OP_PLAY_AUDIO) {
684 return;
685 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000686
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000687 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800688 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
689 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700690 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800691 }
692}
693
Eric Laurent9066ad32019-05-20 14:40:10 -0700694// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700695void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700696 uid_t uid, Vector<String16>& packages)
697{
698 PermissionController permissionController;
699 permissionController.getPackagesForUid(uid, packages);
700}
701
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800702// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700703#undef LOG_TAG
704#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800705
Andy Hung8d31fd22023-06-26 19:20:57 -0700706/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700707sp<IAfTrack> IAfTrack::create(
708 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700709 const sp<Client>& client,
710 audio_stream_type_t streamType,
711 const audio_attributes_t& attr,
712 uint32_t sampleRate,
713 audio_format_t format,
714 audio_channel_mask_t channelMask,
715 size_t frameCount,
716 void *buffer,
717 size_t bufferSize,
718 const sp<IMemory>& sharedBuffer,
719 audio_session_t sessionId,
720 pid_t creatorPid,
721 const AttributionSourceState& attributionSource,
722 audio_output_flags_t flags,
723 track_type type,
724 audio_port_handle_t portId,
725 /** default behaviour is to start when there are as many frames
726 * ready as possible (aka. Buffer is full). */
727 size_t frameCountToBeReady,
728 float speed,
729 bool isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000730 bool isBitPerfect,
731 float volume) {
Andy Hung87c693c2023-07-06 20:56:16 -0700732 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700733 client,
734 streamType,
735 attr,
736 sampleRate,
737 format,
738 channelMask,
739 frameCount,
740 buffer,
741 bufferSize,
742 sharedBuffer,
743 sessionId,
744 creatorPid,
745 attributionSource,
746 flags,
747 type,
748 portId,
749 frameCountToBeReady,
750 speed,
751 isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000752 isBitPerfect,
753 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -0700754}
755
Eric Laurent81784c32012-11-19 14:55:58 -0800756// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700757Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700758 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800759 const sp<Client>& client,
760 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700761 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800762 uint32_t sampleRate,
763 audio_format_t format,
764 audio_channel_mask_t channelMask,
765 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700766 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700767 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800768 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800769 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700770 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000771 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700772 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800773 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100774 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000775 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200776 float speed,
jiabinc658e452022-10-21 20:52:21 +0000777 bool isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000778 bool isBitPerfect,
779 float volume)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700780 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700781 // TODO: Using unsecurePointer() has some associated security pitfalls
782 // (see declaration for details).
783 // Either document why it is safe in this case or address the
784 // issue (e.g. by copying).
785 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700786 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700787 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000788 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700789 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800790 type,
791 portId,
792 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700793 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800794 // mRetryCount initialized later when needed
795 mSharedBuffer(sharedBuffer),
796 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700797 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800798 mAuxBuffer(NULL),
799 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700800 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700801 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700802 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700803 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700804 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800805 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800806 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700807 /* The track might not play immediately after being active, similarly as if its volume was 0.
808 * When the track starts playing, its volume will be computed. */
809 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800810 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700811 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000812 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200813 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000814 mIsSpatialized(isSpatialized),
Andy Hung6b137d12024-08-27 22:35:17 +0000815 mIsBitPerfect(isBitPerfect),
816 mVolume(volume)
Eric Laurent81784c32012-11-19 14:55:58 -0800817{
Eric Laurent83b88082014-06-20 18:31:16 -0700818 // client == 0 implies sharedBuffer == 0
819 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
820
Andy Hung9d84af52018-09-12 18:03:44 -0700821 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700822 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700823
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700824 if (mCblk == NULL) {
825 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800826 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700827
Svet Ganov33761132021-05-13 22:51:08 +0000828 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700829 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
830 ALOGE("%s(%d): no more tracks available", __func__, mId);
831 releaseCblk(); // this makes the track invalid.
832 return;
833 }
834
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700835 if (sharedBuffer == 0) {
836 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700837 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700838 } else {
839 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100840 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700841 }
842 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700843 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700844
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700845 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700846 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700847 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
848 // race with setSyncEvent(). However, if we call it, we cannot properly start
849 // static fast tracks (SoundPool) immediately after stopping.
850 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700851 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
852 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700853 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700854 // FIXME This is too eager. We allocate a fast track index before the
855 // fast track becomes active. Since fast tracks are a scarce resource,
856 // this means we are potentially denying other more important fast tracks from
857 // being created. It would be better to allocate the index dynamically.
858 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700859 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700860 }
Andy Hung8946a282018-04-19 20:04:56 -0700861
Andy Hung6b137d12024-08-27 22:35:17 +0000862 populateUsageAndContentTypeFromStreamType();
863
864 // Audio patch and call assistant volume are always max
865 if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
866 || mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
867 mVolume = 1.0f;
868 }
869
Dean Wheatley7b036912020-06-18 16:22:11 +1000870 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700871#ifdef TEE_SINK
872 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800873 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700874#endif
jiabin57303cc2018-12-18 15:45:57 -0800875
jiabineb3bda02020-06-30 14:07:03 -0700876 if (thread->supportsHapticPlayback()) {
877 // If the track is attached to haptic playback thread, it is potentially to have
878 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
879 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800880 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000881 std::string packageName = attributionSource.packageName.has_value() ?
882 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800883 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700884 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800885 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800886
887 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700888 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800889 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800890}
891
Andy Hung6b137d12024-08-27 22:35:17 +0000892// When attributes are undefined, derive default values from stream type.
893// See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
894void Track::populateUsageAndContentTypeFromStreamType() {
895 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
896 switch (mStreamType) {
897 case AUDIO_STREAM_VOICE_CALL:
898 mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
899 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
900 break;
901 case AUDIO_STREAM_SYSTEM:
902 mAttr.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
903 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
904 break;
905 case AUDIO_STREAM_RING:
906 mAttr.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
907 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
908 break;
909 case AUDIO_STREAM_MUSIC:
910 mAttr.usage = AUDIO_USAGE_MEDIA;
911 mAttr.content_type = AUDIO_CONTENT_TYPE_MUSIC;
912 break;
913 case AUDIO_STREAM_ALARM:
914 mAttr.usage = AUDIO_USAGE_ALARM;
915 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
916 break;
917 case AUDIO_STREAM_NOTIFICATION:
918 mAttr.usage = AUDIO_USAGE_NOTIFICATION;
919 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
920 break;
921 case AUDIO_STREAM_DTMF:
922 mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
923 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
924 break;
925 case AUDIO_STREAM_ACCESSIBILITY:
926 mAttr.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
927 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
928 break;
929 case AUDIO_STREAM_ASSISTANT:
930 mAttr.usage = AUDIO_USAGE_ASSISTANT;
931 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
932 break;
933 case AUDIO_STREAM_REROUTING:
934 case AUDIO_STREAM_PATCH:
935 mAttr.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
936 // unknown content type
937 break;
938 case AUDIO_STREAM_CALL_ASSISTANT:
939 mAttr.usage = AUDIO_USAGE_CALL_ASSISTANT;
940 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
941 break;
942 default:
943 break;
944 }
945 }
946}
947
Andy Hung8d31fd22023-06-26 19:20:57 -0700948Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800949{
Andy Hung9d84af52018-09-12 18:03:44 -0700950 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700951
952 // The destructor would clear mSharedBuffer,
953 // but it will not push the decremented reference count,
954 // leaving the client's IMemory dangling indefinitely.
955 // This prevents that leak.
956 if (mSharedBuffer != 0) {
957 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700958 }
Eric Laurent81784c32012-11-19 14:55:58 -0800959}
960
Andy Hung8d31fd22023-06-26 19:20:57 -0700961status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700962{
963 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700964 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700965 status = NO_MEMORY;
966 }
967 return status;
968}
969
Andy Hung8d31fd22023-06-26 19:20:57 -0700970void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800971{
972 // NOTE: destroyTrack_l() can remove a strong reference to this Track
973 // by removing it from mTracks vector, so there is a risk that this Tracks's
974 // destructor is called. As the destructor needs to lock mLock,
975 // we must acquire a strong reference on this Track before locking mLock
976 // here so that the destructor is called only when exiting this function.
977 // On the other hand, as long as Track::destroy() is only called by
978 // TrackHandle destructor, the TrackHandle still holds a strong ref on
979 // this Track with its member mTrack.
980 sp<Track> keep(this);
981 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700982 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700983 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800984 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -0800985 audio_utils::unique_lock ul(thread->mutex());
986 thread->waitWhileThreadBusy_l(ul);
987
Andy Hung87c693c2023-07-06 20:56:16 -0700988 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700989 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000990 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700991 }
992 if (isExternalTrack() && !wasActive) {
Andy Hung6c498e92023-12-05 17:28:17 -0800993 // If the track is not active, the TrackHandle is responsible for
994 // releasing the port id, not the ThreadBase::threadLoop().
995 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700996 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800997 }
998 }
999}
1000
Andy Hung8d31fd22023-06-26 19:20:57 -07001001void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08001002{
Eric Laurent973db022018-11-20 14:54:31 -08001003 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001004 " Format Chn mask SRate "
1005 "ST Usg CT "
Andy Hung6b137d12024-08-27 22:35:17 +00001006 " G db L dB R dB VS dB PortVol dB "
jiabin220eea12024-05-17 17:55:20 +00001007 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001008 "%s\n",
1009 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08001010}
1011
Andy Hung8d31fd22023-06-26 19:20:57 -07001012void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08001013{
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001014 char trackType;
1015 switch (mType) {
1016 case TYPE_DEFAULT:
1017 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -07001018 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019 trackType = 'S'; // static
1020 } else {
1021 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -08001022 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001023 break;
1024 case TYPE_PATCH:
1025 trackType = 'P';
1026 break;
1027 default:
1028 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -08001029 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001030
1031 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -07001032 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001033 } else {
Andy Hungc0691382018-09-12 18:01:57 -07001034 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001035 }
1036
Eric Laurent81784c32012-11-19 14:55:58 -08001037 char nowInUnderrun;
1038 switch (mObservedUnderruns.mBitFields.mMostRecent) {
1039 case UNDERRUN_FULL:
1040 nowInUnderrun = ' ';
1041 break;
1042 case UNDERRUN_PARTIAL:
1043 nowInUnderrun = '<';
1044 break;
1045 case UNDERRUN_EMPTY:
1046 nowInUnderrun = '*';
1047 break;
1048 default:
1049 nowInUnderrun = '?';
1050 break;
1051 }
Andy Hungda540db2017-04-20 14:06:17 -07001052
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001053 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -07001054 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001055 case FS_INVALID:
1056 fillingStatus = 'I';
1057 break;
1058 case FS_FILLING:
1059 fillingStatus = 'f';
1060 break;
1061 case FS_FILLED:
1062 fillingStatus = 'F';
1063 break;
1064 case FS_ACTIVE:
1065 fillingStatus = 'A';
1066 break;
1067 default:
1068 fillingStatus = '?';
1069 break;
1070 }
1071
1072 // clip framesReadySafe to max representation in dump
1073 const size_t framesReadySafe =
1074 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
1075
1076 // obtain volumes
1077 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1078 const std::pair<float /* volume */, bool /* active */> vsVolume =
1079 mVolumeHandler->getLastVolume();
1080
1081 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
1082 // as it may be reduced by the application.
1083 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
1084 // Check whether the buffer size has been modified by the app.
1085 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
1086 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
1087 ? 'e' /* error */ : ' ' /* identical */;
1088
Eric Laurent973db022018-11-20 14:54:31 -08001089 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001090 "%08X %08X %6u "
1091 "%2u %3x %2x "
Andy Hung6b137d12024-08-27 22:35:17 +00001092 "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
jiabin220eea12024-05-17 17:55:20 +00001093 "%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001094 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001095 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001096 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001097 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001098 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001099 mCblk->mFlags,
1100
Eric Laurent81784c32012-11-19 14:55:58 -08001101 mFormat,
1102 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001103 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001104
1105 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001106 mAttr.usage,
1107 mAttr.content_type,
1108
1109 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001110 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1111 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001112 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1113 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung6b137d12024-08-27 22:35:17 +00001114 20.0 * log10(mVolume),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001115
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001116 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001117 bufferSizeInFrames,
1118 modifiedBufferChar,
1119 framesReadySafe,
1120 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001121 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001122 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001123 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
jiabin220eea12024-05-17 17:55:20 +00001124 isBitPerfect() ? "true" : "false",
1125 getInternalMute() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001126 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001127
1128 if (isServerLatencySupported()) {
1129 double latencyMs;
1130 bool fromTrack;
1131 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1132 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1133 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1134 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001135 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001136 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001137 }
1138 }
1139 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001140}
1141
Andy Hung8d31fd22023-06-26 19:20:57 -07001142uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001143 return mAudioTrackServerProxy->getSampleRate();
1144}
1145
Eric Laurent81784c32012-11-19 14:55:58 -08001146// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001147status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001148{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001149 ServerProxy::Buffer buf;
1150 size_t desiredFrames = buffer->frameCount;
1151 buf.mFrameCount = desiredFrames;
1152 status_t status = mServerProxy->obtainBuffer(&buf);
1153 buffer->frameCount = buf.mFrameCount;
1154 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001155 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001156 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001157 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001158 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001159 } else {
1160 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001161 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001162 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001163}
1164
Andy Hung8d31fd22023-06-26 19:20:57 -07001165void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001166{
1167 interceptBuffer(*buffer);
1168 TrackBase::releaseBuffer(buffer);
1169}
1170
1171// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001172void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001173 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001174 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001175 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001176 if (frameCount == 0) {
1177 return; // No audio to intercept.
1178 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1179 // does not allow 0 frame size request contrary to getNextBuffer
1180 }
Jiabin Huang73f97052023-12-12 20:08:03 +00001181 TeePatches teePatches;
1182 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1183 // Cache a copy of tee patches in case it is updated while using.
1184 teePatches = mTeePatches;
1185 mTeePatchesRWLock.unlock();
1186 }
1187 for (auto& teePatch : teePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001188 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001189 const size_t framesWritten = patchRecord->writeFrames(
1190 sourceBuffer.i8, frameCount, mFrameSize);
1191 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001192 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001193 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001194 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001195 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001196 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1197 using namespace std::chrono_literals;
1198 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001199 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang73f97052023-12-12 20:08:03 +00001200 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001201}
1202
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001203// ExtendedAudioBufferProvider interface
1204
Andy Hung27876c02014-09-09 18:07:55 -07001205// framesReady() may return an approximation of the number of frames if called
1206// from a different thread than the one calling Proxy->obtainBuffer() and
1207// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1208// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001209size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001210 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1211 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1212 // The remainder of the buffer is not drained.
1213 return 0;
1214 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001215 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001216}
1217
Andy Hung8d31fd22023-06-26 19:20:57 -07001218int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001219{
1220 return mAudioTrackServerProxy->framesReleased();
1221}
1222
Andy Hung8d31fd22023-06-26 19:20:57 -07001223void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001224{
1225 // This call comes from a FastTrack and should be kept lockless.
1226 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001227 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001228
Andy Hung818e7a32016-02-16 18:08:07 -08001229 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001230
1231 // Compute latency.
1232 // TODO: Consider whether the server latency may be passed in by FastMixer
1233 // as a constant for all active FastTracks.
1234 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1235 mServerLatencyFromTrack.store(true);
1236 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001237}
1238
Eric Laurent81784c32012-11-19 14:55:58 -08001239// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001240bool Track::isReady() const {
1241 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001242 return true;
1243 }
1244
Eric Laurent16498512014-03-17 17:22:08 -07001245 if (isStopping()) {
1246 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001247 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001248 }
Eric Laurent81784c32012-11-19 14:55:58 -08001249 return true;
1250 }
1251
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001252 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001253 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1254 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1255 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1256 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001257
1258 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1259 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1260 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001261 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001262 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001263 return true;
1264 }
1265 return false;
1266}
1267
Andy Hung8d31fd22023-06-26 19:20:57 -07001268status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001269 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001270{
1271 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001272 ALOGV("%s(%d): calling pid %d session %d",
1273 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001274
Andy Hung87c693c2023-07-06 20:56:16 -07001275 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001276 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001277 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001278 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001279 const bool nonOffloadableGlobalEffectEnabled =
1280 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001281 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001282 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001283 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001284 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001285 invalidate();
1286 return PERMISSION_DENIED;
1287 }
1288 }
Andy Hung6c498e92023-12-05 17:28:17 -08001289 audio_utils::unique_lock ul(thread->mutex());
1290 thread->waitWhileThreadBusy_l(ul);
1291
Eric Laurent81784c32012-11-19 14:55:58 -08001292 track_state state = mState;
1293 // here the track could be either new, or restarted
1294 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001295
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001296 // initial state-stopping. next state-pausing.
1297 // What if resume is called ?
1298
Zhou Song1ed46a22020-08-17 15:36:56 +08001299 if (state == FLUSHED) {
1300 // avoid underrun glitches when starting after flush
1301 reset();
1302 }
1303
kuowei.li576f1362021-05-11 18:02:32 +08001304 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1305 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001306 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001307 if (mResumeToStopping) {
1308 // happened we need to resume to STOPPING_1
1309 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001310 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1311 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001312 } else {
1313 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001314 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1315 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001316 }
Eric Laurent81784c32012-11-19 14:55:58 -08001317 } else {
1318 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001319 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1320 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001321 }
1322
Andy Hung87c693c2023-07-06 20:56:16 -07001323 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001324
1325 // states to reset position info for pcm tracks
1326 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001327 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1328 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001329
Dorin Drimusb882d482024-01-17 18:30:02 +01001330 if (!isFastTrack()) {
yucliu6cfb5932022-07-20 17:40:39 -07001331 // Start point of track -> sink frame map. If the HAL returns a
1332 // frame position smaller than the first written frame in
1333 // updateTrackFrameInfo, the timestamp can be interpolated
1334 // instead of using a larger value.
1335 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1336 playbackThread->framesWritten());
1337 }
Andy Hunge10393e2015-06-12 13:59:33 -07001338 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001339 if (isFastTrack()) {
1340 // refresh fast track underruns on start because that field is never cleared
1341 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1342 // after stop.
1343 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1344 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001345 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001346 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001347 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001348 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001349 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001350 mState = state;
1351 }
1352 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001353
Andy Hungb68f5eb2019-12-03 16:49:17 -08001354 // Audio timing metrics are computed a few mix cycles after starting.
1355 {
1356 mLogStartCountdown = LOG_START_COUNTDOWN;
1357 mLogStartTimeNs = systemTime();
1358 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001359 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1360 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001361 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001362 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001363
Andy Hung1d3556d2018-03-29 16:30:14 -07001364 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1365 // for streaming tracks, remove the buffer read stop limit.
1366 mAudioTrackServerProxy->start();
1367 }
1368
Eric Laurentbfb1b832013-01-07 09:53:42 -08001369 // track was already in the active list, not a problem
1370 if (status == ALREADY_EXISTS) {
1371 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001372 } else {
1373 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1374 // It is usually unsafe to access the server proxy from a binder thread.
1375 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1376 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1377 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001378 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001379 ServerProxy::Buffer buffer;
1380 buffer.mFrameCount = 1;
1381 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001382 }
jiabin7434e812023-06-27 18:22:35 +00001383 if (status == NO_ERROR) {
1384 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1385 }
Eric Laurent81784c32012-11-19 14:55:58 -08001386 } else {
1387 status = BAD_VALUE;
1388 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001389 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001390 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001391 const sp<IAudioManager> audioManager =
1392 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001393 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1394 std::unique_ptr<os::PersistableBundle> bundle =
1395 std::make_unique<os::PersistableBundle>();
1396 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1397 isSpatialized());
1398 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1399 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1400 status_t result = audioManager->portEvent(mPortId,
1401 PLAYER_UPDATE_FORMAT, bundle);
1402 if (result != OK) {
1403 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1404 __func__, mPortId, result);
1405 }
1406 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001407 }
Eric Laurent81784c32012-11-19 14:55:58 -08001408 return status;
1409}
1410
Andy Hung8d31fd22023-06-26 19:20:57 -07001411void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001412{
Andy Hungc0691382018-09-12 18:01:57 -07001413 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001414 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001415 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001416 audio_utils::unique_lock ul(thread->mutex());
1417 thread->waitWhileThreadBusy_l(ul);
1418
Eric Laurent81784c32012-11-19 14:55:58 -08001419 track_state state = mState;
1420 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1421 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001422 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1423 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001424 reset();
1425 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001426 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1427 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1428 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001429 mState = STOPPED;
1430 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001431 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1432 // presentation is complete
1433 // For an offloaded track this starts a drain and state will
1434 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001435 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001436 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001437 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001438 }
Eric Laurent81784c32012-11-19 14:55:58 -08001439 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001440 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001441 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1442 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001443 }
jiabin7434e812023-06-27 18:22:35 +00001444 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001445 }
1446}
1447
Andy Hung8d31fd22023-06-26 19:20:57 -07001448void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001449{
Andy Hungc0691382018-09-12 18:01:57 -07001450 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001451 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001452 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001453 audio_utils::unique_lock ul(thread->mutex());
1454 thread->waitWhileThreadBusy_l(ul);
1455
Andy Hung87c693c2023-07-06 20:56:16 -07001456 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001457 switch (mState) {
1458 case STOPPING_1:
1459 case STOPPING_2:
1460 if (!isOffloaded()) {
1461 /* nothing to do if track is not offloaded */
1462 break;
1463 }
1464
1465 // Offloaded track was draining, we need to carry on draining when resumed
1466 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001467 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001468 case ACTIVE:
1469 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001470 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001471 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1472 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001473 if (isOffloadedOrDirect()) {
1474 mPauseHwPending = true;
1475 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001476 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001477 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001478
Eric Laurentbfb1b832013-01-07 09:53:42 -08001479 default:
1480 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001481 }
jiabin7434e812023-06-27 18:22:35 +00001482 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1483 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001484 }
1485}
1486
Andy Hung8d31fd22023-06-26 19:20:57 -07001487void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001488{
Andy Hungc0691382018-09-12 18:01:57 -07001489 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001490 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001491 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001492 audio_utils::unique_lock ul(thread->mutex());
1493 thread->waitWhileThreadBusy_l(ul);
1494
Andy Hung87c693c2023-07-06 20:56:16 -07001495 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001496
Phil Burk4bb650b2016-09-09 12:11:17 -07001497 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1498 // Otherwise the flush would not be done until the track is resumed.
1499 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001500 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001501 (void)mServerProxy->flushBufferIfNeeded();
1502 }
1503
Eric Laurentbfb1b832013-01-07 09:53:42 -08001504 if (isOffloaded()) {
1505 // If offloaded we allow flush during any state except terminated
1506 // and keep the track active to avoid problems if user is seeking
1507 // rapidly and underlying hardware has a significant delay handling
1508 // a pause
1509 if (isTerminated()) {
1510 return;
1511 }
1512
Andy Hung9d84af52018-09-12 18:03:44 -07001513 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001514 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001515
1516 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001517 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1518 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001519 mState = ACTIVE;
1520 }
1521
Haynes Mathew George7844f672014-01-15 12:32:55 -08001522 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001523 mResumeToStopping = false;
1524 } else {
1525 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1526 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1527 return;
1528 }
1529 // No point remaining in PAUSED state after a flush => go to
1530 // FLUSHED state
1531 mState = FLUSHED;
1532 // do not reset the track if it is still in the process of being stopped or paused.
1533 // this will be done by prepareTracks_l() when the track is stopped.
1534 // prepareTracks_l() will see mState == FLUSHED, then
1535 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001536 if (isDirect()) {
1537 mFlushHwPending = true;
1538 }
Andy Hung87c693c2023-07-06 20:56:16 -07001539 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001540 reset();
1541 }
Eric Laurent81784c32012-11-19 14:55:58 -08001542 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001543 // Prevent flush being lost if the track is flushed and then resumed
1544 // before mixer thread can run. This is important when offloading
1545 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001546 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001547 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1548 // new data
1549 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001550 }
1551}
1552
Haynes Mathew George7844f672014-01-15 12:32:55 -08001553// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001554void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001555{
Andy Hung920f6572022-10-06 12:09:49 -07001556 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001557 return;
Andy Hung920f6572022-10-06 12:09:49 -07001558 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001559
Phil Burk4bb650b2016-09-09 12:11:17 -07001560 // Clear the client ring buffer so that the app can prime the buffer while paused.
1561 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1562 mServerProxy->flushBufferIfNeeded();
1563
Haynes Mathew George7844f672014-01-15 12:32:55 -08001564 mFlushHwPending = false;
1565}
1566
Andy Hung8d31fd22023-06-26 19:20:57 -07001567void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001568{
1569 mPauseHwPending = false;
1570}
1571
Andy Hung8d31fd22023-06-26 19:20:57 -07001572void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001573{
1574 // Do not reset twice to avoid discarding data written just after a flush and before
1575 // the audioflinger thread detects the track is stopped.
1576 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001577 // Force underrun condition to avoid false underrun callback until first data is
1578 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001579 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001580 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001581 mResetDone = true;
1582 if (mState == FLUSHED) {
1583 mState = IDLE;
1584 }
1585 }
1586}
1587
Andy Hung8d31fd22023-06-26 19:20:57 -07001588status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001589{
Andy Hung87c693c2023-07-06 20:56:16 -07001590 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001591 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001592 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001593 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001594 } else if (thread->type() == IAfThreadBase::DIRECT
1595 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001596 return thread->setParameters(keyValuePairs);
1597 } else {
1598 return PERMISSION_DENIED;
1599 }
1600}
1601
Andy Hung8d31fd22023-06-26 19:20:57 -07001602status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001603 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001604 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001605 if (thread == 0) {
1606 ALOGE("thread is dead");
1607 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001608 } else if (thread->type() == IAfThreadBase::DIRECT
1609 || thread->type() == IAfThreadBase::OFFLOAD) {
1610 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001611 return directOutputThread->selectPresentation(presentationId, programId);
1612 }
1613 return INVALID_OPERATION;
1614}
1615
Andy Hungd571fab2024-08-28 21:59:25 -07001616void Track::setPortVolume(float volume) {
1617 mVolume = volume;
1618 if (mType != TYPE_PATCH) {
1619 // Do not recursively propagate a PatchTrack setPortVolume to
1620 // downstream PatchTracks.
1621 forEachTeePatchTrack_l([volume](const auto& patchTrack) {
1622 patchTrack->setPortVolume(volume); });
1623 }
1624}
1625
Andy Hung8d31fd22023-06-26 19:20:57 -07001626VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001627 const sp<VolumeShaper::Configuration>& configuration,
1628 const sp<VolumeShaper::Operation>& operation)
1629{
Andy Hung398ffa22022-12-13 19:19:53 -08001630 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001631
1632 if (isOffloadedOrDirect()) {
1633 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001634 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001635 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001636 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001637 thread->broadcast_l();
1638 }
1639 }
1640 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001641}
1642
Andy Hung8d31fd22023-06-26 19:20:57 -07001643sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001644{
1645 // Note: We don't check if Thread exists.
1646
1647 // mVolumeHandler is thread safe.
1648 return mVolumeHandler->getVolumeShaperState(id);
1649}
1650
Andy Hung8d31fd22023-06-26 19:20:57 -07001651void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001652{
jiabin76d94692022-12-15 21:51:21 +00001653 mFinalVolumeLeft = volumeLeft;
1654 mFinalVolumeRight = volumeRight;
1655 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001656 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1657 mFinalVolume = volume;
1658 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001659 mLogForceVolumeUpdate = true;
1660 }
1661 if (mLogForceVolumeUpdate) {
1662 mLogForceVolumeUpdate = false;
1663 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001664 }
1665}
1666
Andy Hung8d31fd22023-06-26 19:20:57 -07001667void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001668{
Eric Laurent49e39282022-06-24 18:42:45 +02001669 // Do not forward metadata for PatchTrack with unspecified stream type
1670 if (mStreamType == AUDIO_STREAM_PATCH) {
1671 return;
1672 }
1673
Eric Laurent94579172020-11-20 18:41:04 +01001674 playback_track_metadata_v7_t metadata;
1675 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001676 .usage = mAttr.usage,
1677 .content_type = mAttr.content_type,
1678 .gain = mFinalVolume,
1679 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001680
Eric Laurent78b07302022-10-07 16:20:34 +02001681 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001682 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1683 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001684}
1685
Andy Hung8d31fd22023-06-26 19:20:57 -07001686void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001687 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001688 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang73f97052023-12-12 20:08:03 +00001689 {
1690 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1691 mTeePatches = std::move(mTeePatchesToUpdate.value());
1692 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001693 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1694 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001695 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001696 }
1697 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001698 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001699}
1700
Andy Hung16ed0da2023-07-14 11:45:38 -07001701void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001702 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1703 "%s, existing tee patches to update will be ignored", __func__);
1704 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1705}
1706
Vlad Popae8d99472022-06-30 16:02:48 +02001707// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001708void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001709 IAudioManager>& audioManager, mute_state_t muteState)
1710{
1711 if (mMuteState == muteState) {
1712 // mute state did not change, do nothing
1713 return;
1714 }
1715
1716 status_t result = UNKNOWN_ERROR;
1717 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1718 if (mMuteEventExtras == nullptr) {
1719 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1720 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001721 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001722
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001723 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001724 }
1725
1726 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001727 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung0e26ec62024-02-20 16:32:57 -08001728 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001729 mMuteState = muteState;
1730 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001731 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1732 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001733 }
1734}
1735
Andy Hung8d31fd22023-06-26 19:20:57 -07001736status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001737{
Andy Hung818e7a32016-02-16 18:08:07 -08001738 if (!isOffloaded() && !isDirect()) {
1739 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001740 }
Andy Hung87c693c2023-07-06 20:56:16 -07001741 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001742 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001743 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001744 }
Phil Burk6140c792015-03-19 14:30:21 -07001745
Andy Hungc5007f82023-08-29 14:26:09 -07001746 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001747 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001748 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001749}
1750
Andy Hung8d31fd22023-06-26 19:20:57 -07001751status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001752{
Andy Hung87c693c2023-07-06 20:56:16 -07001753 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001754 if (thread == nullptr) {
1755 return DEAD_OBJECT;
1756 }
Eric Laurent81784c32012-11-19 14:55:58 -08001757
Andy Hung87c693c2023-07-06 20:56:16 -07001758 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001759 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001760 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001761 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001762 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001763
Eric Laurent6c796322019-04-09 14:13:17 -07001764 if (EffectId != 0 && status == NO_ERROR) {
1765 status = dstThread->attachAuxEffect(this, EffectId);
1766 if (status == NO_ERROR) {
1767 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001768 }
Eric Laurent6c796322019-04-09 14:13:17 -07001769 }
1770
1771 if (status != NO_ERROR && srcThread != nullptr) {
1772 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001773 }
1774 return status;
1775}
1776
Andy Hung8d31fd22023-06-26 19:20:57 -07001777void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001778{
1779 mAuxEffectId = EffectId;
1780 mAuxBuffer = buffer;
1781}
1782
Andy Hung59de4262021-06-14 10:53:54 -07001783// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001784bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001785 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001786{
Andy Hung818e7a32016-02-16 18:08:07 -08001787 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1788 // This assists in proper timestamp computation as well as wakelock management.
1789
Eric Laurent81784c32012-11-19 14:55:58 -08001790 // a track is considered presented when the total number of frames written to audio HAL
1791 // corresponds to the number of frames written when presentationComplete() is called for the
1792 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001793 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1794 // to detect when all frames have been played. In this case framesWritten isn't
1795 // useful because it doesn't always reflect whether there is data in the h/w
1796 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001797 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1798 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001799 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001800 if (mPresentationCompleteFrames == 0) {
1801 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001802 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001803 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1804 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001805 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001806 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001807
Andy Hungc54b1ff2016-02-23 14:07:07 -08001808 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001809 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001810 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001811 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1812 __func__, mId, (complete ? "complete" : "waiting"),
1813 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001814 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001815 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001816 && mAudioTrackServerProxy->isDrained();
1817 }
1818
1819 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001820 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001821 return true;
1822 }
1823 return false;
1824}
1825
Andy Hung59de4262021-06-14 10:53:54 -07001826// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001827bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001828{
1829 // For Offloaded or Direct tracks.
1830
1831 // For a direct track, we incorporated time based testing for presentationComplete.
1832
1833 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1834 // to detect when all frames have been played. In this case latencyMs isn't
1835 // useful because it doesn't always reflect whether there is data in the h/w
1836 // buffers, particularly if a track has been paused and resumed during draining
1837
1838 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1839 if (mPresentationCompleteTimeNs == 0) {
1840 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1841 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1842 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1843 }
1844
1845 bool complete;
1846 if (isOffloaded()) {
1847 complete = true;
1848 } else { // Direct
1849 complete = systemTime() >= mPresentationCompleteTimeNs;
1850 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1851 }
1852 if (complete) {
1853 notifyPresentationComplete();
1854 return true;
1855 }
1856 return false;
1857}
1858
Andy Hung8d31fd22023-06-26 19:20:57 -07001859void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001860{
1861 // This only triggers once. TODO: should we enforce this?
1862 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1863 mAudioTrackServerProxy->setStreamEndDone();
1864}
1865
Andy Hung8d31fd22023-06-26 19:20:57 -07001866void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001867{
Andy Hung068e08e2023-05-15 19:02:55 -07001868 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1869 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001870 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001871 (*it)->trigger();
1872 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001873 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001874 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001875 }
1876 }
1877}
1878
1879// implement VolumeBufferProvider interface
1880
Andy Hung8d31fd22023-06-26 19:20:57 -07001881gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001882{
1883 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1884 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001885 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1886 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1887 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001888 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001889 if (vl > GAIN_FLOAT_UNITY) {
1890 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001891 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001892 if (vr > GAIN_FLOAT_UNITY) {
1893 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001894 }
1895 // now apply the cached master volume and stream type volume;
1896 // this is trusted but lacks any synchronization or barrier so may be stale
1897 float v = mCachedVolume;
1898 vl *= v;
1899 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001900 // re-combine into packed minifloat
1901 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001902 // FIXME look at mute, pause, and stop flags
1903 return vlr;
1904}
1905
Andy Hung8d31fd22023-06-26 19:20:57 -07001906status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001907 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001908{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001909 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001910 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1911 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001912 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1913 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001914 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001915 event->cancel();
1916 return INVALID_OPERATION;
1917 }
1918 (void) TrackBase::setSyncEvent(event);
1919 return NO_ERROR;
1920}
1921
Andy Hung8d31fd22023-06-26 19:20:57 -07001922void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001923{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001924 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001925 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001926}
1927
Andy Hung8d31fd22023-06-26 19:20:57 -07001928void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001929{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001930 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001931 signalClientFlag(CBLK_DISABLED);
1932}
1933
Eric Laurent022a5132024-04-12 17:02:51 +00001934bool Track::isDisabled() const {
1935 audio_track_cblk_t* cblk = mCblk;
1936 return (cblk != nullptr)
1937 && ((android_atomic_release_load(&cblk->mFlags) & CBLK_DISABLED) != 0);
1938}
1939
Andy Hung8d31fd22023-06-26 19:20:57 -07001940void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001941{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001942 // FIXME should use proxy, and needs work
1943 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001944 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001945 android_atomic_release_store(0x40000000, &cblk->mFutex);
1946 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001947 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001948}
1949
Andy Hung8d31fd22023-06-26 19:20:57 -07001950void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001951{
Andy Hung87c693c2023-07-06 20:56:16 -07001952 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001953 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001954 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001955 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001956 t->broadcast_l();
1957 }
1958}
1959
Andy Hung8d31fd22023-06-26 19:20:57 -07001960status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001961{
1962 status_t status = INVALID_OPERATION;
1963 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001964 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001966 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001967 audio_utils::lock_guard _l(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001968 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001969 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1970 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1971 }
1972 }
1973 return status;
1974}
1975
Andy Hung8d31fd22023-06-26 19:20:57 -07001976status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001977{
1978 status_t status = INVALID_OPERATION;
1979 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001980 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001981 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001982 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001983 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001984 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001985 if (status == NO_ERROR) {
1986 mDualMonoMode = mode;
1987 }
1988 }
1989 }
1990 return status;
1991}
1992
Andy Hung8d31fd22023-06-26 19:20:57 -07001993status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001994{
1995 status_t status = INVALID_OPERATION;
1996 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001997 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001998 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001999 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002000 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002001 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002002 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
2003 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
2004 }
2005 }
2006 return status;
2007}
2008
Andy Hung8d31fd22023-06-26 19:20:57 -07002009status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002010{
2011 status_t status = INVALID_OPERATION;
2012 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002013 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002014 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002015 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002016 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002017 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002018 if (status == NO_ERROR) {
2019 mAudioDescriptionMixLevel = leveldB;
2020 }
2021 }
2022 }
2023 return status;
2024}
2025
Andy Hung8d31fd22023-06-26 19:20:57 -07002026status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07002027 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002028{
2029 status_t status = INVALID_OPERATION;
2030 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002031 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002032 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002033 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002034 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002035 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002036 ALOGD_IF((status == NO_ERROR) &&
2037 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
2038 "%s: playbackRate inconsistent", __func__);
2039 }
2040 }
2041 return status;
2042}
2043
Andy Hung8d31fd22023-06-26 19:20:57 -07002044status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002045 const audio_playback_rate_t& playbackRate)
2046{
2047 status_t status = INVALID_OPERATION;
2048 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002049 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002050 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002051 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002052 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002053 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002054 if (status == NO_ERROR) {
2055 mPlaybackRateParameters = playbackRate;
2056 }
2057 }
2058 }
2059 return status;
2060}
2061
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002062//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002063bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07002064 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002065 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002066 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002067 /* Resume is pending if track was stopping before pause was called */
2068 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07002069 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002070 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002071 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002072
2073 return false;
2074}
2075
2076//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002077void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07002078 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002079 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002080 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002081
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002082 // Other possibility of pending resume is stopping_1 state
2083 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002084 // drain being called.
2085 if (mState == STOPPING_1) {
2086 mResumeToStopping = false;
2087 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002088}
Andy Hunge10393e2015-06-12 13:59:33 -07002089
2090//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002091void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002092 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002093 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002094 // Make the kernel frametime available.
2095 const FrameTime ft{
2096 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2097 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2098 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2099 mKernelFrameTime.store(ft);
2100 if (!audio_is_linear_pcm(mFormat)) {
2101 return;
2102 }
2103
Andy Hung818e7a32016-02-16 18:08:07 -08002104 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002105 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002106
2107 // adjust server times and set drained state.
2108 //
2109 // Our timestamps are only updated when the track is on the Thread active list.
2110 // We need to ensure that tracks are not removed before full drain.
2111 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002112 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002113 bool checked = false;
2114 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2115 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2116 // Lookup the track frame corresponding to the sink frame position.
2117 if (local.mTimeNs[i] > 0) {
2118 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2119 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002120 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002121 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002122 checked = true;
2123 }
2124 }
Andy Hunge10393e2015-06-12 13:59:33 -07002125 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002126
Andy Hung93bb5732023-05-04 21:16:34 -07002127 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2128 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002129 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002130 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002131 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002132 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002133
2134 // Compute latency info.
2135 const bool useTrackTimestamp = !drained;
2136 const double latencyMs = useTrackTimestamp
2137 ? local.getOutputServerLatencyMs(sampleRate())
2138 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2139
2140 mServerLatencyFromTrack.store(useTrackTimestamp);
2141 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002142
Andy Hung62921122020-05-18 10:47:31 -07002143 if (mLogStartCountdown > 0
2144 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2145 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2146 {
2147 if (mLogStartCountdown > 1) {
2148 --mLogStartCountdown;
2149 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2150 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002151 // startup is the difference in times for the current timestamp and our start
2152 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002153 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002154 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002155 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2156 * 1e3 / mSampleRate;
2157 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2158 " localTime:%lld startTime:%lld"
2159 " localPosition:%lld startPosition:%lld",
2160 __func__, latencyMs, startUpMs,
2161 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002162 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002163 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002164 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002165 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002166 }
Andy Hung62921122020-05-18 10:47:31 -07002167 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002168 }
Andy Hunge10393e2015-06-12 13:59:33 -07002169}
2170
Andy Hung8d31fd22023-06-26 19:20:57 -07002171bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002172 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002173 if (thread != 0) {
2174 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002175 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002176 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002177 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002178 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002179 ALOGD("%s, haptic playback was %s for track %d",
2180 __func__, muted ? "muted" : "unmuted", mTrack->id());
2181 mTrack->setHapticPlaybackEnabled(!muted);
2182 return true;
jiabin57303cc2018-12-18 15:45:57 -08002183 }
2184 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002185 return false;
2186}
2187
Andy Hung8d31fd22023-06-26 19:20:57 -07002188binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002189 /*out*/ bool *ret) {
2190 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002191 return binder::Status::ok();
2192}
2193
Andy Hung8d31fd22023-06-26 19:20:57 -07002194binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002195 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002196 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002197 return binder::Status::ok();
2198}
2199
Eric Laurent81784c32012-11-19 14:55:58 -08002200// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002201#undef LOG_TAG
2202#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002203
Andy Hung8d31fd22023-06-26 19:20:57 -07002204/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002205sp<IAfOutputTrack> IAfOutputTrack::create(
2206 IAfPlaybackThread* playbackThread,
2207 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002208 uint32_t sampleRate,
2209 audio_format_t format,
2210 audio_channel_mask_t channelMask,
2211 size_t frameCount,
2212 const AttributionSourceState& attributionSource) {
2213 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002214 playbackThread,
2215 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002216 sampleRate,
2217 format,
2218 channelMask,
2219 frameCount,
2220 attributionSource);
2221}
2222
2223OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002224 IAfPlaybackThread* playbackThread,
2225 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002226 uint32_t sampleRate,
2227 audio_format_t format,
2228 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002229 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002230 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002231 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Andy Hung6b137d12024-08-27 22:35:17 +00002232 AUDIO_ATTRIBUTES_INITIALIZER ,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002233 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002234 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002235 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002236 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002237 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002238{
Eric Laurent81784c32012-11-19 14:55:58 -08002239 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002240 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002241 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002242 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002243 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002244 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002245 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002246 // since client and server are in the same process,
2247 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002248 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2249 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002250 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002251 mClientProxy->setSendLevel(0.0);
2252 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002253 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002254 ALOGW("%s(%d): Error creating output track on thread %d",
2255 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002256 }
2257}
2258
Andy Hung8d31fd22023-06-26 19:20:57 -07002259OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002260{
2261 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002262 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002263}
2264
Andy Hung8d31fd22023-06-26 19:20:57 -07002265status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002266 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002267{
2268 status_t status = Track::start(event, triggerSession);
2269 if (status != NO_ERROR) {
2270 return status;
2271 }
2272
2273 mActive = true;
2274 mRetryCount = 127;
2275 return status;
2276}
2277
Andy Hung8d31fd22023-06-26 19:20:57 -07002278void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002279{
2280 Track::stop();
2281 clearBufferQueue();
2282 mOutBuffer.frameCount = 0;
2283 mActive = false;
2284}
2285
Andy Hung8d31fd22023-06-26 19:20:57 -07002286ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002287{
Eric Laurent19952e12023-04-20 10:08:29 +02002288 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002289 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002290 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002291 // preload one silent buffer to trigger mixer on start()
2292 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2293 status_t status = mClientProxy->obtainBuffer(&buf);
2294 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2295 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2296 return 0;
2297 }
2298 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2299 mClientProxy->releaseBuffer(&buf);
2300
2301 (void) start();
2302
2303 // wait for HAL stream to start before sending actual audio. Doing this on each
2304 // OutputTrack makes that playback start on all output streams is synchronized.
2305 // If another OutputTrack has already started it can underrun but this is OK
2306 // as only silence has been played so far and the retry count is very high on
2307 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002308 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002309 if (!pt->waitForHalStart()) {
2310 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2311 stop();
2312 return 0;
2313 }
2314
2315 // enqueue the first buffer and exit so that other OutputTracks will also start before
2316 // write() is called again and this buffer actually consumed.
2317 Buffer firstBuffer;
2318 firstBuffer.frameCount = frames;
2319 firstBuffer.raw = data;
2320 queueBuffer(firstBuffer);
2321 return frames;
2322 } else {
2323 (void) start();
2324 }
2325 }
2326
Eric Laurent81784c32012-11-19 14:55:58 -08002327 Buffer *pInBuffer;
2328 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002329 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002330 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002331 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002332 while (waitTimeLeftMs) {
2333 // First write pending buffers, then new data
2334 if (mBufferQueue.size()) {
2335 pInBuffer = mBufferQueue.itemAt(0);
2336 } else {
2337 pInBuffer = &inBuffer;
2338 }
2339
2340 if (pInBuffer->frameCount == 0) {
2341 break;
2342 }
2343
2344 if (mOutBuffer.frameCount == 0) {
2345 mOutBuffer.frameCount = pInBuffer->frameCount;
2346 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002347 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002348 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002349 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2350 __func__, mId,
2351 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002352 break;
2353 }
2354 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2355 if (waitTimeLeftMs >= waitTimeMs) {
2356 waitTimeLeftMs -= waitTimeMs;
2357 } else {
2358 waitTimeLeftMs = 0;
2359 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002360 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002361 deferRestartIfDisabled();
Eric Laurent4d231dc2016-03-11 18:38:23 -08002362 continue;
2363 }
Eric Laurent81784c32012-11-19 14:55:58 -08002364 }
2365
2366 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2367 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002368 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002369 Proxy::Buffer buf;
2370 buf.mFrameCount = outFrames;
2371 buf.mRaw = NULL;
2372 mClientProxy->releaseBuffer(&buf);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002373 deferRestartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002374 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002375 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002376 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002377 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002378
2379 if (pInBuffer->frameCount == 0) {
2380 if (mBufferQueue.size()) {
2381 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002382 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002383 if (pInBuffer != &inBuffer) {
2384 delete pInBuffer;
2385 }
Andy Hung9d84af52018-09-12 18:03:44 -07002386 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2387 __func__, mId,
2388 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002389 } else {
2390 break;
2391 }
2392 }
2393 }
2394
2395 // If we could not write all frames, allocate a buffer and queue it for next time.
2396 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002397 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002398 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002399 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002400 }
2401 }
2402
Andy Hungc25b84a2015-01-14 19:04:10 -08002403 // Calling write() with a 0 length buffer means that no more data will be written:
2404 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2405 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2406 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002407 }
2408
Andy Hung1c86ebe2018-05-29 20:29:08 -07002409 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002410}
2411
Andy Hung8d31fd22023-06-26 19:20:57 -07002412void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002413
2414 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2415 Buffer *pInBuffer = new Buffer;
2416 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2417 pInBuffer->mBuffer = malloc(bufferSize);
2418 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2419 "%s: Unable to malloc size %zu", __func__, bufferSize);
2420 pInBuffer->frameCount = inBuffer.frameCount;
2421 pInBuffer->raw = pInBuffer->mBuffer;
2422 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2423 mBufferQueue.add(pInBuffer);
2424 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2425 (int)mThreadIoHandle, mBufferQueue.size());
2426 // audio data is consumed (stored locally); set frameCount to 0.
2427 inBuffer.frameCount = 0;
2428 } else {
2429 ALOGW("%s(%d): thread %d no more overflow buffers",
2430 __func__, mId, (int)mThreadIoHandle);
2431 // TODO: return error for this.
2432 }
2433}
2434
Andy Hung8d31fd22023-06-26 19:20:57 -07002435void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002436{
Andy Hungc5007f82023-08-29 14:26:09 -07002437 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002438 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2439}
2440
Andy Hung8d31fd22023-06-26 19:20:57 -07002441void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002442 {
Andy Hungc5007f82023-08-29 14:26:09 -07002443 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002444 mTrackMetadatas = metadatas;
2445 }
2446 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2447 setMetadataHasChanged();
2448}
2449
Andy Hung8d31fd22023-06-26 19:20:57 -07002450status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002451 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2452{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002453 ClientProxy::Buffer buf;
2454 buf.mFrameCount = buffer->frameCount;
2455 struct timespec timeout;
2456 timeout.tv_sec = waitTimeMs / 1000;
2457 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2458 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2459 buffer->frameCount = buf.mFrameCount;
2460 buffer->raw = buf.mRaw;
2461 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002462}
2463
Andy Hung8d31fd22023-06-26 19:20:57 -07002464void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002465{
2466 size_t size = mBufferQueue.size();
2467
2468 for (size_t i = 0; i < size; i++) {
2469 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002470 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002471 delete pBuffer;
2472 }
2473 mBufferQueue.clear();
2474}
2475
Andy Hung8d31fd22023-06-26 19:20:57 -07002476void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002477{
2478 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2479 if (mActive && (flags & CBLK_DISABLED)) {
2480 start();
2481 }
2482}
Eric Laurent81784c32012-11-19 14:55:58 -08002483
Andy Hung9d84af52018-09-12 18:03:44 -07002484// ----------------------------------------------------------------------------
2485#undef LOG_TAG
2486#define LOG_TAG "AF::PatchTrack"
2487
Andy Hung8d31fd22023-06-26 19:20:57 -07002488/* static */
2489sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002490 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002491 audio_stream_type_t streamType,
2492 uint32_t sampleRate,
2493 audio_channel_mask_t channelMask,
2494 audio_format_t format,
2495 size_t frameCount,
2496 void* buffer,
2497 size_t bufferSize,
2498 audio_output_flags_t flags,
2499 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002500 size_t frameCountToBeReady, /** Default behaviour is to start
Andy Hung8d31fd22023-06-26 19:20:57 -07002501 * as soon as possible to have
2502 * the lowest possible latency
guonaichao3acc9b12024-06-07 09:27:21 +08002503 * even if it might glitch. */
Andy Hung6b137d12024-08-27 22:35:17 +00002504 float speed,
2505 float volume)
Andy Hung8d31fd22023-06-26 19:20:57 -07002506{
2507 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002508 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002509 streamType,
2510 sampleRate,
2511 channelMask,
2512 format,
2513 frameCount,
2514 buffer,
2515 bufferSize,
2516 flags,
2517 timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002518 frameCountToBeReady,
Andy Hung6b137d12024-08-27 22:35:17 +00002519 speed,
2520 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -07002521}
2522
Andy Hung87c693c2023-07-06 20:56:16 -07002523PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002524 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002525 uint32_t sampleRate,
2526 audio_channel_mask_t channelMask,
2527 audio_format_t format,
2528 size_t frameCount,
2529 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002530 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002531 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002532 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002533 size_t frameCountToBeReady,
Andy Hung6b137d12024-08-27 22:35:17 +00002534 float speed,
2535 float volume)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002536 : Track(playbackThread, NULL, streamType,
Andy Hung6b137d12024-08-27 22:35:17 +00002537 AUDIO_ATTRIBUTES_INITIALIZER,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002538 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002539 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002540 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Andy Hung6b137d12024-08-27 22:35:17 +00002541 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
2542 false /*isSpatialized*/, false /*isBitPerfect*/, volume),
guonaichao3acc9b12024-06-07 09:27:21 +08002543 PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
2544 true /*clientInServer*/) : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002545 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002546{
guonaichao3acc9b12024-06-07 09:27:21 +08002547 if (mProxy != nullptr) {
2548 sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
2549 /* .mSpeed = */ speed,
2550 /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
2551 /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
2552 /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
2553 });
2554 }
Andy Hung9d84af52018-09-12 18:03:44 -07002555 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2556 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002557 (int)mPeerTimeout.tv_sec,
2558 (int)(mPeerTimeout.tv_nsec / 1000000));
2559}
2560
Andy Hung8d31fd22023-06-26 19:20:57 -07002561PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002562{
Andy Hungabfab202019-03-07 19:45:54 -08002563 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002564}
2565
Andy Hung8d31fd22023-06-26 19:20:57 -07002566size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002567{
2568 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2569 return std::numeric_limits<size_t>::max();
2570 } else {
2571 return Track::framesReady();
2572 }
2573}
2574
Andy Hung8d31fd22023-06-26 19:20:57 -07002575status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002576 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002577{
2578 status_t status = Track::start(event, triggerSession);
2579 if (status != NO_ERROR) {
2580 return status;
2581 }
2582 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2583 return status;
2584}
2585
Eric Laurent83b88082014-06-20 18:31:16 -07002586// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002587status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002588 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002589{
Andy Hung9d84af52018-09-12 18:03:44 -07002590 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002591 Proxy::Buffer buf;
2592 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002593 if (ATRACE_ENABLED()) {
2594 std::string traceName("PTnReq");
2595 traceName += std::to_string(id());
2596 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2597 }
Eric Laurent83b88082014-06-20 18:31:16 -07002598 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002599 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002600 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002601 if (ATRACE_ENABLED()) {
2602 std::string traceName("PTnObt");
2603 traceName += std::to_string(id());
2604 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2605 }
Eric Laurent83b88082014-06-20 18:31:16 -07002606 if (buf.mFrameCount == 0) {
2607 return WOULD_BLOCK;
2608 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002609 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002610 return status;
2611}
2612
Andy Hung8d31fd22023-06-26 19:20:57 -07002613void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002614{
Andy Hung9d84af52018-09-12 18:03:44 -07002615 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002616 Proxy::Buffer buf;
2617 buf.mFrameCount = buffer->frameCount;
2618 buf.mRaw = buffer->raw;
2619 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002620 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002621}
2622
Andy Hung8d31fd22023-06-26 19:20:57 -07002623status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002624 const struct timespec *timeOut)
2625{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002626 status_t status = NO_ERROR;
2627 static const int32_t kMaxTries = 5;
2628 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002629 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002630 do {
2631 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002632 deferRestartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002633 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002634 }
2635 status = mProxy->obtainBuffer(buffer, timeOut);
2636 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2637 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002638}
2639
Andy Hung8d31fd22023-06-26 19:20:57 -07002640void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002641{
2642 mProxy->releaseBuffer(buffer);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002643 deferRestartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002644
2645 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2646 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2647 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2648 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002649 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002650 && audio_is_linear_pcm(mFormat)
2651 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002652 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002653 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002654 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002655 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2656 / playbackThread->sampleRate();
2657 if (framesReady() < frameCount) {
2658 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002659 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002660 }
2661 }
2662 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002663}
2664
Andy Hung8d31fd22023-06-26 19:20:57 -07002665void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002666{
Eric Laurent83b88082014-06-20 18:31:16 -07002667 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002668 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002669 start();
2670 }
Eric Laurent83b88082014-06-20 18:31:16 -07002671}
2672
Eric Laurent81784c32012-11-19 14:55:58 -08002673// ----------------------------------------------------------------------------
2674// Record
2675// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002676
2677
Andy Hung9d84af52018-09-12 18:03:44 -07002678#undef LOG_TAG
2679#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002680
Andy Hunga5a7fc92023-06-23 19:27:19 -07002681class RecordHandle : public android::media::BnAudioRecord {
2682public:
Andy Hungd29af632023-06-23 19:27:19 -07002683 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002684 ~RecordHandle() override;
2685 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2686 int /*audio_session_t*/ triggerSession) final;
2687 binder::Status stop() final;
2688 binder::Status getActiveMicrophones(
2689 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2690 binder::Status setPreferredMicrophoneDirection(
2691 int /*audio_microphone_direction_t*/ direction) final;
2692 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2693 binder::Status shareAudioHistory(
2694 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2695
2696private:
Andy Hungd29af632023-06-23 19:27:19 -07002697 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002698
2699 // for use from destructor
2700 void stop_nonvirtual();
2701};
2702
2703/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002704sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2705 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002706 return sp<RecordHandle>::make(recordTrack);
2707}
2708
2709RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002710 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002711 : BnAudioRecord(),
2712 mRecordTrack(recordTrack)
2713{
Andy Hung225aef62022-12-06 16:33:20 -08002714 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -07002715 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002716}
2717
Andy Hunga5a7fc92023-06-23 19:27:19 -07002718RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002719 stop_nonvirtual();
2720 mRecordTrack->destroy();
2721}
2722
Andy Hunga5a7fc92023-06-23 19:27:19 -07002723binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002724 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002725 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002726 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002727 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002728}
2729
Andy Hunga5a7fc92023-06-23 19:27:19 -07002730binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002731 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002732 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002733}
2734
Andy Hunga5a7fc92023-06-23 19:27:19 -07002735void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002736 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002737 mRecordTrack->stop();
2738}
2739
Andy Hunga5a7fc92023-06-23 19:27:19 -07002740binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002741 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002742 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002743 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002744}
2745
Andy Hunga5a7fc92023-06-23 19:27:19 -07002746binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002747 int /*audio_microphone_direction_t*/ direction) {
2748 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002749 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002750 static_cast<audio_microphone_direction_t>(direction)));
2751}
2752
Andy Hunga5a7fc92023-06-23 19:27:19 -07002753binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002754 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002755 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002756}
2757
Andy Hunga5a7fc92023-06-23 19:27:19 -07002758binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002759 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2760 return binderStatusFromStatusT(
2761 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2762}
2763
Eric Laurent81784c32012-11-19 14:55:58 -08002764// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002765#undef LOG_TAG
2766#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002767
Andy Hung8d31fd22023-06-26 19:20:57 -07002768
Andy Hung99b1ba62023-07-14 11:00:08 -07002769/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002770sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002771 const sp<Client>& client,
2772 const audio_attributes_t& attr,
2773 uint32_t sampleRate,
2774 audio_format_t format,
2775 audio_channel_mask_t channelMask,
2776 size_t frameCount,
2777 void* buffer,
2778 size_t bufferSize,
2779 audio_session_t sessionId,
2780 pid_t creatorPid,
2781 const AttributionSourceState& attributionSource,
2782 audio_input_flags_t flags,
2783 track_type type,
2784 audio_port_handle_t portId,
2785 int32_t startFrames)
2786{
2787 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002788 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002789 client,
2790 attr,
2791 sampleRate,
2792 format,
2793 channelMask,
2794 frameCount,
2795 buffer,
2796 bufferSize,
2797 sessionId,
2798 creatorPid,
2799 attributionSource,
2800 flags,
2801 type,
2802 portId,
2803 startFrames);
2804}
2805
Glenn Kasten05997e22014-03-13 15:08:33 -07002806// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002807RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002808 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002809 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002810 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002811 uint32_t sampleRate,
2812 audio_format_t format,
2813 audio_channel_mask_t channelMask,
2814 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002815 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002816 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002817 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002818 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002819 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002820 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002821 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002822 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002823 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002824 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002825 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002826 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002827 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002828 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002829 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002830 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002831 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002832 type, portId,
2833 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002834 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002835 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002836 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002837 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002838 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002839 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002840{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002841 if (mCblk == NULL) {
2842 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002843 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002844
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002845 if (!isDirect()) {
2846 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002847 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002848 channelMask, format, sampleRate);
2849 // Check if the RecordBufferConverter construction was successful.
2850 // If not, don't continue with construction.
2851 //
2852 // NOTE: It would be extremely rare that the record track cannot be created
2853 // for the current device, but a pending or future device change would make
2854 // the record track configuration valid.
2855 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002856 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002857 return;
2858 }
Andy Hung97a893e2015-03-29 01:03:07 -07002859 }
2860
Andy Hung6ae58432016-02-16 18:32:24 -08002861 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002862 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002863
Andy Hung97a893e2015-03-29 01:03:07 -07002864 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002865
Eric Laurent05067782016-06-01 18:27:28 -07002866 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002867 ALOG_ASSERT(thread->fastTrackAvailable());
2868 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002869 } else {
2870 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002871 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002872 }
Andy Hung8946a282018-04-19 20:04:56 -07002873#ifdef TEE_SINK
2874 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2875 + "_" + std::to_string(mId)
2876 + "_R");
2877#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002878
2879 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002880 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002881}
2882
Andy Hung8d31fd22023-06-26 19:20:57 -07002883RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002884{
Andy Hung9d84af52018-09-12 18:03:44 -07002885 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002886 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002887 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002888}
2889
Andy Hung8d31fd22023-06-26 19:20:57 -07002890status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002891{
2892 status_t status = TrackBase::initCheck();
2893 if (status == NO_ERROR && mServerProxy == 0) {
2894 status = BAD_VALUE;
2895 }
2896 return status;
2897}
2898
Eric Laurent81784c32012-11-19 14:55:58 -08002899// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002900status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002901{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002902 ServerProxy::Buffer buf;
2903 buf.mFrameCount = buffer->frameCount;
2904 status_t status = mServerProxy->obtainBuffer(&buf);
2905 buffer->frameCount = buf.mFrameCount;
2906 buffer->raw = buf.mRaw;
2907 if (buf.mFrameCount == 0) {
2908 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002909 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002910 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002911 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002912}
2913
Andy Hung8d31fd22023-06-26 19:20:57 -07002914status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002915 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002916{
Andy Hung87c693c2023-07-06 20:56:16 -07002917 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002918 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002919 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002920 return recordThread->start(this, event, triggerSession);
2921 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002922 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2923 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002924 }
2925}
2926
Andy Hung8d31fd22023-06-26 19:20:57 -07002927void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002928{
Andy Hung87c693c2023-07-06 20:56:16 -07002929 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002930 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002931 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002932 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002933 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002934 }
2935 }
2936}
2937
Andy Hung8d31fd22023-06-26 19:20:57 -07002938void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002939{
Andy Hung8d31fd22023-06-26 19:20:57 -07002940 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002941 sp<RecordTrack> keep(this);
2942 {
Andy Hungce685402018-10-05 17:23:27 -07002943 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002944 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002945 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002946 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002947 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002948 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002949 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002950 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002951 }
Andy Hungce685402018-10-05 17:23:27 -07002952 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2953 }
2954 // APM portid/client management done outside of lock.
2955 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2956 if (isExternalTrack()) {
2957 switch (priorState) {
2958 case ACTIVE: // invalidated while still active
2959 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2960 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2961 AudioSystem::stopInput(mPortId);
2962 break;
2963
2964 case STARTING_1: // invalidated/start-aborted and startInput not successful
2965 case PAUSED: // OK, not active
2966 case IDLE: // OK, not active
2967 break;
2968
2969 case STOPPED: // unexpected (destroyed)
2970 default:
2971 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2972 }
2973 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002974 }
2975 }
2976}
2977
Andy Hung8d31fd22023-06-26 19:20:57 -07002978void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002979{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002980 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002981 // FIXME should use proxy, and needs work
2982 audio_track_cblk_t* cblk = mCblk;
2983 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2984 android_atomic_release_store(0x40000000, &cblk->mFutex);
2985 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002986 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002987}
2988
Eric Laurent81784c32012-11-19 14:55:58 -08002989
Andy Hung8d31fd22023-06-26 19:20:57 -07002990void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002991{
Eric Laurent973db022018-11-20 14:54:31 -08002992 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002993 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002994 " Server FrmCnt FrmRdy Sil%s\n",
2995 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002996}
2997
Andy Hung8d31fd22023-06-26 19:20:57 -07002998void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002999{
Eric Laurent973db022018-11-20 14:54:31 -08003000 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003001 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07003002 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003003 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08003004 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07003005 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07003006 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003007 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003008 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08003009 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003010 mCblk->mFlags,
3011
Eric Laurent81784c32012-11-19 14:55:58 -08003012 mFormat,
3013 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003014 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003015 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08003016
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003017 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07003018 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07003019 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07003020 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003021 );
Andy Hung000adb52018-06-01 15:43:26 -07003022 if (isServerLatencySupported()) {
3023 double latencyMs;
3024 bool fromTrack;
3025 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
3026 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
3027 // or 'k' if estimated from kernel (usually for debugging).
3028 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
3029 } else {
3030 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
3031 }
3032 }
3033 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08003034}
3035
Andy Hung93bb5732023-05-04 21:16:34 -07003036// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07003037void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07003038 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003039{
Andy Hung93bb5732023-05-04 21:16:34 -07003040 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07003041 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07003042 if (threadBase != 0) {
3043 // TODO: use actual buffer filling status instead of 2 buffers when info is available
3044 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07003045 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003046 }
Andy Hung93bb5732023-05-04 21:16:34 -07003047
3048 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003049}
3050
Andy Hung8d31fd22023-06-26 19:20:57 -07003051void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003052{
Andy Hung93bb5732023-05-04 21:16:34 -07003053 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003054}
3055
Andy Hung8d31fd22023-06-26 19:20:57 -07003056void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08003057 int64_t trackFramesReleased, int64_t sourceFramesRead,
3058 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
3059{
Andy Hung30282562018-08-08 18:27:03 -07003060 // Make the kernel frametime available.
3061 const FrameTime ft{
3062 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3063 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3064 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3065 mKernelFrameTime.store(ft);
3066 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003067 // Stream is direct, return provided timestamp with no conversion
3068 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003069 return;
3070 }
3071
Andy Hung3f0c9022016-01-15 17:49:46 -08003072 ExtendedTimestamp local = timestamp;
3073
3074 // Convert HAL frames to server-side track frames at track sample rate.
3075 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3076 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3077 if (local.mTimeNs[i] != 0) {
3078 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3079 const int64_t relativeTrackFrames = relativeServerFrames
3080 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3081 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3082 }
3083 }
Andy Hung6ae58432016-02-16 18:32:24 -08003084 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003085
3086 // Compute latency info.
3087 const bool useTrackTimestamp = true; // use track unless debugging.
3088 const double latencyMs = - (useTrackTimestamp
3089 ? local.getOutputServerLatencyMs(sampleRate())
3090 : timestamp.getOutputServerLatencyMs(halSampleRate));
3091
3092 mServerLatencyFromTrack.store(useTrackTimestamp);
3093 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003094}
Eric Laurent83b88082014-06-20 18:31:16 -07003095
Andy Hung8d31fd22023-06-26 19:20:57 -07003096status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003097 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003098{
Andy Hung87c693c2023-07-06 20:56:16 -07003099 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003100 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003101 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003102 return recordThread->getActiveMicrophones(activeMicrophones);
3103 } else {
3104 return BAD_VALUE;
3105 }
3106}
3107
Andy Hung8d31fd22023-06-26 19:20:57 -07003108status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003109 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003110 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003111 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003112 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003113 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003114 } else {
3115 return BAD_VALUE;
3116 }
3117}
3118
Andy Hung8d31fd22023-06-26 19:20:57 -07003119status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003120 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003121 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003122 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003123 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003124 } else {
3125 return BAD_VALUE;
3126 }
3127}
3128
Andy Hung8d31fd22023-06-26 19:20:57 -07003129status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003130 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3131
3132 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3133 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3134 if (callingUid != mUid || callingPid != mCreatorPid) {
3135 return PERMISSION_DENIED;
3136 }
3137
Svet Ganov33761132021-05-13 22:51:08 +00003138 AttributionSourceState attributionSource{};
3139 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3140 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3141 attributionSource.token = sp<BBinder>::make();
3142 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003143 return PERMISSION_DENIED;
3144 }
3145
Andy Hung87c693c2023-07-06 20:56:16 -07003146 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003147 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003148 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003149 status_t status = recordThread->shareAudioHistory(
3150 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3151 if (status == NO_ERROR) {
3152 mSharedAudioPackageName = sharedAudioPackageName;
3153 }
3154 return status;
3155 } else {
3156 return BAD_VALUE;
3157 }
3158}
3159
Andy Hung8d31fd22023-06-26 19:20:57 -07003160void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003161{
3162
3163 // Do not forward PatchRecord metadata with unspecified audio source
3164 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3165 return;
3166 }
3167
3168 // No track is invalid as this is called after prepareTrack_l in the same critical section
3169 record_track_metadata_v7_t metadata;
3170 metadata.base = {
3171 .source = mAttr.source,
3172 .gain = 1, // capture tracks do not have volumes
3173 };
3174 metadata.channel_mask = mChannelMask;
3175 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3176
3177 *backInserter++ = metadata;
3178}
Eric Laurentec376dc2021-04-08 20:41:22 +02003179
Andy Hung9d84af52018-09-12 18:03:44 -07003180// ----------------------------------------------------------------------------
3181#undef LOG_TAG
3182#define LOG_TAG "AF::PatchRecord"
3183
Andy Hung8d31fd22023-06-26 19:20:57 -07003184/* static */
3185sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003186 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003187 uint32_t sampleRate,
3188 audio_channel_mask_t channelMask,
3189 audio_format_t format,
3190 size_t frameCount,
3191 void *buffer,
3192 size_t bufferSize,
3193 audio_input_flags_t flags,
3194 const Timeout& timeout,
3195 audio_source_t source)
3196{
3197 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003198 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003199 sampleRate,
3200 channelMask,
3201 format,
3202 frameCount,
3203 buffer,
3204 bufferSize,
3205 flags,
3206 timeout,
3207 source);
3208}
3209
Andy Hung87c693c2023-07-06 20:56:16 -07003210PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003211 uint32_t sampleRate,
3212 audio_channel_mask_t channelMask,
3213 audio_format_t format,
3214 size_t frameCount,
3215 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003216 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003217 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003218 const Timeout& timeout,
3219 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003220 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003221 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003222 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003223 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003224 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003225 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3226 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003227 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003228{
Andy Hung9d84af52018-09-12 18:03:44 -07003229 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3230 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003231 (int)mPeerTimeout.tv_sec,
3232 (int)(mPeerTimeout.tv_nsec / 1000000));
3233}
3234
Andy Hung8d31fd22023-06-26 19:20:57 -07003235PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003236{
Andy Hungabfab202019-03-07 19:45:54 -08003237 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003238}
3239
Mikhail Naganov8296c252019-09-25 14:59:54 -07003240static size_t writeFramesHelper(
3241 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3242{
3243 AudioBufferProvider::Buffer patchBuffer;
3244 patchBuffer.frameCount = frameCount;
3245 auto status = dest->getNextBuffer(&patchBuffer);
3246 if (status != NO_ERROR) {
3247 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3248 __func__, status, strerror(-status));
3249 return 0;
3250 }
3251 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3252 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3253 size_t framesWritten = patchBuffer.frameCount;
3254 dest->releaseBuffer(&patchBuffer);
3255 return framesWritten;
3256}
3257
3258// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003259size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003260 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3261{
3262 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3263 // On buffer wrap, the buffer frame count will be less than requested,
3264 // when this happens a second buffer needs to be used to write the leftover audio
3265 const size_t framesLeft = frameCount - framesWritten;
3266 if (framesWritten != 0 && framesLeft != 0) {
3267 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3268 framesLeft, frameSize);
3269 }
3270 return framesWritten;
3271}
3272
Eric Laurent83b88082014-06-20 18:31:16 -07003273// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003274status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003275 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003276{
Andy Hung9d84af52018-09-12 18:03:44 -07003277 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003278 Proxy::Buffer buf;
3279 buf.mFrameCount = buffer->frameCount;
3280 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3281 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003282 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003283 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003284 if (ATRACE_ENABLED()) {
3285 std::string traceName("PRnObt");
3286 traceName += std::to_string(id());
3287 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3288 }
Eric Laurent83b88082014-06-20 18:31:16 -07003289 if (buf.mFrameCount == 0) {
3290 return WOULD_BLOCK;
3291 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003292 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003293 return status;
3294}
3295
Andy Hung8d31fd22023-06-26 19:20:57 -07003296void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003297{
Andy Hung9d84af52018-09-12 18:03:44 -07003298 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003299 Proxy::Buffer buf;
3300 buf.mFrameCount = buffer->frameCount;
3301 buf.mRaw = buffer->raw;
3302 mPeerProxy->releaseBuffer(&buf);
3303 TrackBase::releaseBuffer(buffer);
3304}
3305
Andy Hung8d31fd22023-06-26 19:20:57 -07003306status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003307 const struct timespec *timeOut)
3308{
3309 return mProxy->obtainBuffer(buffer, timeOut);
3310}
3311
Andy Hung8d31fd22023-06-26 19:20:57 -07003312void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003313{
3314 mProxy->releaseBuffer(buffer);
3315}
3316
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003317#undef LOG_TAG
3318#define LOG_TAG "AF::PthrPatchRecord"
3319
3320static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3321{
3322 void *ptr = nullptr;
3323 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003324 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003325}
3326
Andy Hung8d31fd22023-06-26 19:20:57 -07003327/* static */
3328sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003329 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003330 uint32_t sampleRate,
3331 audio_channel_mask_t channelMask,
3332 audio_format_t format,
3333 size_t frameCount,
3334 audio_input_flags_t flags,
3335 audio_source_t source)
3336{
3337 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003338 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003339 sampleRate,
3340 channelMask,
3341 format,
3342 frameCount,
3343 flags,
3344 source);
3345}
3346
3347PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003348 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003349 uint32_t sampleRate,
3350 audio_channel_mask_t channelMask,
3351 audio_format_t format,
3352 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003353 audio_input_flags_t flags,
3354 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003355 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003356 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003357 mPatchRecordAudioBufferProvider(*this),
3358 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3359 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3360{
3361 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3362}
3363
Andy Hung8d31fd22023-06-26 19:20:57 -07003364sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003365 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003366{
3367 *thread = mThread.promote();
3368 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003369 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003370 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003371 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003372}
3373
3374// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003375status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003376 Proxy::Buffer* buffer, const struct timespec* timeOut)
3377{
3378 if (mUnconsumedFrames) {
3379 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3380 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3381 return PatchRecord::obtainBuffer(buffer, timeOut);
3382 }
3383
3384 // Otherwise, execute a read from HAL and write into the buffer.
3385 nsecs_t startTimeNs = 0;
3386 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3387 // Will need to correct timeOut by elapsed time.
3388 startTimeNs = systemTime();
3389 }
3390 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3391 buffer->mFrameCount = 0;
3392 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003393 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003394 sp<StreamInHalInterface> stream = obtainStream(&thread);
3395 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3396
3397 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003398 size_t bytesRead = 0;
3399 {
3400 ATRACE_NAME("read");
3401 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3402 if (result != NO_ERROR) goto stream_error;
3403 if (bytesRead == 0) return NO_ERROR;
3404 }
3405
3406 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003407 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003408 mReadBytes += bytesRead;
3409 mReadError = NO_ERROR;
3410 }
3411 mReadCV.notify_one();
3412 // writeFrames handles wraparound and should write all the provided frames.
3413 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3414 buffer->mFrameCount = writeFrames(
3415 &mPatchRecordAudioBufferProvider,
3416 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3417 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3418 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3419 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003420 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003421 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003422 // Correct the timeout by elapsed time.
3423 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003424 if (newTimeOutNs < 0) newTimeOutNs = 0;
3425 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3426 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003427 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003428 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003429 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003430
3431stream_error:
3432 stream->standby();
3433 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003434 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003435 mReadError = result;
3436 }
3437 mReadCV.notify_one();
3438 return result;
3439}
3440
Andy Hung8d31fd22023-06-26 19:20:57 -07003441void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003442{
3443 if (buffer->mFrameCount <= mUnconsumedFrames) {
3444 mUnconsumedFrames -= buffer->mFrameCount;
3445 } else {
3446 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3447 buffer->mFrameCount, mUnconsumedFrames);
3448 mUnconsumedFrames = 0;
3449 }
3450 PatchRecord::releaseBuffer(buffer);
3451}
3452
3453// AudioBufferProvider and Source methods are called on RecordThread
3454// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3455// and 'releaseBuffer' are stubbed out and ignore their input.
3456// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3457// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003458status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003459 void* buffer, size_t bytes, size_t* read)
3460{
3461 bytes = std::min(bytes, mFrameCount * mFrameSize);
3462 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003463 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003464 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3465 if (mReadError != NO_ERROR) {
3466 mLastReadFrames = 0;
3467 return mReadError;
3468 }
3469 *read = std::min(bytes, mReadBytes);
3470 mReadBytes -= *read;
3471 }
3472 mLastReadFrames = *read / mFrameSize;
3473 memset(buffer, 0, *read);
3474 return 0;
3475}
3476
Andy Hung8d31fd22023-06-26 19:20:57 -07003477status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003478 int64_t* frames, int64_t* time)
3479{
Andy Hung87c693c2023-07-06 20:56:16 -07003480 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003481 sp<StreamInHalInterface> stream = obtainStream(&thread);
3482 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3483}
3484
Andy Hung8d31fd22023-06-26 19:20:57 -07003485status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003486{
3487 // RecordThread issues 'standby' command in two major cases:
3488 // 1. Error on read--this case is handled in 'obtainBuffer'.
3489 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3490 // output, this can only happen when the software patch
3491 // is being torn down. In this case, the RecordThread
3492 // will terminate and close the HAL stream.
3493 return 0;
3494}
3495
3496// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003497status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003498 AudioBufferProvider::Buffer* buffer)
3499{
3500 buffer->frameCount = mLastReadFrames;
3501 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3502 return NO_ERROR;
3503}
3504
Andy Hung8d31fd22023-06-26 19:20:57 -07003505void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003506 AudioBufferProvider::Buffer* buffer)
3507{
3508 buffer->frameCount = 0;
3509 buffer->raw = nullptr;
3510}
3511
Andy Hung9d84af52018-09-12 18:03:44 -07003512// ----------------------------------------------------------------------------
3513#undef LOG_TAG
3514#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515
Andy Hung8d31fd22023-06-26 19:20:57 -07003516/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003517sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003518 const audio_attributes_t& attr,
3519 uint32_t sampleRate,
3520 audio_format_t format,
3521 audio_channel_mask_t channelMask,
3522 audio_session_t sessionId,
3523 bool isOut,
3524 const android::content::AttributionSourceState& attributionSource,
3525 pid_t creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003526 audio_port_handle_t portId,
3527 float volume)
Andy Hung8d31fd22023-06-26 19:20:57 -07003528{
3529 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003530 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003531 attr,
3532 sampleRate,
3533 format,
3534 channelMask,
3535 sessionId,
3536 isOut,
3537 attributionSource,
3538 creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003539 portId,
3540 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -07003541}
3542
Andy Hung87c693c2023-07-06 20:56:16 -07003543MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003544 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003545 uint32_t sampleRate,
3546 audio_format_t format,
3547 audio_channel_mask_t channelMask,
3548 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003549 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003550 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003551 pid_t creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003552 audio_port_handle_t portId,
3553 float volume)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003554 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003555 channelMask, (size_t)0 /* frameCount */,
3556 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003557 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003558 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003559 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003560 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003561 TYPE_DEFAULT, portId,
3562 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003563 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Andy Hung6b137d12024-08-27 22:35:17 +00003564 mSilenced(false), mSilencedNotified(false), mVolume(volume)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003565{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003566 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003567 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Andy Hung6b137d12024-08-27 22:35:17 +00003568 if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
3569 || attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
3570 // Audio patch and call assistant volume are always max
3571 mVolume = 1.0f;
3572 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08003573}
3574
Andy Hung8d31fd22023-06-26 19:20:57 -07003575MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003576{
3577}
3578
Andy Hung8d31fd22023-06-26 19:20:57 -07003579status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003580{
3581 return NO_ERROR;
3582}
3583
Andy Hung8d31fd22023-06-26 19:20:57 -07003584status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003585 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003586{
3587 return NO_ERROR;
3588}
3589
Andy Hung8d31fd22023-06-26 19:20:57 -07003590void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003591{
3592}
3593
3594// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003595status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003596{
3597 buffer->frameCount = 0;
3598 buffer->raw = nullptr;
3599 return INVALID_OPERATION;
3600}
3601
3602// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003603size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003604 return 0;
3605}
3606
Andy Hung8d31fd22023-06-26 19:20:57 -07003607int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003608{
3609 return 0;
3610}
3611
Andy Hung8d31fd22023-06-26 19:20:57 -07003612void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003613{
3614}
3615
Andy Hung8d31fd22023-06-26 19:20:57 -07003616void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003617{
3618 if (mMuteState == muteState) {
3619 // mute state did not change, do nothing
3620 return;
3621 }
3622
3623 status_t result = UNKNOWN_ERROR;
3624 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3625 if (mMuteEventExtras == nullptr) {
3626 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3627 }
3628 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3629 static_cast<int>(muteState));
3630
3631 result = audioManager->portEvent(mPortId,
3632 PLAYER_UPDATE_MUTED,
3633 mMuteEventExtras);
3634 }
3635
3636 if (result == OK) {
Andy Hung0e26ec62024-02-20 16:32:57 -08003637 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3638 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003639 mMuteState = muteState;
3640 } else {
3641 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3642 __func__,
3643 id(),
3644 mPortId,
3645 result);
3646 }
3647}
3648
Andy Hung8d31fd22023-06-26 19:20:57 -07003649void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003650{
Andy Hung6b137d12024-08-27 22:35:17 +00003651 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s %s\n",
3652 isOut() ? "Usg CT": "Source", isOut() ? "PortVol dB" : "");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003653}
3654
Andy Hung8d31fd22023-06-26 19:20:57 -07003655void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003656{
Eric Laurent973db022018-11-20 14:54:31 -08003657 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003658 mPid,
3659 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003660 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003661 mFormat,
3662 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003663 mSampleRate,
3664 mAttr.flags);
3665 if (isOut()) {
3666 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
Andy Hung6b137d12024-08-27 22:35:17 +00003667 result.appendFormat("%11.2g", 20.0 * log10(mVolume));
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003668 } else {
3669 result.appendFormat("%6x", mAttr.source);
3670 }
3671 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003672}
3673
Glenn Kasten63238ef2015-03-02 15:50:29 -08003674} // namespace android